[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Client (please complete the following information):**\n - OS: [e.g. Windows 8.1]\n - VNC client: [e.g. TigerVNC, or UltraVNC]\n - VNC client version: [e.g. 1.8.0]\n - Client downloaded from: [e.g. my Linux distribution]\n\n**Server (please complete the following information):**\n - OS: [e.g. Windows 8.1]\n - VNC server: [e.g. TigerVNC, or UltraVNC]\n - VNC server version: [e.g. 1.8.0]\n - Server downloaded from: [e.g. my Linux distribution]\n - Server was started using: [e.g. `vncserver`]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Usage question or discussion\n    url: https://groups.google.com/forum/#!forum/tigervnc-users\n    about: Ask a question or start a discussion on how to use TigerVNC\n  - name: Development question or discussion\n    url: https://groups.google.com/forum/#!forum/tigervnc-devel\n    about: Ask a question or start a discussion about TigerVNC's code\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/containers/jammy/Dockerfile",
    "content": "FROM ubuntu:jammy\n\nARG DEBIAN_FRONTEND=noninteractive\n\nRUN apt-get update\nRUN apt-get -y install packaging-dev equivs\n\nRUN useradd -s /bin/bash -m deb\nRUN echo >> /etc/sudoers\nRUN echo \"deb ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers\n\nUSER deb\nWORKDIR /home/deb\n"
  },
  {
    "path": ".github/containers/jammy/build.sh",
    "content": "#!/bin/bash\n\nset -e\nset -x\n\n## Basic variables\n\nCURDIR=$(dirname $(readlink -f $0))\nTOPDIR=$(git rev-parse --show-toplevel 2>/dev/null)\n\nDEBDIR=${TOPDIR}/contrib/packages/deb/ubuntu-jammy\n\nVERSION=$(grep '^set(VERSION ' ${TOPDIR}/CMakeLists.txt | sed 's@^set(VERSION \\(.*\\))@\\1@')\n\n## Prepare the build directory\n\nrm -rf ${CURDIR}/build\nmkdir -p ${CURDIR}/build\nchmod a+w ${CURDIR}/build\n[ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled && chcon -Rt container_file_t ${CURDIR}/build\n\n## Copy over the source code\n\n(cd ${TOPDIR} && git archive --prefix tigervnc-${VERSION}/ HEAD) | xz > ${CURDIR}/build/tigervnc_${VERSION}.orig.tar.xz\n\n## Copy over the packaging files\n\ncp -r ${DEBDIR}/debian ${CURDIR}/build/debian\n\nchmod a+x ${CURDIR}/build/debian/rules\n\n# Assemble a fake changelog entry to get the correct version\n\ncat - > ${CURDIR}/build/debian/changelog << EOT\ntigervnc (${VERSION}-1ubuntu1) UNRELEASED; urgency=low\n\n  * Automated build for TigerVNC\n\n -- Build bot <tigervncbot@tigervnc.org>  $(date -R)\n\nEOT\ncat ${DEBDIR}/debian/changelog >> ${CURDIR}/build/debian/changelog\n\n## Start the build\n\ndocker run --volume ${CURDIR}/build:/home/deb/build --interactive --rm tigervnc/${DOCKER} \\\n\tbash -e -x -c \"\n\ttar -C ~/build -axf ~/build/tigervnc_${VERSION}.orig.tar.xz\n\tcp -a ~/build/debian ~/build/tigervnc-${VERSION}/debian\n\tsudo apt-get update\n\tmk-build-deps ~/build/tigervnc-${VERSION}/debian/control\n\tsudo DEBIAN_FRONTEND=noninteractive \\\n\t    apt-get install -y ~/tigervnc-build-deps_*.deb\n\tcd ~/build/tigervnc-${VERSION} && dpkg-buildpackage\n\t\"\n\nmkdir -p ${CURDIR}/result\ncp -av ${CURDIR}/build/*.deb ${CURDIR}/result\ncp -av ${CURDIR}/build/*.ddeb ${CURDIR}/result\n"
  },
  {
    "path": ".github/containers/noble/Dockerfile",
    "content": "FROM ubuntu:noble\n\nARG DEBIAN_FRONTEND=noninteractive\n\nRUN apt-get update\nRUN apt-get -y install packaging-dev equivs\n\nRUN useradd -s /bin/bash -m deb\nRUN echo >> /etc/sudoers\nRUN echo \"deb ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers\n\nUSER deb\nWORKDIR /home/deb\n"
  },
  {
    "path": ".github/containers/noble/build.sh",
    "content": "#!/bin/bash\n\nset -e\nset -x\n\n## Basic variables\n\nCURDIR=$(dirname $(readlink -f $0))\nTOPDIR=$(git rev-parse --show-toplevel 2>/dev/null)\n\nDEBDIR=${TOPDIR}/contrib/packages/deb/ubuntu-noble\n\nVERSION=$(grep '^set(VERSION ' ${TOPDIR}/CMakeLists.txt | sed 's@^set(VERSION \\(.*\\))@\\1@')\n\n## Prepare the build directory\n\nrm -rf ${CURDIR}/build\nmkdir -p ${CURDIR}/build\nchmod a+w ${CURDIR}/build\n[ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled && chcon -Rt container_file_t ${CURDIR}/build\n\n## Copy over the source code\n\n(cd ${TOPDIR} && git archive --prefix tigervnc-${VERSION}/ HEAD) | xz > ${CURDIR}/build/tigervnc_${VERSION}.orig.tar.xz\n\n## Copy over the packaging files\n\ncp -r ${DEBDIR}/debian ${CURDIR}/build/debian\n\nchmod a+x ${CURDIR}/build/debian/rules\n\n# Assemble a fake changelog entry to get the correct version\n\ncat - > ${CURDIR}/build/debian/changelog << EOT\ntigervnc (${VERSION}-1ubuntu1) UNRELEASED; urgency=low\n\n  * Automated build for TigerVNC\n\n -- Build bot <tigervncbot@tigervnc.org>  $(date -R)\n\nEOT\ncat ${DEBDIR}/debian/changelog >> ${CURDIR}/build/debian/changelog\n\n## Start the build\n\ndocker run --volume ${CURDIR}/build:/home/deb/build --interactive --rm tigervnc/${DOCKER} \\\n\tbash -e -x -c \"\n\ttar -C ~/build -axf ~/build/tigervnc_${VERSION}.orig.tar.xz\n\tcp -a ~/build/debian ~/build/tigervnc-${VERSION}/debian\n\tsudo apt-get update\n\tmk-build-deps ~/build/tigervnc-${VERSION}/debian/control\n\tsudo DEBIAN_FRONTEND=noninteractive \\\n\t    apt-get install -y ~/tigervnc-build-deps_*.deb\n\tcd ~/build/tigervnc-${VERSION} && dpkg-buildpackage\n\t\"\n\nmkdir -p ${CURDIR}/result\ncp -av ${CURDIR}/build/*.deb ${CURDIR}/result\ncp -av ${CURDIR}/build/*.ddeb ${CURDIR}/result\n"
  },
  {
    "path": ".github/containers/rocky10/Dockerfile",
    "content": "FROM rockylinux/rockylinux:10\n\nRUN dnf -y group install 'Development Tools'\nRUN dnf -y install dnf-plugins-core sudo\nRUN dnf config-manager --set-enabled crb\nRUN dnf -y install epel-release\n\nRUN useradd -s /bin/bash -m rpm\nRUN echo >> /etc/sudoers\nRUN echo \"rpm ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers\n\nUSER rpm\nWORKDIR /home/rpm\n"
  },
  {
    "path": ".github/containers/rocky10/build.sh",
    "content": "#!/bin/bash\n\nset -e\nset -x\n\n## Basic variables\n\nCURDIR=$(dirname $(readlink -f $0))\nTOPDIR=$(git rev-parse --show-toplevel 2>/dev/null)\n\nRPMDIR=${TOPDIR}/contrib/packages/rpm/el10\n\nVERSION=$(grep '^set(VERSION ' ${TOPDIR}/CMakeLists.txt | sed 's@^set(VERSION \\(.*\\))@\\1@')\n\n## Prepare the build directory\n\nrm -rf ${CURDIR}/rpmbuild\nmkdir -p ${CURDIR}/rpmbuild/{BUILD,BUILDROOT,SRPMS,SOURCES,SPECS,RPMS}\nchmod a+w ${CURDIR}/rpmbuild/{BUILD,BUILDROOT,SRPMS,RPMS}\n[ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled && chcon -Rt container_file_t ${CURDIR}/rpmbuild\n\n## Copy over the packaging files\n\ncp ${RPMDIR}/SOURCES/* ${CURDIR}/rpmbuild/SOURCES\ncp ${RPMDIR}/SPECS/tigervnc.spec ${CURDIR}/rpmbuild/SPECS\nsed -i \"s/@VERSION@/${VERSION}/\" ${CURDIR}/rpmbuild/SPECS/tigervnc.spec\n\n## Copy over the source code\n\n(cd ${TOPDIR} && git archive --prefix tigervnc-${VERSION}/ HEAD) | bzip2 > ${CURDIR}/rpmbuild/SOURCES/tigervnc-${VERSION}.tar.bz2\n\n## Download the xorg-server source code\n\ncurl -L https://xorg.freedesktop.org/releases/individual/xserver/xorg-server-21.1.18.tar.xz > ${CURDIR}/rpmbuild/SOURCES/xorg-server-21.1.18.tar.xz\n\n## Start the build\n\ndocker run --volume ${CURDIR}/rpmbuild:/home/rpm/rpmbuild --interactive --rm tigervnc/${DOCKER} \\\n\tbash -e -x -c \"\n\tsudo dnf builddep -y ~/rpmbuild/SPECS/tigervnc.spec\n\tsudo chown 0.0 ~/rpmbuild/SOURCES/*\n\tsudo chown 0.0 ~/rpmbuild/SPECS/*\n\trpmbuild -ba ~/rpmbuild/SPECS/tigervnc.spec\n\t\"\n\nmkdir -p ${CURDIR}/result\ncp -av ${CURDIR}/rpmbuild/RPMS ${CURDIR}/result\ncp -av ${CURDIR}/rpmbuild/SRPMS ${CURDIR}/result\n"
  },
  {
    "path": ".github/containers/rocky8/Dockerfile",
    "content": "FROM rockylinux/rockylinux:8\n\nRUN dnf -y group install 'Development Tools'\nRUN dnf -y install sudo\nRUN dnf -y install dnf-plugins-core\nRUN dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm\nRUN dnf config-manager --set-enabled powertools\n\nRUN useradd -s /bin/bash -m rpm\nRUN echo >> /etc/sudoers\nRUN echo \"rpm ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers\n\nUSER rpm\nWORKDIR /home/rpm\n"
  },
  {
    "path": ".github/containers/rocky8/build.sh",
    "content": "#!/bin/bash\n\nset -e\nset -x\n\n## Basic variables\n\nCURDIR=$(dirname $(readlink -f $0))\nTOPDIR=$(git rev-parse --show-toplevel 2>/dev/null)\n\nRPMDIR=${TOPDIR}/contrib/packages/rpm/el8\n\nVERSION=$(grep '^set(VERSION ' ${TOPDIR}/CMakeLists.txt | sed 's@^set(VERSION \\(.*\\))@\\1@')\n\n## Prepare the build directory\n\nrm -rf ${CURDIR}/rpmbuild\nmkdir -p ${CURDIR}/rpmbuild/{BUILD,BUILDROOT,SRPMS,SOURCES,SPECS,RPMS}\nchmod a+w ${CURDIR}/rpmbuild/{BUILD,BUILDROOT,SRPMS,RPMS}\n[ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled && chcon -Rt container_file_t ${CURDIR}/rpmbuild\n\n## Copy over the packaging files\n\ncp ${RPMDIR}/SOURCES/* ${CURDIR}/rpmbuild/SOURCES\ncp ${RPMDIR}/SPECS/tigervnc.spec ${CURDIR}/rpmbuild/SPECS\nsed -i \"s/@VERSION@/${VERSION}/\" ${CURDIR}/rpmbuild/SPECS/tigervnc.spec\n\n## Copy over the source code\n\n(cd ${TOPDIR} && git archive --prefix tigervnc-${VERSION}/ HEAD) | bzip2 > ${CURDIR}/rpmbuild/SOURCES/tigervnc-${VERSION}.tar.bz2\n\n## Start the build\n\ndocker run --volume ${CURDIR}/rpmbuild:/home/rpm/rpmbuild --interactive --rm tigervnc/${DOCKER} \\\n\tbash -e -x -c \"\n\tsudo dnf install -y xorg-x11-server-devel\n\tsudo dnf builddep -y ~/rpmbuild/SPECS/tigervnc.spec\n\tsudo chown 0.0 ~/rpmbuild/SOURCES/*\n\tsudo chown 0.0 ~/rpmbuild/SPECS/*\n\trpmbuild -ba ~/rpmbuild/SPECS/tigervnc.spec\n\t\"\n\nmkdir -p ${CURDIR}/result\ncp -av ${CURDIR}/rpmbuild/RPMS ${CURDIR}/result\ncp -av ${CURDIR}/rpmbuild/SRPMS ${CURDIR}/result\n"
  },
  {
    "path": ".github/containers/rocky9/Dockerfile",
    "content": "FROM rockylinux/rockylinux:9\n\nRUN dnf -y group install 'Development Tools'\nRUN dnf -y install dnf-plugins-core sudo\nRUN dnf config-manager --set-enabled crb\n\nRUN useradd -s /bin/bash -m rpm\nRUN echo >> /etc/sudoers\nRUN echo \"rpm ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers\n\nUSER rpm\nWORKDIR /home/rpm\n"
  },
  {
    "path": ".github/containers/rocky9/build.sh",
    "content": "#!/bin/bash\n\nset -e\nset -x\n\n## Basic variables\n\nCURDIR=$(dirname $(readlink -f $0))\nTOPDIR=$(git rev-parse --show-toplevel 2>/dev/null)\n\nRPMDIR=${TOPDIR}/contrib/packages/rpm/el9\n\nVERSION=$(grep '^set(VERSION ' ${TOPDIR}/CMakeLists.txt | sed 's@^set(VERSION \\(.*\\))@\\1@')\n\n## Prepare the build directory\n\nrm -rf ${CURDIR}/rpmbuild\nmkdir -p ${CURDIR}/rpmbuild/{BUILD,BUILDROOT,SRPMS,SOURCES,SPECS,RPMS}\nchmod a+w ${CURDIR}/rpmbuild/{BUILD,BUILDROOT,SRPMS,RPMS}\n[ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled && chcon -Rt container_file_t ${CURDIR}/rpmbuild\n\n## Copy over the packaging files\n\ncp ${RPMDIR}/SOURCES/* ${CURDIR}/rpmbuild/SOURCES\ncp ${RPMDIR}/SPECS/tigervnc.spec ${CURDIR}/rpmbuild/SPECS\nsed -i \"s/@VERSION@/${VERSION}/\" ${CURDIR}/rpmbuild/SPECS/tigervnc.spec\n\n## Copy over the source code\n\n(cd ${TOPDIR} && git archive --prefix tigervnc-${VERSION}/ HEAD) | bzip2 > ${CURDIR}/rpmbuild/SOURCES/tigervnc-${VERSION}.tar.bz2\n\n## Start the build\n\ndocker run --volume ${CURDIR}/rpmbuild:/home/rpm/rpmbuild --interactive --rm tigervnc/${DOCKER} \\\n\tbash -e -x -c \"\n\tsudo dnf install -y xorg-x11-server-devel\n\tsudo dnf builddep -y ~/rpmbuild/SPECS/tigervnc.spec\n\tsudo chown 0.0 ~/rpmbuild/SOURCES/*\n\tsudo chown 0.0 ~/rpmbuild/SPECS/*\n\trpmbuild -ba ~/rpmbuild/SPECS/tigervnc.spec\n\t\"\n\nmkdir -p ${CURDIR}/result\ncp -av ${CURDIR}/rpmbuild/RPMS ${CURDIR}/result\ncp -av ${CURDIR}/rpmbuild/SRPMS ${CURDIR}/result\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build\n\non: [push, pull_request]\n\njobs:\n  build-linux:\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n    env:\n      VERBOSE: 1\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install -y libfltk1.3-dev fluid gettext appstream\n          sudo apt-get install -y libpixman-1-dev libjpeg-turbo8-dev\n          sudo apt-get install -y libgnutls28-dev nettle-dev libgmp-dev\n          sudo apt-get install -y libxtst-dev libxdamage-dev libxfixes-dev libxrandr-dev libpam-dev\n          sudo apt-get install -y libavcodec-dev libavutil-dev libswscale-dev\n          sudo apt-get install -y uuid-dev libglib2.0-dev libpipewire-0.3-dev\n          sudo apt-get install -y libwayland-dev libxkbcommon-dev\n          sudo apt-get install -y libgtest-dev\n      - name: Configure\n        run: |\n          cmake \\\n            -DCMAKE_BUILD_TYPE=Debug \\\n            -DENABLE_NLS=ON \\\n            -DENABLE_H264=ON \\\n            -DENABLE_GNUTLS=ON \\\n            -DENABLE_NETTLE=ON \\\n            -DBUILD_VIEWER=ON \\\n            -S . -B build\n      - name: Build\n        working-directory: build\n        run: make\n      - name: Install\n        working-directory: build\n        run: make tarball\n      - uses: actions/upload-artifact@v4\n        with:\n          name: Linux (Ubuntu)\n          path: build/tigervnc-*.tar.gz\n      - name: Test\n        working-directory: build\n        run: ctest --test-dir tests/unit/ --output-junit test-results.xml\n      - name: Upload test results\n        uses: actions/upload-artifact@v4\n        if: always()\n        with:\n          name: test-results-linux\n          path: build/tests/unit/test-results.xml\n\n  build-windows:\n    runs-on: windows-latest\n    timeout-minutes: 20\n    env:\n      VERBOSE: 1\n    defaults:\n      run:\n        shell: msys2 {0}\n    steps:\n      - uses: actions/checkout@v4\n      - uses: msys2/setup-msys2@v2\n        with:\n          update: true\n      - name: Install dependencies\n        run: |\n          pacman --sync --noconfirm --needed \\\n            make mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake\n          pacman --sync --noconfirm --needed \\\n            mingw-w64-x86_64-fltk1.3 mingw-w64-x86_64-libjpeg-turbo \\\n            mingw-w64-x86_64-gnutls mingw-w64-x86_64-pixman \\\n            mingw-w64-x86_64-nettle mingw-w64-x86_64-gmp \\\n            mingw-w64-x86_64-gtest\n      - name: Configure\n        run: |\n          cmake \\\n            -G \"MSYS Makefiles\" \\\n            -DCMAKE_BUILD_TYPE=Debug \\\n            -DENABLE_NLS=ON \\\n            -DENABLE_H264=ON \\\n            -DENABLE_GNUTLS=ON \\\n            -DENABLE_NETTLE=ON \\\n            -DBUILD_VIEWER=ON \\\n            -S . -B build\n      - name: Build\n        working-directory: build\n        run: make\n      - name: Install\n        working-directory: build\n        env:\n          MSYS2_PATH_TYPE: inherit\n        run: make installer winvnc_installer\n      - uses: actions/upload-artifact@v4\n        with:\n          name: Windows\n          path: build/release/tigervnc*.exe\n      - name: Test\n        working-directory: build\n        run: ctest --test-dir tests/unit/ --output-junit test-results.xml\n      - name: Upload test results\n        uses: actions/upload-artifact@v4\n        if: always()\n        with:\n          name: test-results-windows\n          path: build/tests/unit/test-results.xml\n\n  build-macos:\n    runs-on: macos-latest\n    timeout-minutes: 20\n    env:\n      VERBOSE: 1\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install dependencies\n        run: |\n          brew install fltk@1.3 pixman ffmpeg\n          brew install gnutls nettle gmp\n          brew install googletest\n          brew link fltk@1.3\n      - name: Configure\n        run: |\n          cmake \\\n            -DCMAKE_BUILD_TYPE=Debug \\\n            -DENABLE_NLS=ON \\\n            -DENABLE_H264=ON \\\n            -DENABLE_GNUTLS=ON \\\n            -DENABLE_NETTLE=ON \\\n            -DENABLE_WAYLAND=ON \\\n            -DBUILD_VIEWER=ON \\\n            -S . -B build\n      - name: Build\n        working-directory: build\n        run: make\n      - name: Install\n        working-directory: build\n        run: make dmg\n      - uses: actions/upload-artifact@v4\n        with:\n          name: macOS\n          path: build/release/TigerVNC-*.dmg\n      - name: Test\n        working-directory: build\n        run: ctest --test-dir tests/unit/ --output-junit test-results.xml\n      - name: Upload test results\n        uses: actions/upload-artifact@v4\n        if: always()\n        with:\n          name: test-results-macos\n          path: build/tests/unit/test-results.xml\n\n  build-java:\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    env:\n      VERBOSE: 1\n    strategy:\n      matrix:\n        java: [ '8', '11', '17', '21' ]\n    steps:\n      - uses: actions/checkout@v4\n      - name: Setup java\n        uses: actions/setup-java@v4\n        with:\n          distribution: 'temurin'\n          java-version: ${{ matrix.java }}\n      - name: Configure\n        working-directory: java\n        run: cmake -DCMAKE_BUILD_TYPE=Debug -S . -B build\n      - name: Build\n        working-directory: java/build\n        run: make\n      - uses: actions/upload-artifact@v4\n        with:\n          name: Java (${{ matrix.java }})\n          path: java/build/VncViewer.jar\n\n  build-packages:\n    timeout-minutes: 20\n    strategy:\n      matrix:\n        target:\n          - rocky8\n          - rocky9\n          - rocky10\n          - jammy\n          - noble\n      fail-fast: false\n    runs-on: ubuntu-latest\n    env:\n      DOCKER: ${{ matrix.target }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Build image\n        run: docker build -t tigervnc/$DOCKER .github/containers/$DOCKER\n      - name: Build packages\n        run: .github/containers/$DOCKER/build.sh\n      - uses: actions/upload-artifact@v4\n        with:\n          name: Packages (${{ matrix.target }})\n          path: .github/containers/${{ matrix.target }}/result\n"
  },
  {
    "path": ".github/workflows/test-report.yml",
    "content": "name: Test report\n\non:\n  workflow_run:\n    workflows: ['build']\n    types:\n      - completed\n\njobs:\n  report:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: dorny/test-reporter@v1\n        with:\n          artifact: /test-results-(.*)/\n          name: Unit tests ($1)\n          path: '*.xml'\n          reporter: java-junit\n"
  },
  {
    "path": ".gitignore",
    "content": "*.[ao]\n*.mo\n*.la\n*.lo\n.deps\n.libs\n\nCMakeFiles\nCMakeCache.txt\nMakefile\nMakefile.in\nconfig.h\ncmake_install.cmake\ncmake_uninstall.cmake\ninstall_manifest.txt\n"
  },
  {
    "path": "BUILDING.txt",
    "content": "*******************************************************************************\n**     Building TigerVNC\n*******************************************************************************\n\n\n================================\nBuild requirements (all systems)\n================================\n\n-- CMake (http://www.cmake.org) v3.10 or later\n\n-- gcc\n\nDevelopment kits for the following packages:\n\n-- zlib\n\n-- pixman\n\n-- FLTK 1.3.3 or later\n\n-- If building TLS support:\n   * GnuTLS 3.x\n   * See \"Building TLS Support\" below.\n\n-- If building RSA-AES support:\n   * Nettle 3.0 or later\n\n-- If building native language support (NLS):\n   * Gnu gettext 0.14.4 or later\n   * See \"Building Native Language Support\" below.\n\n-- libjpeg-turbo\n   * \"Normal\" libjpegv6 is also supported, although it is not\n     recommended as it is much slower.\n\n\n=========================\nBuild requirements (Unix)\n=========================\n\n-- Non-Mac platforms:\n   * Development kits for all standard X11 libraries\n   * PAM\n\n-- If building Xvnc/libvnc.so:\n   * Xorg server source code, 1.20 or later\n   * All build requirements Xorg imposes (see its documentation)\n   * patch\n\n-- If building x0vncserver with socket activation support:\n   * libsystemd\n\n-- If building w0vncserver:\n   * GLib (Gio + GObject)\n   * libpipewire\n   * libuuuid\n   * libwayland-client\n   * libxkbcommon\n\n-- Optional ffmpeg development kit support (libav)\n   * You might have to enable additional repositories for this. E.g.,\n     on RHEL, EPEL and RPMFusion (free + nonfree) need to be enabled.\n\n-- If building vncpasswd with password quality check support:\n   * libpwquality\n\n============================\nBuild requirements (Windows)\n============================\n\n-- MinGW or MinGW-w64\n\n-- Inno Setup (needed to build the TigerVNC installer)\n   Inno Setup can be downloaded from http://www.jrsoftware.org/isinfo.php.\n   You also need the Inno Setup Preprocessor, which is available in the\n   Inno Setup QuickStart Pack.\n\n   Add the directory containing iscc.exe (for instance, \n   C:\\Program Files\\Inno Setup 5) to the system or user PATH environment\n   variable prior to building TigerVNC.\n\n\n=========================\nBuild requirements (Java)\n=========================\n\n-- Sun/Oracle JDK 1.7 or later or OpenJDK 7 or later\n\n-- See \"Building Java support\" below.\n\n\n==================\nOut-of-tree builds\n==================\n\nBinary objects, libraries, and executables are generated in the same directory\nfrom which cmake was executed (the \"binary directory\"), and this directory need\nnot necessarily be the same as the TigerVNC source directory.  You can create\nmultiple independent binary directories, in which different versions of\nTigerVNC can be built from the same source tree using different compilers or\nsettings.  In the sections below, {build_directory} refers to the binary\ndirectory, whereas {source_directory} refers to the TigerVNC source directory.\nFor in-tree builds, these directories are the same.\n\n\n=================\nBuilding TigerVNC\n=================\n\n\nBuilding the TigerVNC viewer on Unix/Mac systems\n------------------------------------------------\n\nThe following procedure will build the TigerVNC viewer on Linux and Unix\nsystems.\n\n  cd {build_directory}\n  cmake -G \"Unix Makefiles\" [additional CMake flags] {source_directory}\n  make\n\n\nBuilding the TigerVNC server on Unix/Linux systems\n--------------------------------------------------\n\nBuilding the TigerVNC server (Xvnc) is a bit trickier. Xvnc is typically built\nto use the X11 shared libraries provided with the system.  The procedure for\nthis is system-specific, since it requires specifying such things as font\ndirectories, but the general outline is as follows (this procedure assumes\nthat the viewer has already been built, per above.)\n\n  > cd {build_directory}\n\n    If performing an out-of-tree build:\n  > cp -R {source_directory}/unix/xserver unix/\n\n  > cp -R {xorg_source}/* unix/xserver/\n    (NOTE: {xorg_source} is the directory containing the Xorg source for the\n    machine on which you are building TigerVNC.  The most recent versions of\n    Red Hat/CentOS/Fedora, for instance, provide an RPM called\n    \"xorg-x11-server-source\", which installs the Xorg source under\n    /usr/share/xorg-x11-server-source.)\n\n  > cd unix/xserver/\n  > patch -p1 < {source_directory}/unix/xserver{version}.patch\n    (where {version} matches the X server version you are building, such as\n    \"120\" for version 1.20.x.)\n  > autoreconf -fiv\n\n  > ./configure --with-pic --without-dtrace --disable-static --disable-dri \\\n      --disable-xinerama --disable-xvfb --disable-xnest --disable-xorg \\\n      --disable-dmx --disable-xwin --disable-xephyr --disable-kdrive \\\n      --disable-config-hal --disable-config-udev --disable-dri2 --enable-glx \\\n      --with-default-font-path=\"catalogue:/etc/X11/fontpath.d,built-ins\" \\\n      --with-xkb-path=/usr/share/X11/xkb \\\n      --with-xkb-output=/var/lib/xkb \\\n      --with-xkb-bin-directory=/usr/bin \\\n      --with-serverconfig-path=/usr/lib64/xorg \\\n      {additional configure options}\n    (NOTE: This is merely an example that works with Red Hat Enterprise/CentOS\n    9 and recent Fedora releases.  You should customize it for your particular\n    system.  In particular, it will be necessary to customize the XKB\n    directory.)\n\n    For a regular, in-tree build:\n  > make TIGERVNC_SRCDIR={source_directory}\n    If performing an out-of-tree build:\n  > make TIGERVNC_SRCDIR={source_directory} TIGERVNC_BUILDDIR={build_directory}\n    (NOTE: Use absolute paths for source_directory and build_directory)\n\n\nBuilding the Windows TigerVNC viewer with MinGW\n-----------------------------------------------\n\nIf building the Windows version of TigerVNC on a Windows build system, use\nthe following procedure.\n\n  cd {build_directory}\n  cmake -G \"MSYS Makefiles\" [additional CMake flags] {source_directory}\n  make\n\nIf cross-compiling on a Unix/Linux system, then see the \"Build Recipes\" section\nbelow.\n\n\nDebug build\n-----------\n\nAdd \"-DCMAKE_BUILD_TYPE=Debug\" to the CMake command line.\n\n\nPortable (semi-static) build\n----------------------------\n\nTigerVNC can under favourble circumstances be built in a way that allows\nthe resulting binaries to run on any system without having to also install\nall the dynamic libraries it depends on. Enable this mode by adding:\n\n  -DBUILD_STATIC=1\n\nto the CMake command line.\n\nNote that the method used to achieve this is very fragile and it may be\nnecessary to tweak cmake/StaticBuild.cmake to make things work on your\nspecific system.\n\n\n=====================\nBuilding Java support\n=====================\n\nTigerVNC includes a Java version of the TigerVNC Viewer, which can be used on\nany platform that has a Java Runtime Environment (JRE) installed.  The Java\nviewer works similarly to the native viewer, but with lower performance.\n\nTo build the Java TigerVNC Viewer, add\n\n  -DBUILD_JAVA=1\n\nto the CMake or build-xorg command line.  The build system will attempt to find\nan installed Java Development Kit (JDK) and determine the appropriate paths for\nthe Java compiler (javac) and the JAR creation utility (jar).  You can override\nthese paths by setting the Java_JAVAC_EXECUTABLE and Java_JAR_EXECUTABLE CMake\nvariables.  You can also override the default flags that are passed to javac\nby setting the JAVACFLAGS CMake variable.  The build system will look for\nkeytool and jarsigner in the same directory as Java_JAR_EXECUTABLE.  These\ntools are needed to sign the JAR file, which is necessary to enable certain\nfunctionality (such as clipboard transfers) when the Java viewer is used as an\napplet.\n\nIf the Java viewer is built along with the Windows TigerVNC server (WinVNC),\nthen the build system will embed the Java viewer into WinVNC4.exe so that it\nwill automatically be served up using WinVNC's built-in HTTP server.\nSimilarly, if the Java viewer is built along with the Unix TigerVNC server\n(Xvnc), then the build system will include the Java viewer in the server\ntarball.\n\nBy default, a self-signed certificate will be generated and used to sign the\njar file.  By specifying the following command line arguments to the CMake\ncommand line, an alternate certificate may be used for signing.\n\n  -DJAVA_KEYSTORE=${keystore_location_or_url}\n  -DJAVA_KEYSTORE_TYPE=${keystore_type} (Default: \"jks\")\n  -DJAVA_KEY_ALIAS=${keytore_key_alias}\n  -DJAVA_STOREPASS=${keystore_password}\n  -DJAVA_KEYPASS=${keystore_entry_password}\n  -DJAVA_TSA_URL=${url_of_timestamping_authority}\n\nThe values of the JAVA_STOREPASS and JAVA_KEYPASS arguments may optionally be\nread from file or environment variables by prefixing the value with \":env \" \nor \":file \" (see the jarsigner documentation for more info): \n\n  export StorePass=tigervnc\n  export KeyPass=tigervnc\n  cmake \\\n    ...\n    -DJAVA_STOREPASS=\":env StorePass\"\n    -DJAVA_KEYPASS=\":env KeyPass\"\n\n\n======================================\nBuilding TLS support\n======================================\n\nTLS requires GnuTLS, which is supplied with most Linux distributions and\nwith MinGW for Windows and can be built from source on OS X and other \nUnix variants. However, GnuTLS versions > 2.12.x && < 3.3.x should be\navoided because of potential incompatibilities during initial handshaking.\n\n\n======================================\nBuilding native language support (NLS)\n======================================\n\nNLS requires gettext, which is supplied with most Linux distributions and\nwith MinGW for Windows and which can easily be built from source on OS X and\nother Unix variants.\n\n\n===================\nInstalling TigerVNC\n===================\n\nYou can use the build system to install TigerVNC into a directory of your\nchoosing.  To do this, add:\n\n  -DCMAKE_INSTALL_PREFIX={install_directory}\n\nto the CMake command line.  Then, you can run 'make install' to build and\ninstall it.\n\nIf you don't specify CMAKE_INSTALL_PREFIX, then the default is\nc:\\Program Files\\TigerVNC on Windows and /usr/local on Unix.\n\n\n=========================\nCreating release packages\n=========================\n\nThe following commands can be used to create various types of release packages:\n\n\nUnix\n----\n\nmake tarball\n\n  Create a binary tarball containing the TigerVNC viewer\n\n\nmacOS\n-----\n\nmake dmg\n\n  Create Macintosh disk image file that contains an application bundle of the\n  TigerVNC viewer\n\n\nWindows\n-------\n\nmake installer\n\n  Create a Windows installer using Inno Setup.  The installer package\n  (TigerVNC[64].exe) will be located under {build_directory}.\n\n\n=============\nBuild recipes\n=============\n\n\nMinGW build on Cygwin\n---------------------\n\n  cd {build_directory}\n  CC=/usr/bin/x86_64-w64-mingw32-gcc CXX=/usr/bin/x86_64-w64-mingw32-g++ \\\n    RC=/usr/bin/x86_64-w64-mingw32-windres \\\n    cmake -G \"Unix Makefiles\" -DCMAKE_SYSTEM_NAME=Windows \\\n    -DCMAKE_AR=/usr/bin/x86_64-w64-mingw32-ar \\\n    -DCMAKE_RANLIB=/usr/bin/x86_64-w64-mingw32-ranlib {source_directory}\n  make\n\nThis produces a build of TigerVNC that does not depend on cygwin1.dll or\nother Cygwin DLL's.  The mingw64-x86_64-gcc-core and mingw64-x86_64-gcc-g++\npackages (and their dependencies) must be installed.\n\n\nMinGW-w64 build on Windows\n--------------------------\n\nThis produces a build of TigerVNC using the \"native\" MinGW-w64 toolchain\n(which is faster than the Cygwin version):\n\n  cd {build_directory}\n  CC={mingw-w64_binary_path}/x86_64-w64-mingw32-gcc \\\n    CXX={mingw-w64_binary_path}/x86_64-w64-mingw32-g++ \\\n    RC={mingw-w64_binary_path}/x86_64-w64-mingw32-windres \\\n    cmake -G \"MSYS Makefiles\" \\\n    -DCMAKE_AR={mingw-w64_binary_path}/x86_64-w64-mingw32-ar \\\n    -DCMAKE_RANLIB={mingw-w64_binary_path}/x86_64-w64-mingw32-ranlib \\\n    {source_directory}\n  make\n\n\nMinGW build on Linux\n--------------------\n\n  cd {build_directory}\n  CC={mingw_binary_path}/x86_64-w64-mingw32-gcc \\\n    CXX={mingw_binary_path}/x86_64-w64-mingw32-g++ \\\n    RC={mingw_binary_path}/x86_64-w64-mingw32-windres \\\n    cmake -G \"Unix Makefiles\" -DCMAKE_SYSTEM_NAME=Windows \\\n    -DCMAKE_AR={mingw_binary_path}/x86_64-w64-mingw32-ar \\\n    -DCMAKE_RANLIB={mingw_binary_path}/x86_64-w64-mingw32-ranlib \\\n    {source_directory}\n  make\n\n\n===============================\nDistribution-specific packaging\n===============================\n\nConfiguration for building packages for current versions of RHEL/CentOS\nand Ubuntu LTS can be found under contrib/packages.\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "#\n# Setup\n#\n\ncmake_minimum_required(VERSION 3.10.0)\n\n# Internal cmake modules\nset(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)\n\ninclude(CheckIncludeFiles)\ninclude(CheckFunctionExists)\ninclude(CheckLibraryExists)\ninclude(CheckVariableExists)\ninclude(CheckTypeSize)\ninclude(CheckCSourceCompiles)\ninclude(CheckCXXSourceCompiles)\ninclude(CheckCSourceRuns)\n\ninclude(CMakeMacroLibtoolFile)\n\nproject(tigervnc)\nset(VERSION 1.16.80)\n\n# The RC version must always be four comma-separated numbers\nstring(REPLACE . , RCVERSION \"${VERSION}.0\")\n\n# Installation paths\ninclude(GNUInstallDirs)\nset(CMAKE_INSTALL_UNITDIR \"lib/systemd/system\" CACHE PATH \"systemd unit files (lib/systemd/system)\")\nif(IS_ABSOLUTE \"${CMAKE_INSTALL_UNITDIR}\")\n  set(CMAKE_INSTALL_FULL_UNITDIR \"${CMAKE_INSTALL_UNITDIR}\")\nelse()\n  set(CMAKE_INSTALL_FULL_UNITDIR \"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_UNITDIR}\")\nendif()\n\noption(INSTALL_SYSTEMD_UNITS \"Install TigerVNC systemd units\" ON)\n\nif(MSVC)\n  message(FATAL_ERROR \"TigerVNC cannot be built with Visual Studio.  Please use MinGW\")\nendif()\n\nif(NOT BUILD_TIMESTAMP)\n  STRING(TIMESTAMP BUILD_TIMESTAMP \"%Y-%m-%d %H:%M\" UTC)\nendif()\n\n# Default to optimised builds instead of debug ones. Our code has no bugs ;)\n# (CMake makes it fairly easy to toggle this back to Debug if needed)\nif(NOT CMAKE_BUILD_TYPE)\n  set(CMAKE_BUILD_TYPE Release)\nendif()\n\nmessage(STATUS \"CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}\")\n\nmessage(STATUS \"VERSION = ${VERSION}\")\nmessage(STATUS \"BUILD_TIMESTAMP = ${BUILD_TIMESTAMP}\")\nadd_definitions(-DBUILD_TIMESTAMP=\"${BUILD_TIMESTAMP}\")\n\n# We want to keep our asserts even in release builds so remove NDEBUG\nset(CMAKE_C_FLAGS_RELEASE \"${CMAKE_C_FLAGS_RELEASE} -UNDEBUG\")\nset(CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE} -UNDEBUG\")\nset(CMAKE_C_FLAGS_RELWITHDEBINFO \"${CMAKE_C_FLAGS_RELWITHDEBINFO} -UNDEBUG\")\nset(CMAKE_CXX_FLAGS_RELWITHDEBINFO \"${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -UNDEBUG\")\nset(CMAKE_C_FLAGS_MINSIZEREL \"${CMAKE_C_FLAGS_MINSIZEREL} -UNDEBUG\")\nset(CMAKE_CXX_FLAGS_MINSIZEREL \"${CMAKE_CXX_FLAGS_MINSIZEREL} -UNDEBUG\")\n\n# But extra debug checks are still gated by this custom define\nset(CMAKE_C_FLAGS_DEBUG \"${CMAKE_C_FLAGS_DEBUG} -D_DEBUG\")\nset(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG\")\n\n# Enable debug friendly optimizations for debug builds\nset(CMAKE_C_FLAGS_DEBUG \"${CMAKE_C_FLAGS_DEBUG} -Og\")\nset(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -Og\")\n\n# Make sure we get a sane C and C++ version\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -std=gnu99\")\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=gnu++11\")\n\n# Tell the compiler to be stringent\nadd_compile_definitions(_FORTIFY_SOURCE=2)\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -Wall -Wextra -Wformat=2 -Wvla\")\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wall -Wextra -Wformat=2 -Wvla\")\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wzero-as-null-pointer-constant\")\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wsuggest-override\")\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wshadow\")\n# Make sure we catch these issues whilst developing\nset(CMAKE_C_FLAGS_DEBUG \"${CMAKE_C_FLAGS_DEBUG} -Werror\")\nset(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -Werror\")\n# clang doesn't support format_arg, which breaks this warning\nif (CMAKE_CXX_COMPILER_ID MATCHES \"Clang\")\n  set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -Wno-format-nonliteral -Wno-format-security\")\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wno-format-nonliteral -Wno-format-security\")\nendif()\n\noption(ENABLE_ASAN \"Enable address sanitizer support\" OFF)\nif(ENABLE_ASAN AND NOT WIN32 AND NOT APPLE)\n  set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -fsanitize=address\")\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -fsanitize=address\")\nendif()\n\noption(ENABLE_TSAN \"Enable thread sanitizer support\" OFF)\nif(ENABLE_TSAN AND NOT WIN32 AND NOT APPLE AND CMAKE_SIZEOF_VOID_P MATCHES 8)\n  set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -fsanitize=thread\")\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -fsanitize=thread\")\nendif()\n\nif(MSVC)\n  # undef min and max macro\n  target_compile_definitions(rfb PRIVATE NOMINMAX)\nendif()\n\nif(NOT DEFINED BUILD_WINVNC)\n  set(BUILD_WINVNC 1)\nendif()\n\n# libstdc++ doesn't implicitly include this, although it is very much\n# required when using any of the C++ threading features (at least on\n# systems where pthread is a separate library, e.g. glibc < 2.34)\nif(UNIX)\n  link_libraries(pthread)\nendif()\n\n# Minimum version is Windows 7\nif(WIN32)\n  add_definitions(-D_WIN32_WINNT=0x0601)\nendif()\n\n# Legacy macros (macOS 10.12 and older) conflict with our code\nif(APPLE)\n  add_definitions(-D__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0)\nendif()\n\n#### Check for required and optional libraries ####\n\nmacro(trioption VAR DESC)\n  set(${VAR} AUTO CACHE STRING \"${DESC}\")\n  set_property(CACHE ${VAR} PROPERTY STRINGS AUTO ON OFF)\nendmacro()\n\n# X11 stuff. It's in a if() so that we can say REQUIRED\nif(UNIX AND NOT APPLE)\n  find_package(X11 REQUIRED)\n  if(X11_Xdamage_LIB)\n    add_definitions(-DHAVE_XDAMAGE)\n  endif()\n  if(X11_Xfixes_LIB)\n    add_definitions(-DHAVE_XFIXES)\n  endif()\n  if(X11_Xrandr_LIB)\n    add_definitions(-DHAVE_XRANDR)\n  endif()\n  if(X11_XTest_LIB)\n    add_definitions(-DHAVE_XTEST)\n  endif()\nendif()\n\n# Check for zlib\nfind_package(ZLIB REQUIRED)\n\n# Check for pixman\nfind_package(Pixman REQUIRED)\n\n# Check for gettext\ntrioption(ENABLE_NLS \"Enable translation of program messages\")\nif(ENABLE_NLS)\n  # Tools\n  if(ENABLE_NLS STREQUAL \"AUTO\")\n    find_package(Gettext)\n  else()\n    find_package(Gettext REQUIRED)\n  endif()\n\n  # Runtime library\n  if(ENABLE_NLS STREQUAL \"AUTO\")\n    find_package(Intl)\n  else()\n    find_package(Intl REQUIRED)\n  endif()\n\n  if(NOT GETTEXT_FOUND OR NOT INTL_FOUND)\n    message(WARNING \"Gettext NOT found.  Native Language Support disabled.\")\n    set(ENABLE_NLS 0)\n  endif()\nendif()\n\ntrioption(ENABLE_H264 \"Enable H.264 RFB encoding\")\nif(ENABLE_H264)\n  if(WIN32)\n    add_definitions(\"-DHAVE_H264\")\n    set(H264_LIBS \"WIN\")  # may be LIBAV in the future\n    set(H264_LIBRARIES ole32 mfplat mfuuid wmcodecdspuuid)\n\n    set(CMAKE_REQUIRED_LIBRARIES ${H264_LIBRARIES})\n    check_variable_exists(CLSID_VideoProcessorMFT HAVE_VIDEO_PROCESSOR_MFT)\n    set(CMAKE_REQUIRED_LIBRARIES)\n    if(HAVE_VIDEO_PROCESSOR_MFT)\n      add_definitions(\"-DHAVE_VIDEO_PROCESSOR_MFT\")\n    endif()\n  else()\n    if(ENABLE_H264 STREQUAL \"AUTO\")\n      find_package(AVCodec)\n      find_package(AVUtil)\n      find_package(SWScale)\n    else()\n      find_package(AVCodec REQUIRED)\n      find_package(AVUtil REQUIRED)\n      find_package(SWScale REQUIRED)\n    endif()\n    if (AVCODEC_FOUND AND AVUTIL_FOUND AND SWSCALE_FOUND)\n      set(H264_INCLUDE_DIRS ${AVCODEC_INCLUDE_DIRS} ${AVUTIL_INCLUDE_DIRS} ${SWSCALE_INCLUDE_DIRS})\n      set(H264_LIBRARIES ${AVCODEC_LIBRARIES} ${AVUTIL_LIBRARIES} ${SWSCALE_LIBRARIES})\n      add_definitions(\"-D__STDC_CONSTANT_MACROS\")\n      add_definitions(\"-DHAVE_H264\")\n      set(H264_LIBS \"LIBAV\")\n    else()\n      set(H264_LIBS \"NONE\")\n      message(WARNING \"FFMPEG support can't be found\")\n    endif()\n  endif()\n  add_definitions(\"-DH264_${H264_LIBS}\")\nendif()\n\n# Check for libjpeg\nfind_package(JPEG REQUIRED)\n\n# Warn if it doesn't seem to be the accelerated libjpeg that's found\nset(CMAKE_REQUIRED_LIBRARIES ${JPEG_LIBRARIES})\nset(CMAKE_REQUIRED_FLAGS -I${JPEG_INCLUDE_DIR})\n\nset(JPEG_TEST_SOURCE \"\\n\n  #include <stdio.h>\\n\n  #include <jpeglib.h>\\n\n  int main(void) {\\n\n    struct jpeg_compress_struct cinfo;\\n\n    struct jpeg_error_mgr jerr;\\n\n    cinfo.err=jpeg_std_error(&jerr);\\n\n    jpeg_create_compress(&cinfo);\\n\n    cinfo.input_components = 3;\\n\n    jpeg_set_defaults(&cinfo);\\n\n    cinfo.in_color_space = JCS_EXT_RGB;\\n\n    jpeg_default_colorspace(&cinfo);\\n\n    return 0;\\n\n  }\")\n\nif(CMAKE_CROSSCOMPILING)\n  check_c_source_compiles(\"${JPEG_TEST_SOURCE}\" FOUND_LIBJPEG_TURBO)\nelse()\n  check_c_source_runs(\"${JPEG_TEST_SOURCE}\" FOUND_LIBJPEG_TURBO)\nendif()\n\nset(CMAKE_REQUIRED_LIBRARIES)\nset(CMAKE_REQUIRED_FLAGS)\nset(CMAKE_REQUIRED_DEFINITIONS)\n\nif(NOT FOUND_LIBJPEG_TURBO)\n  message(STATUS \"Warning: You are not using libjpeg-turbo. Performance will suffer.\")\nendif()\n\noption(BUILD_JAVA \"Build Java version of the TigerVNC Viewer\" FALSE)\nif(BUILD_JAVA)\n  add_subdirectory(java)\nendif()\n\ntrioption(BUILD_VIEWER \"Build TigerVNC viewer\")\nif(BUILD_VIEWER)\n  # Check for FLTK\n  set(FLTK_SKIP_FLUID TRUE)\n  set(FLTK_SKIP_OPENGL TRUE)\n  set(FLTK_SKIP_FORMS TRUE)\n  if(BUILD_VIEWER STREQUAL \"AUTO\")\n    find_package(FLTK)\n  else()\n    find_package(FLTK REQUIRED)\n  endif()\n\n  if(NOT FLTK_FOUND)\n    message(WARNING \"FLTK NOT found. TigerVNC viewer disabled.\")\n    set(BUILD_VIEWER 0)\n  endif()\n\n  if(UNIX AND NOT APPLE)\n    # No proper handling for extra X11 libs that FLTK might need...\n    if(X11_Xft_FOUND)\n      # Xft headers include references to fontconfig, so we need\n      # to link to that as well\n      find_library(FONTCONFIG_LIB fontconfig)\n      set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xft_LIB} ${FONTCONFIG_LIB})\n    endif()\n    if(X11_Xinerama_FOUND)\n      set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xinerama_LIB})\n    endif()\n    if(X11_Xfixes_FOUND)\n      set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xfixes_LIB})\n    endif()\n    if(X11_Xcursor_FOUND)\n      set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xcursor_LIB})\n    endif()\n    if(X11_Xrender_FOUND)\n      set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xrender_LIB})\n    endif()\n  endif()\n\n  if(FLTK_FOUND)\n    set(CMAKE_REQUIRED_FLAGS \"-Wno-error\")\n    set(CMAKE_REQUIRED_INCLUDES ${FLTK_INCLUDE_DIR})\n    set(CMAKE_REQUIRED_LIBRARIES ${FLTK_LIBRARIES})\n\n    check_cxx_source_compiles(\"#include <FL/Fl.H>\\n#if FL_MAJOR_VERSION != 1 || FL_MINOR_VERSION != 3\\n#error Wrong FLTK version\\n#endif\\nint main(int, char**) { return 0; }\" OK_FLTK_VERSION)\n    if(NOT OK_FLTK_VERSION)\n      message(FATAL_ERROR \"Incompatible version of FLTK\")\n    endif()\n\n    set(CMAKE_REQUIRED_FLAGS)\n    set(CMAKE_REQUIRED_INCLUDES)\n    set(CMAKE_REQUIRED_LIBRARIES)\n  endif()\nendif()\n\n# Check for GNUTLS library\ntrioption(ENABLE_GNUTLS \"Enable protocol encryption and advanced authentication\")\nif(ENABLE_GNUTLS)\n  if(ENABLE_GNUTLS STREQUAL \"AUTO\")\n    find_package(GnuTLS)\n  else()\n    find_package(GnuTLS REQUIRED)\n  endif()\n  if (GNUTLS_FOUND)\n    add_definitions(\"-DHAVE_GNUTLS\")\n  endif()\nendif()\n\ntrioption(ENABLE_NETTLE \"Enable RSA-AES security types\")\nif (ENABLE_NETTLE)\n  if(ENABLE_NETTLE STREQUAL \"AUTO\")\n    find_package(Nettle)\n  else()\n    find_package(Nettle REQUIRED)\n  endif()\n  if (NETTLE_FOUND)\n    add_definitions(\"-DHAVE_NETTLE\")\n  endif()\nendif()\n\n# Check for PAM library\nif(UNIX AND NOT APPLE)\n  find_package(PAM REQUIRED)\nendif()\n\n# Check for SELinux library\nif(UNIX AND NOT APPLE)\n  trioption(ENABLE_SELINUX \"Enable SELinux support\")\n  if(ENABLE_SELINUX)\n    if(ENABLE_SELINUX STREQUAL \"AUTO\")\n      find_package(SELinux)\n    else()\n      find_package(SELinux REQUIRED)\n    endif()\n    if(SELINUX_FOUND)\n      add_definitions(\"-DHAVE_SELINUX\")\n    endif()\n  endif()\nendif()\n\n# check for systemd support (socket activation)\nif(UNIX AND NOT APPLE)\n  trioption(ENABLE_SYSTEMD \"Enable systemd support\")\n  if(ENABLE_SYSTEMD)\n    if(ENABLE_SYSTEMD STREQUAL \"AUTO\")\n      find_package(Systemd)\n    else()\n      find_package(Systemd REQUIRED)\n    endif()\n    if (SYSTEMD_FOUND)\n      add_definitions(-DHAVE_LIBSYSTEMD)\n    endif()\n  endif()\nendif()\n\n# check for password pwquality check support\nif(UNIX AND NOT APPLE)\n  trioption(ENABLE_PWQUALITY \"Enable password pwquality check\")\n  if(ENABLE_PWQUALITY)\n    if(ENABLE_PWQUALITY STREQUAL \"AUTO\")\n      find_package(PWQuality)\n    else()\n      find_package(PWQuality REQUIRED)\n    endif()\n    if(PWQUALITY_FOUND)\n      add_definitions(-DHAVE_PWQUALITY)\n    endif()\n  endif()\nendif()\n\n# check for libraries needed for wayland support\nif(UNIX AND NOT APPLE)\n  trioption(ENABLE_WAYLAND \"Enable wayland support\")\n  if(ENABLE_WAYLAND)\n    if(ENABLE_WAYLAND STREQUAL \"AUTO\")\n      find_package(GLib)\n      find_package(Gio)\n      find_package(Gobject)\n\n      # Portals specific\n      find_package(PipeWire)\n      find_package(Uuid)\n\n      # wlroots specific\n      find_package(WaylandClient)\n      find_package(Xkbcommon)\n    else()\n      find_package(GLib REQUIRED)\n      find_package(Gio REQUIRED)\n      find_package(Gobject REQUIRED)\n\n      # Portals specific\n      find_package(PipeWire REQUIRED)\n      find_package(Uuid REQUIRED)\n\n      # wlroots specific\n      find_package(WaylandClient REQUIRED)\n      find_package(Xkbcommon REQUIRED)\n    endif()\n    if(NOT GLIB_FOUND OR NOT GIO_FOUND OR NOT GOBJECT_FOUND OR NOT PIPEWIRE_FOUND\n       OR NOT UUID_FOUND OR NOT WAYLANDCLIENT_FOUND OR NOT XKBCOMMON_FOUND)\n      set(ENABLE_WAYLAND 0)\n      message(WARNING \"GLib, Gio, Gobject, PipeWire, Uuid, WaylandClient or Xkbcommon NOT found. w0vncserver disabled.\")\n    endif()\n  endif()\nendif()\n\nfind_package(GTest)\n\n# Generate config.h and make sure the source finds it\nconfigure_file(config.h.in config.h)\nadd_definitions(-DHAVE_CONFIG_H)\ninclude_directories(${CMAKE_BINARY_DIR})\n\ninclude(cmake/StaticBuild.cmake)\n\nadd_subdirectory(common)\n\nif(WIN32)\n  add_subdirectory(win)\nelse()\n  # No interest in building x related parts on Apple\n  if(NOT APPLE)\n    add_subdirectory(unix)\n  endif()\nendif()\n\nif(ENABLE_NLS)\n  add_subdirectory(po)\nendif()\n\nif(BUILD_VIEWER)\n  add_subdirectory(vncviewer)\n  add_subdirectory(media)\nendif()\n\nadd_subdirectory(tests)\n\n\nif(BUILD_VIEWER)\n  add_subdirectory(release)\nendif()\n\n# uninstall\nconfigure_file(\"${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in\"\n  \"cmake_uninstall.cmake\" IMMEDIATE @ONLY)\n\nadd_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P cmake_uninstall.cmake)\n\nlibtool_generate_control_files()\n"
  },
  {
    "path": "LICENCE.TXT",
    "content": "\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 2, June 1991\n\n\t  Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n\t 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\t\t\t    Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Library General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\f\n\t\t    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\f\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\f\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\f\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n\t\t\t    NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n\t\t     END OF TERMS AND CONDITIONS\n\f\n\tAppendix: How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) 19yy  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n    USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) 19yy name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Library General\nPublic License instead of this License.\n"
  },
  {
    "path": "README.rst",
    "content": "About TigerVNC\n==============\n\nVirtual Network Computing (VNC) is a remote display system which allows you to\nview and interact with a virtual desktop environment that is running on another\ncomputer on the network.  Using VNC, you can run graphical applications on a\nremote machine and send only the display from these applications to your local\nmachine.  VNC is platform-independent and supports a wide variety of operating\nsystems and architectures as both servers and clients.\n\nTigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code\nbases.  TigerVNC started as a next-generation development effort for TightVNC\non Unix and Linux platforms, but it split from its parent project in early 2009\nso that TightVNC could focus on Windows platforms.  TigerVNC supports a variant\nof Tight encoding that is greatly accelerated by the use of the libjpeg-turbo\nJPEG codec.\n\n\nLegal\n=====\n\nIncomplete and generally out of date copyright list::\n\n        Copyright (C) 1999 AT&T Laboratories Cambridge\n        Copyright (C) 2002-2005 RealVNC Ltd.\n        Copyright (C) 2000-2006 TightVNC Group\n        Copyright (C) 2005-2006 Martin Koegler\n        Copyright (C) 2005-2006 Sun Microsystems, Inc.\n        Copyright (C) 2006 OCCAM Financial Technology\n        Copyright (C) 2000-2008 Constantin Kaplinsky\n        Copyright (C) 2004-2017 Peter Astrand for Cendio AB\n        Copyright (C) 2010 Antoine Martin\n        Copyright (C) 2010 m-privacy GmbH\n        Copyright (C) 2009-2011 D. R. Commander\n        Copyright (C) 2009-2011 Pierre Ossman for Cendio AB\n        Copyright (C) 2004, 2009-2011 Red Hat, Inc.\n        Copyright (C) 2009-2026 TigerVNC team\n        All Rights Reserved.\n\nThis software is distributed under the GNU General Public Licence as published\nby the Free Software Foundation.  See the file LICENCE.TXT for the conditions\nunder which this software is made available.  TigerVNC also contains code from\nother sources.  See the Acknowledgements section below, and the individual\nsource files, for details of the conditions under which they are made\navailable.\n\n\nAll Platforms\n=============\n\nAll versions of TigerVNC contain the following programs:\n\n* vncviewer - the cross-platform TigerVNC Viewer, written using FLTK.\n              vncviewer connects to a VNC server and allows you to interact\n              with the remote desktop being displayed by the VNC server.  The\n              VNC server can be running on a Windows or a Unix/Linux machine.\n\n\nWindows-specific\n================\n\nThe Windows version of TigerVNC contains the following programs:\n\n* winvnc - the TigerVNC server for Windows.  winvnc allows a Windows desktop to\n           be accessed remotely using a VNC viewer.\n\nWARNING: winvnc is currently unmaintained and and may not function correctly.\n\nwinvnc may not work if the Fast user switching or Remote desktop features are\nin use.\n\n\nUnix/Linux-specific (not Mac)\n=============================\n\nThe Unix/Linux version of TigerVNC contains the following programs:\n\n* Xvnc - the TigerVNC server for Unix.  Xvnc is both a VNC server and an X\n         server with a \"virtual\" framebuffer.  You should normally use the\n         vncserver service to start Xvnc.\n\n* vncpasswd - a program which allows you to change the VNC password used to\n              access your VNC server sessions (assuming that VNC authentication\n              is being used.) This command must be run to set a password before\n              using VNC authentication with any of the servers or services.\n\n* vncconfig - a program which is used to configure and control a running\n              instance of Xvnc.\n\n* x0vncserver - an inefficient VNC server which continuously polls any X\n                display, allowing it to be controlled via VNC.  It is intended\n                mainly as a demonstration of a simple VNC server.\n\n* w0vncserver - a VNC server for Wayland compositors which gives control\n                over your local Wayland session.\n\nIt also contains the following systemd service:\n\n* vncserver@.service - a service to start a user session with Xvnc and one of\n                       the desktop environments available on the system.\n\nACKNOWLEDGEMENTS\n================\n\nThis distribution contains public domain DES software by Richard Outerbridge.\nThis is:\n\n    Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.\n    (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.\n\n\nThis distribution contains software from the X Window System.  This is:\n\n Copyright 1987, 1988, 1998  The Open Group\n \n Permission to use, copy, modify, distribute, and sell this software and its\n documentation for any purpose is hereby granted without fee, provided that\n the above copyright notice appear in all copies and that both that\n copyright notice and this permission notice appear in supporting\n documentation.\n \n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\n OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\n AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n \n Except as contained in this notice, the name of The Open Group shall not be\n used in advertising or otherwise to promote the sale, use or other dealings\n in this Software without prior written authorization from The Open Group.\n \n \n Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.\n \n                         All Rights Reserved\n \n Permission to use, copy, modify, and distribute this software and its \n documentation for any purpose and without fee is hereby granted, \n provided that the above copyright notice appear in all copies and that\n both that copyright notice and this permission notice appear in \n supporting documentation, and that the name of Digital not be\n used in advertising or publicity pertaining to distribution of the\n software without specific, written prior permission.  \n \n DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\n ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\n DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\n ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\n WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\n ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\n SOFTWARE.\n"
  },
  {
    "path": "cmake/Modules/CMakeMacroLibtoolFile.cmake",
    "content": "# FIXME: Since we cannot require CMake 3.17, we cannot used deferred\n#        functions, and hence we have to do something similar manually\n\nset_property(GLOBAL PROPERTY LIBTOOL_TARGETS \"\")\n\nfunction(libtool_create_control_file target)\n  set_property(GLOBAL APPEND PROPERTY LIBTOOL_TARGETS ${target})\nendfunction()\n\nfunction(libtool_generate_control_files)\n  get_property(LIBTOOL_TARGETS GLOBAL PROPERTY LIBTOOL_TARGETS)\n  foreach(target ${LIBTOOL_TARGETS})\n    libtool_generate_control_file(${target})\n  endforeach()\nendfunction()\n\nfunction(libtool_generate_control_file _target)\n  get_target_property(_target_type ${_target} TYPE)\n\n  message(\"-- Creating static libtool control file for target ${_target}\")\n  # No support for shared libraries, as TigerVNC only needs libtool config\n  # files for static libraries.\n  if(\"${_target_type}\" MATCHES \"^[^STATIC_LIBRARY]$\")\n    message(FATAL_ERROR \" -  trying to use libtool_create_control_file for non-static library target.\")\n  endif()\n\n  #\n  # Parse the INTERFACE_LINK_LIBRARIES property to determine which\n  # libraries to put into libtool control file as library dependencies,\n  # and handle a few corner cases.\n  #\n\n  # First we need to split up any internal entries\n  set(target_libs \"\")\n  get_property(_target_libs TARGET ${_target}\n               PROPERTY INTERFACE_LINK_LIBRARIES)\n  foreach(library ${_target_libs})\n    if(\"${library}\" MATCHES \" \")\n      string(REPLACE \" \" \";\" lib_list \"${library}\")\n      list(APPEND target_libs ${lib_list})\n    else()\n      list(APPEND target_libs \"${library}\")\n    endif()\n  endforeach()\n\n  set(STATIC_MODE OFF)\n  set(FRAMEWORK OFF)\n  get_property(LIBRARY_PATHS TARGET ${_target}\n               PROPERTY INTERFACE_LINK_DIRECTORIES)\n\n  foreach(library ${target_libs})\n    if(FRAMEWORK)\n      set(_target_dependency_libs \"${_target_dependency_libs} -framework ${library}\")\n      set(FRAMEWORK OFF)\n      continue()\n    elseif(${library} STREQUAL \"-framework\")\n      set(FRAMEWORK ON)\n      continue()\n    # Assume all entries are shared libs if platform-specific static library\n    # extension is not matched.\n    elseif(NOT \"${library}\" MATCHES \".+${CMAKE_STATIC_LIBRARY_SUFFIX}$\")\n      set(SHARED OFF)\n      foreach(suffix ${CMAKE_SHARED_LIBRARY_SUFFIX} ${CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES})\n        if(\"${library}\" MATCHES \".+${suffix}$\")\n          set(SHARED ON)\n          break()\n        endif()\n      endforeach()\n\n      if(SHARED)\n        # Shared library extension matched, so extract the path and library\n        # name, then add the result to the libtool dependency libs.  This\n        # will always be an absolute path, because that's what CMake uses\n        # internally.\n        get_filename_component(_shared_lib ${library} NAME_WE)\n        get_filename_component(_shared_lib_path ${library} PATH)\n        string(REPLACE \"lib\" \"\" _shared_lib ${_shared_lib})\n        set(_target_dependency_libs \"${_target_dependency_libs} -L${_shared_lib_path} -l${_shared_lib}\")\n      else()\n        # No shared library extension matched.  Check whether target is a CMake\n        # target.\n        if(TARGET ${library})\n          # Target is a CMake target, so assume it is a static library and\n          # build a reference to it\n          get_target_property(library_path ${library} BINARY_DIR)\n          set(library ${library_path}/${CMAKE_STATIC_LIBRARY_PREFIX}${library}.la)\n          set(_target_dependency_libs \"${_target_dependency_libs} ${library}\")\n        elseif(${library} STREQUAL \"-Wl,-Bstatic\")\n          # All following libraries should be static\n          set(STATIC_MODE ON)\n        elseif(${library} STREQUAL \"-Wl,-Bdynamic\")\n          # All following libraries should be dynamic\n          set(STATIC_MODE OFF)\n        elseif(${library} MATCHES \"^${CMAKE_LIBRARY_PATH_FLAG}\")\n          # Library search path\n          string(REPLACE ${CMAKE_LIBRARY_PATH_FLAG} \"\" library ${library})\n          list(APPEND LIBRARY_PATHS ${library})\n        else()\n          # Normal library, so use find_library() to attempt to locate the\n          # library in a system directory.\n\n          # Need to remove -l prefix\n          if(${library} MATCHES \"^${CMAKE_LINK_LIBRARY_FLAG}\")\n            string(REPLACE ${CMAKE_LINK_LIBRARY_FLAG} \"\" library ${library})\n          endif()\n\n          if(STATIC_MODE)\n            set(_library ${CMAKE_STATIC_LIBRARY_PREFIX}${library}${CMAKE_STATIC_LIBRARY_SUFFIX})\n            find_library(FL ${_library} PATHS ${LIBRARY_PATHS})\n          endif()\n\n          if(NOT FL)\n            find_library(FL ${library} PATHS ${LIBRARY_PATHS})\n          endif()\n\n          if(FL)\n            # Found library. Depending on if it's static or not we might\n            # extract the path and library name, then add the\n            # result to the libtool dependency libs.\n            if(\"${FL}\" MATCHES \".+${CMAKE_STATIC_LIBRARY_SUFFIX}$\")\n              set(_target_dependency_libs \"${_target_dependency_libs} ${FL}\")\n            else()\n              get_filename_component(_shared_lib ${FL} NAME_WE)\n              get_filename_component(_shared_lib_path ${FL} PATH)\n              string(REPLACE \"lib\" \"\" _shared_lib ${_shared_lib})\n              set(_target_dependency_libs \"${_target_dependency_libs} -L${_shared_lib_path} -l${_shared_lib}\")\n            endif()\n          else()\n            message(FATAL_ERROR \" - could not find library ${library}\")\n          endif()\n          # Need to clear FL to get new results next loop\n          unset(FL CACHE)\n        endif()\n      endif()\n    else()\n      # Detected a static library.  Check whether the library pathname is\n      # absolute and, if not, use find_library() to get the absolute path.\n      get_filename_component(_name ${library} NAME)\n      string(REPLACE \"${_name}\" \"\" _path ${library})\n      if(NOT \"${_path}\" STREQUAL \"\")\n      \t# Pathname is absolute, so add it to the libtool library dependencies\n        # as-is.\n        set(_target_dependency_libs \"${_target_dependency_libs} ${library}\")\n      else()\n        # Pathname is not absolute, so use find_library() to get the absolute\n        # path.\n        find_library(FL ${library})\n        if(FL)\n          # Absolute pathname found.  Add it.\n          set(_target_dependency_libs \"${_target_dependency_libs} ${FL}\")\n        else()\n          message(FATAL_ERROR \" - could not find library ${library}\")\n        endif()\n        # Need to clear FL to get new results next loop\n        unset(FL CACHE)\n      endif()\n    endif()\n  endforeach()\n\n  get_target_property(_binary_dir ${_target} BINARY_DIR)\n\n  # Write the libtool control file for the static library\n  set(_lname ${CMAKE_STATIC_LIBRARY_PREFIX}${_target})\n  set(_laname ${_binary_dir}/${_lname}.la)\n\n  file(WRITE ${_laname} \"# ${_lname}.la - a libtool library file\\n# Generated by ltmain.sh (GNU libtool) 2.2.6b\\n\")\n  file(APPEND ${_laname} \"dlname=''\\n\\n\")\n  file(APPEND ${_laname} \"library_names=''\\n\\n\")\n  file(APPEND ${_laname} \"old_library='${_lname}${CMAKE_STATIC_LIBRARY_SUFFIX}'\\n\\n\")\n  file(APPEND ${_laname} \"inherited_linker_flags=''\\n\\n\")\n  file(APPEND ${_laname} \"dependency_libs=' ${_target_dependency_libs}'\\n\\n\")\n  file(APPEND ${_laname} \"weak_library_names=''\\n\\n\")\n  file(APPEND ${_laname} \"current=\\n\")\n  file(APPEND ${_laname} \"age=\\n\")\n  file(APPEND ${_laname} \"revision=\\n\\n\")\n  file(APPEND ${_laname} \"installed=no\\n\\n\")\n  file(APPEND ${_laname} \"shouldnotlink=no\\n\\n\")\n  file(APPEND ${_laname} \"dlopen=''\\n\")\n  file(APPEND ${_laname} \"dlpreopen=''\\n\\n\")\n  file(APPEND ${_laname} \"libdir='/usr/lib'\\n\\n\")\n\n  # Make sure the timestamp is updated to trigger other make invocations\n  set(_lamarker ${_binary_dir}/.${_lname}.la.fresh)\n  add_custom_command(OUTPUT \"${_lamarker}\" DEPENDS ${_target}\n    COMMENT \"Updating timestamp on ${_lname}.la\"\n    COMMAND \"${CMAKE_COMMAND}\" -E touch \"${_lamarker}\"\n    COMMAND \"${CMAKE_COMMAND}\" -E touch \"${_laname}\")\n\n  # Add custom command to symlink the static library so that autotools finds\n  # the library in .libs.  These are executed after the specified target build.\n  set(_libname ${_binary_dir}/.libs/${_lname}${CMAKE_STATIC_LIBRARY_SUFFIX})\n  add_custom_command(OUTPUT \"${_libname}\" DEPENDS ${_target}\n    COMMENT \"Creating symlink .libs/${_lname}${CMAKE_STATIC_LIBRARY_SUFFIX}\"\n    COMMAND \"${CMAKE_COMMAND}\" -E make_directory \"${_binary_dir}/.libs\"\n    COMMAND \"${CMAKE_COMMAND}\" -E create_symlink ../${_lname}${CMAKE_STATIC_LIBRARY_SUFFIX} \"${_libname}\")\n\n  add_custom_target(${_target}.la ALL\n    DEPENDS \"${_lamarker}\" \"${_libname}\")\nendfunction()\n"
  },
  {
    "path": "cmake/Modules/FindAVCodec.cmake",
    "content": "#[=======================================================================[.rst:\nFindAVCodec\n-----------\n\nFind the FFmpeg avcodec library\n\nResult variables\n^^^^^^^^^^^^^^^^\n\nThis module will set the following variables if found:\n\n``AVCODEC_INCLUDE_DIRS``\n  where to find libavcodec/avcodec.h, etc.\n``AVCODEC_LIBRARIES``\n  the libraries to link against to use avcodec.\n``AVCODEC_FOUND``\n  TRUE if found\n\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_AVCodec QUIET libavcodec)\nendif()\n\nfind_path(AVCodec_INCLUDE_DIR NAMES libavcodec/avcodec.h\n  HINTS\n    ${PC_AVCodec_INCLUDE_DIRS}\n)\nmark_as_advanced(AVCodec_INCLUDE_DIR)\n\nfind_library(AVCodec_LIBRARY NAMES avcodec\n  HINTS\n    ${PC_AVCodec_LIBRARY_DIRS}\n)\nmark_as_advanced(AVCodec_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(AVCodec\n  REQUIRED_VARS\n    AVCodec_LIBRARY AVCodec_INCLUDE_DIR\n)\n\nif(AVCodec_FOUND)\n  set(AVCODEC_INCLUDE_DIRS ${AVCodec_INCLUDE_DIR})\n  set(AVCODEC_LIBRARIES ${AVCodec_LIBRARY})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindAVUtil.cmake",
    "content": "#[=======================================================================[.rst:\nFindAVUtil\n----------\n\nFind the FFmpeg avutil library\n\nResult variables\n^^^^^^^^^^^^^^^^\n\nThis module will set the following variables if found:\n\n``AVUTIL_INCLUDE_DIRS``\n  where to find libavutil/avutil.h, etc.\n``AVUTIL_LIBRARIES``\n  the libraries to link against to use avutil.\n``AVUTIL_FOUND``\n  TRUE if found\n\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_AVUtil QUIET libavutil)\nendif()\n\nfind_path(AVUtil_INCLUDE_DIR NAMES libavutil/avutil.h\n  HINTS\n    ${PC_AVUtil_INCLUDE_DIRS}\n)\nmark_as_advanced(AVUtil_INCLUDE_DIR)\n\nfind_library(AVUtil_LIBRARY NAMES avutil\n  HINTS\n    ${PC_AVUtil_LIBRARY_DIRS}\n)\nmark_as_advanced(AVUtil_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(AVUtil\n  REQUIRED_VARS\n    AVUtil_LIBRARY AVUtil_INCLUDE_DIR\n)\n\nif(AVUtil_FOUND)\n  set(AVUTIL_INCLUDE_DIRS ${AVUtil_INCLUDE_DIR})\n  set(AVUTIL_LIBRARIES ${AVUtil_LIBRARY})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindGLib.cmake",
    "content": "#[=======================================================================[.rst:\nFindGLib\n----------\nFind the GLib library\nResult variables\n^^^^^^^^^^^^^^^^\nThis module will set the following variables if found:\n``GLIB_INCLUDE_DIRS``\n  where to find glib.h, etc.\n``GLIB_LIBRARIES``\n  the libraries to link against to use libglib.\n``GLIB_FOUND``\n  TRUE if found\n#]=======================================================================]\n\n\nfind_package(PkgConfig QUIET)\nif (PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_GLib QUIET glib-2.0)\nendif()\n\nfind_path(GLib_INCLUDE_DIR NAMES glib.h\n  PATH_SUFFIXES\n    glib-2.0\n  HINTS\n    ${PC_GLib_INCLUDE_DIRS}\n)\nmark_as_advanced(GLib_INCLUDE_DIR)\n\nfind_path(GLib_CONFIG_INCLUDE_DIR NAMES glibconfig.h\n  PATH_SUFFIXES\n    glib-2.0/include\n  HINTS\n    ${PC_GLib_INCLUDE_DIRS}\n)\nmark_as_advanced(GLib_CONFIG_INCLUDE_DIR)\n\nfind_library(GLib_LIBRARIES NAMES glib-2.0\n  HINTS\n    ${PC_GLib_LIBRARY_DIRS}\n)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(GLib\n  REQUIRED_VARS\n    GLib_LIBRARIES GLib_INCLUDE_DIR GLib_CONFIG_INCLUDE_DIR\n)\n\nif(GLIB_FOUND)\n  set(GLIB_INCLUDE_DIRS ${GLib_INCLUDE_DIR} ${GLib_CONFIG_INCLUDE_DIR})\n  set(GLIB_LIBRARIES ${GLib_LIBRARIES})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindGMP.cmake",
    "content": "#[=======================================================================[.rst:\nFindGMP\n-------\n\nFind the GNU MP bignum library\n\nResult variables\n^^^^^^^^^^^^^^^^\n\nThis module will set the following variables if found:\n\n``GMP_INCLUDE_DIRS``\n  where to find gmp.h, etc.\n``GMP_LIBRARIES``\n  the libraries to link against to use GMP.\n``GMP_FOUND``\n  TRUE if found\n\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_GMP QUIET gmp)\nendif()\n\nfind_path(GMP_INCLUDE_DIR NAMES gmp.h\n  HINTS\n    ${PC_GMP_INCLUDE_DIRS}\n)\nmark_as_advanced(GMP_INCLUDE_DIR)\n\nfind_library(GMP_LIBRARY NAMES gmp\n  HINTS\n    ${PC_GMP_LIBRARY_DIRS}\n)\nmark_as_advanced(GMP_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(GMP\n  REQUIRED_VARS\n    GMP_LIBRARY GMP_INCLUDE_DIR\n)\n\nif(GMP_FOUND)\n  set(GMP_INCLUDE_DIRS ${GMP_INCLUDE_DIR})\n  set(GMP_LIBRARIES ${GMP_LIBRARY})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindGio.cmake",
    "content": "#[=======================================================================[.rst:\nFindGio\n----------\nFind the GIO library\nResult variables\n^^^^^^^^^^^^^^^^\nThis module will set the following variables if found:\n``GIO_INCLUDE_DIRS``\n  where to find gio/gio.h, etc.\n``GIO_LIBRARIES``\n  the libraries to link against to use libgio.\n``GIO_FOUND``\n  TRUE if found\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif (PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_Gio QUIET gio-2.0)\n  pkg_check_modules(PC_Gio_unix QUIET gio-unix-2.0)\nendif()\n\nfind_path(Gio_INCLUDE_DIR NAMES gio/gio.h\n  PATH_SUFFIXES\n    glib-2.0\n  HINTS\n    ${PC_Gio_INCLUDE_DIRS}\n)\nmark_as_advanced(Gio_INCLUDE_DIR)\n\nfind_path(Gio_unix_INCLUDE_DIR NAMES gio/gunixfdlist.h\n  PATH_SUFFIXES\n    gio-unix-2.0\n  HINTS\n    ${PC_Gio_unix_INCLUDE_DIRS}\n)\nmark_as_advanced(Gio_unix_INCLUDE_DIR)\n\nfind_library(Gio_LIBRARIES NAMES gio-2.0\n  HINTS\n    ${PC_Gio_LIBRARY_DIRS}\n)\nmark_as_advanced(Gio_LIBRARIES)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(Gio\n  REQUIRED_VARS\n    Gio_LIBRARIES Gio_INCLUDE_DIR Gio_unix_INCLUDE_DIR\n)\n\n\nif(GIO_FOUND)\n  set(GIO_INCLUDE_DIRS ${Gio_INCLUDE_DIR} ${Gio_unix_INCLUDE_DIR})\n  set(GIO_LIBRARIES ${Gio_LIBRARIES})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindGobject.cmake",
    "content": "#[=======================================================================[.rst:\nFindGobject\n----------\nFind the GObject library\nResult variables\n^^^^^^^^^^^^^^^^\nThis module will set the following variables if found:\n``GOBJECT_INCLUDE_DIRS``\n  where to find gobject/gobject.h, etc.\n``GOBJECT_LIBRARIES``\n  the libraries to link against to use libgobject.\n``GOBJECT_FOUND``\n  TRUE if found\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif (PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_Gobject QUIET gobject-2.0)\nendif()\n\nfind_path(Gobject_INCLUDE_DIR NAMES gobject/gobject.h\n  PATH_SUFFIXES\n    glib-2.0\n  HINTS\n    ${PC_Gobject_INCLUDE_DIRS}\n)\nmark_as_advanced(Gobject_INCLUDE_DIR)\n\nfind_library(Gobject_LIBRARIES NAMES gobject-2.0\n  HINTS\n    ${PC_Gobject_LIBRARY_DIRS}\n)\nmark_as_advanced(Gobject_LIBRARIES)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(Gobject\n  REQUIRED_vARS\n    Gobject_INCLUDE_DIR Gobject_LIBRARIES\n)\n\nif(GOBJECT_FOUND)\n  set(GOBJECT_INCLUDE_DIRS ${Gobject_INCLUDE_DIR})\n  set(GOBJECT_LIBRARIES ${Gobject_LIBRARIES})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindNettle.cmake",
    "content": "#[=======================================================================[.rst:\nFindNettle\n----------\n\nFind the Nettle and Hogweed libraries\n\nResult variables\n^^^^^^^^^^^^^^^^\n\nThis module will set the following variables if found:\n\n``NETTLE_INCLUDE_DIRS``\n  where to find nettle/eax.h, etc.\n``NETTLE_LIBRARIES``\n  the libraries to link against to use Nettle.\n``HOGWEED_LIBRARIES``\n  the libraries to link against to use Hogweed.\n``NETTLE_FOUND``\n  TRUE if found\n\n#]=======================================================================]\n\nif(Nettle_FIND_REQUIRED)\n  find_package(GMP QUIET REQUIRED)\nelse()\n  find_package(GMP QUIET)\nendif()\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_Nettle QUIET nettle)\n  pkg_check_modules(PC_Hogweed QUIET hogweed)\nendif()\n\nfind_path(Nettle_INCLUDE_DIR NAMES nettle/eax.h\n  HINTS\n    ${PC_Nettle_INCLUDE_DIRS}\n)\nmark_as_advanced(Nettle_INCLUDE_DIR)\n\nfind_library(Nettle_LIBRARY NAMES nettle\n  HINTS\n    ${PC_Nettle_LIBRARY_DIRS}\n)\nmark_as_advanced(Nettle_LIBRARY)\n\nfind_library(Hogweed_LIBRARY NAMES hogweed\n  HINTS\n    ${PC_Hogweed_LIBRARY_DIRS}\n)\nmark_as_advanced(Hogweed_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(Nettle\n  REQUIRED_VARS\n    Nettle_LIBRARY Nettle_INCLUDE_DIR Hogweed_LIBRARY\n)\n\nif(Nettle_FOUND)\n  set(NETTLE_INCLUDE_DIRS ${Nettle_INCLUDE_DIR} ${GMP_INCLUDE_DIRS})\n  set(NETTLE_LIBRARIES ${Nettle_LIBRARY})\n  set(HOGWEED_LIBRARIES ${Hogweed_LIBRARY} ${GMP_LIBRARIES})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindPAM.cmake",
    "content": "#[=======================================================================[.rst:\nFindPAM\n-------\n\nFind the Pluggable Authentication Modules library\n\nResult variables\n^^^^^^^^^^^^^^^^\n\nThis module will set the following variables if found:\n\n``PAM_INCLUDE_DIRS``\n  where to find security/pam_appl.h, etc.\n``PAM_LIBRARIES``\n  the libraries to link against to use PAM.\n``PAM_FOUND``\n  TRUE if found\n\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_PAM QUIET pam)\nendif()\n\nfind_path(PAM_INCLUDE_DIR NAMES security/pam_appl.h\n  HINTS\n    ${PC_PAM_INCLUDE_DIRS}\n)\nmark_as_advanced(PAM_INCLUDE_DIR)\n\nfind_library(PAM_LIBRARY NAMES pam\n  HINTS\n    ${PC_PAM_LIBRARY_DIRS}\n)\nmark_as_advanced(PAM_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(PAM\n  REQUIRED_VARS\n    PAM_LIBRARY PAM_INCLUDE_DIR\n)\n\nif(PAM_FOUND)\n  set(PAM_INCLUDE_DIRS ${PAM_INCLUDE_DIR})\n  set(PAM_LIBRARIES ${PAM_LIBRARY})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindPWQuality.cmake",
    "content": "#[=======================================================================[.rst:\nFindPWQuality\n-------------\n\nFind the password quality library\n\nResult variables\n^^^^^^^^^^^^^^^^\n\nThis module will set the following variables if found:\n\n``PWQUALITY_INCLUDE_DIRS``\n  where to find pwquality.h, etc.\n``PWQUALITY_LIBRARIES``\n  the libraries to link against to use pwquality.\n``PWQUALITY_FOUND``\n  TRUE if found\n\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_PWQuality QUIET pwquality)\nendif()\n\nfind_path(PWQuality_INCLUDE_DIR NAMES pwquality.h\n  HINTS\n    ${PC_PWQuality_INCLUDE_DIRS}\n)\nmark_as_advanced(PWQuality_INCLUDE_DIR)\n\nfind_library(PWQuality_LIBRARY NAMES pwquality\n  HINTS\n    ${PC_PWQuality_LIBRARY_DIRS}\n)\nmark_as_advanced(PWQuality_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(PWQuality\n  REQUIRED_VARS\n    PWQuality_LIBRARY PWQuality_INCLUDE_DIR\n)\n\nif(PWQuality_FOUND)\n  set(PWQUALITY_INCLUDE_DIRS ${PWQuality_INCLUDE_DIR})\n  set(PWQUALITY_LIBRARIES ${PWQuality_LIBRARY})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindPipeWire.cmake",
    "content": "#[=======================================================================[.rst:\nFindPipeWire\n----------\nFind the PipeWire library\nResult variables\n^^^^^^^^^^^^^^^^\nThis module will set the following variables if found:\n``PIPEWIRE_INCLUDE_DIRS``\n  where to find pipewire/pipewire.h, etc.\n``PIPEWIRE_LIBRARIES``\n  the libraries to link against to use libpipewire.\n``PIPEWIRE_FOUND``\n  TRUE if found\n#]=======================================================================]\n\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_PipeWire QUIET libpipewire-0.3)\nendif()\n\nfind_path(PipeWire_INCLUDE_DIR NAMES pipewire/pipewire.h\n  PATH_SUFFIXES\n    pipewire-0.3\n  HINTS\n    ${PC_PipeWire_INCLUDE_DIRS}\n)\nmark_as_advanced(PipeWire_INCLUDE_DIR)\n\nfind_path(Spa_INCLUDE_DIR NAMES spa/pod/pod.h\n  PATH_SUFFIXES\n    spa-0.2\n   HINTS\n    ${PC_PipeWire_INCLUDE_DIRS})\nmark_as_advanced(Spa_INCLUDE_DIR)\n\nfind_library(PipeWire_LIBRARY NAMES pipewire-0.3\n  HINTS\n    ${PC_PipeWire_LIBRARY_DIRS}\n)\nmark_as_advanced(PipeWire_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(PipeWire\n  REQUIRED_VARS\n    PipeWire_LIBRARY PipeWire_INCLUDE_DIR Spa_INCLUDE_DIR\n)\n\nif(PipeWire_FOUND)\n  set(PIPEWIRE_LIBRARIES ${PipeWire_LIBRARY})\n  set(PIPEWIRE_INCLUDE_DIRS ${PipeWire_INCLUDE_DIR} ${Spa_INCLUDE_DIR})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindPixman.cmake",
    "content": "#[=======================================================================[.rst:\nFindPixman\n----------\n\nFind the Pixman library\n\nResult variables\n^^^^^^^^^^^^^^^^\n\nThis module will set the following variables if found:\n\n``PIXMAN_INCLUDE_DIRS``\n  where to find pixman.h, etc.\n``PIXMAN_LIBRARIES``\n  the libraries to link against to use Pixman.\n``PIXMAN_FOUND``\n  TRUE if found\n\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_Pixman QUIET pixman-1)\nendif()\n\nfind_path(Pixman_INCLUDE_DIR NAMES pixman.h\n  PATH_SUFFIXES\n    pixman-1\n  HINTS\n    ${PC_Pixman_INCLUDE_DIRS}\n)\nmark_as_advanced(Pixman_INCLUDE_DIR)\n\nfind_library(Pixman_LIBRARY NAMES pixman-1\n  HINTS\n    ${PC_Pixman_LIBRARY_DIRS}\n)\nmark_as_advanced(Pixman_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(Pixman\n  REQUIRED_VARS\n    Pixman_LIBRARY Pixman_INCLUDE_DIR\n)\n\nif(Pixman_FOUND)\n  set(PIXMAN_INCLUDE_DIRS ${Pixman_INCLUDE_DIR})\n  set(PIXMAN_LIBRARIES ${Pixman_LIBRARY})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindSELinux.cmake",
    "content": "#[=======================================================================[.rst:\nFindSELinux\n-----------\n\nFind the SELinux library\n\nResult variables\n^^^^^^^^^^^^^^^^\n\nThis module will set the following variables if found:\n\n``SELINUX_INCLUDE_DIRS``\n  where to find selinux/selinux.h, etc.\n``SELINUX_LIBRARIES``\n  the libraries to link against to use libselinux.\n``SELINUX_FOUND``\n  TRUE if found\n\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_SELinux QUIET libselinux)\nendif()\n\nfind_path(SELinux_INCLUDE_DIR NAMES selinux/selinux.h\n  HINTS\n    ${PC_SELinux_INCLUDE_DIRS}\n)\nmark_as_advanced(SELinux_INCLUDE_DIR)\n\nfind_library(SELinux_LIBRARY NAMES selinux\n  HINTS\n    ${PC_SELinux_LIBRARY_DIRS}\n)\nmark_as_advanced(SELinux_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(SELinux\n  REQUIRED_VARS\n    SELinux_LIBRARY SELinux_INCLUDE_DIR\n)\n\nif(SELinux_FOUND)\n  set(SELINUX_INCLUDE_DIRS ${SELinux_INCLUDE_DIR})\n  set(SELINUX_LIBRARIES ${SELinux_LIBRARY})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindSWScale.cmake",
    "content": "#[=======================================================================[.rst:\nFindSWScale\n-----------\n\nFind the FFmpeg swscale library\n\nResult variables\n^^^^^^^^^^^^^^^^\n\nThis module will set the following variables if found:\n\n``SWSCALE_INCLUDE_DIRS``\n  where to find libswscale/swscale.h, etc.\n``SWSCALE_LIBRARIES``\n  the libraries to link against to use swscale.\n``SWSCALE_FOUND``\n  TRUE if found\n\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_SWScale QUIET libswscale)\nendif()\n\nfind_path(SWScale_INCLUDE_DIR NAMES libswscale/swscale.h\n  HINTS\n    ${PC_SWScale_INCLUDE_DIRS}\n)\nmark_as_advanced(SWScale_INCLUDE_DIR)\n\nfind_library(SWScale_LIBRARY NAMES swscale\n  HINTS\n    ${PC_SWScale_LIBRARY_DIRS}\n)\nmark_as_advanced(SWScale_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(SWScale\n  REQUIRED_VARS\n    SWScale_LIBRARY SWScale_INCLUDE_DIR\n)\n\nif(SWScale_FOUND)\n  set(SWSCALE_INCLUDE_DIRS ${SWScale_INCLUDE_DIR})\n  set(SWSCALE_LIBRARIES ${SWScale_LIBRARY})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindSystemd.cmake",
    "content": "#[=======================================================================[.rst:\nFindSystemd\n-----------\n\nFind the systemd library\n\nResult variables\n^^^^^^^^^^^^^^^^\n\nThis module will set the following variables if found:\n\n``SYSTEMD_INCLUDE_DIRS``\n  where to find systemd/sd-daemon.h, etc.\n``SYSTEMD_LIBRARIES``\n  the libraries to link against to use libsystemd.\n``SYSTEMD_FOUND``\n  TRUE if found\n\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_Systemd QUIET libsystemd)\nendif()\n\nfind_path(Systemd_INCLUDE_DIR NAMES systemd/sd-daemon.h\n  HINTS\n    ${PC_Systemd_INCLUDE_DIRS}\n)\nmark_as_advanced(Systemd_INCLUDE_DIR)\n\nfind_library(Systemd_LIBRARY NAMES systemd\n  HINTS\n    ${PC_Systemd_LIBRARY_DIRS}\n)\nmark_as_advanced(Systemd_LIBRARY)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(Systemd\n  REQUIRED_VARS\n    Systemd_LIBRARY Systemd_INCLUDE_DIR\n)\n\nif(Systemd_FOUND)\n  set(SYSTEMD_INCLUDE_DIRS ${Systemd_INCLUDE_DIR})\n  set(SYSTEMD_LIBRARIES ${Systemd_LIBRARY})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindUuid.cmake",
    "content": "#[=======================================================================[.rst:\nFindUuid\n----------\nFind the UUID library\nResult variables\n^^^^^^^^^^^^^^^^\nThis module will set the following variables if found:\n``UUID_INCLUDE_DIRS``\n  where to find uuid/uuid.h, etc.\n``UUID_LIBRARIES``\n  the libraries to link against to use libuuid.\n``UUID_FOUND``\n  TRUE if found\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\nif (PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_Uuid QUIET uuid)\nendif()\n\nfind_path(Uuid_INCLUDE_DIR NAMES uuid/uuid.h\n  HINTS\n    ${PC_Uuid_INCLUDE_DIRS}\n)\nmark_as_advanced(Uuid_INCLUDE_DIR)\n\nfind_library(Uuid_LIBRARIES NAMES uuid\n  HINTS\n    ${PC_Uuid_LIBRARY_DIRS}\n)\nmark_as_advanced(Uuid_LIBRARIES)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(Uuid\n  REQUIRED_VARS\n    Uuid_LIBRARIES Uuid_INCLUDE_DIR\n)\n\nif(Uuid_FOUND)\n  set(UUID_INCLUDE_DIRS ${Uuid_INCLUDE_DIR})\n  set(UUID_LIBRARIES ${Uuid_LIBRARIES})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindWaylandClient.cmake",
    "content": "#[=======================================================================[.rst:\nFindWaylandClient\n-----------------\nFind the Wayland client library\nResult variables\n^^^^^^^^^^^^^^^^\nThis module will set the following variables if found:\n``WAYLANDCLIENT_INCLUDE_DIRS``\n  where to find wayland-client.h.h, etc.\n``WAYLANDCLIENT_LIBRARIES``\n  the libraries to link against to use wayland client.\n``WAYLAND_CLIENT_FOUND``\n  TRUE if found\n#]=======================================================================]\n\nfind_package(PkgConfig QUIET)\n\nif (PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_WaylandClient QUIET wayland-client)\nendif()\n\nfind_program(Wayland_scanner_EXECUTABLE\n    NAMES wayland-scanner\n)\n\nfind_path(WaylandClient_INCLUDE_DIR NAMES wayland-client.h\n  PATH_SUFFIXES\n    wayland\n  HINTS\n    ${PC_WaylandClient_INCLUDE_DIRS}\n)\nmark_as_advanced(WaylandClient_INCLUDE_DIR)\n\nfind_library(WaylandClient_LIBRARIES NAMES wayland-client\n  HINTS\n    ${PC_WaylandClient_LIBRARY_DIRS}\n)\nmark_as_advanced(WaylandClient_LIBRARIES)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(WaylandClient\n  REQUIRED_VARS\n    WaylandClient_LIBRARIES WaylandClient_INCLUDE_DIR Wayland_scanner_EXECUTABLE\n)\n\nif(WaylandClient_FOUND)\n  set(WAYLANDCLIENT_INCLUDE_DIRS ${WaylandClient_INCLUDE_DIR})\n  set(WAYLANDCLIENT_LIBRARIES ${WaylandClient_LIBRARIES})\n  set(WAYLAND_SCANNER_EXECUTABLE ${Wayland_scanner_EXECUTABLE})\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindXkbcommon.cmake",
    "content": "#[=======================================================================[.rst:\nFindXkbcommon\n----------\nFind the Xkbcommon library\nResult variables\n^^^^^^^^^^^^^^^^\nThis module will set the following variables if found:\n``XKBCOMMON_INCLUDE_DIRS``\n  where to find xkbcommon/xkbcommon.h, etc.\n``XKBCOMMON_LIBRARIES``\n  the libraries to link against to use libxkbcommon.\n``XKBCOMMON_FOUND``\n  TRUE if found\n#]=======================================================================]\n\n\nfind_package(Pkgconfig QUIET)\nif(PKG_CONFIG_FOUND)\n  pkg_check_modules(PC_Xkbcommon QUIET xkbcommon)\nendif()\n\nfind_path(Xkbcommon_INCLUDE_DIR NAMES xkbcommon/xkbcommon.h\n  HINTS\n    ${PC_Xkbcommon_INCLUDE_DIRS}\n)\nmark_as_advanced(Xkbcommon_INCLUDE_DIR)\n\nfind_library(Xkbcommon_LIBRARIES NAMES xkbcommon\n  HINTS\n    ${PC_Xkbcommon_LIBRARY_DIRS}\n)\nmark_as_advanced(Xkbcommon_LIBRARIES)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(Xkbcommon\n  REQUIRED_VARS Xkbcommon_LIBRARIES Xkbcommon_INCLUDE_DIR\n)\n\nif(Xkbcommon_FOUND)\n  set(XKBCOMMON_INCLUDE_DIRS ${Xkbcommon_INCLUDE_DIR})\n  set(XKBCOMMON_LIBRARIES ${Xkbcommon_LIBRARIES})\nendif()\n"
  },
  {
    "path": "cmake/StaticBuild.cmake",
    "content": "#\n# Best-effort magic that tries to produce semi-static binaries\n# (i.e. only depends on \"safe\" libraries like libc and libX11)\n#\n# Note that this often fails as there is no way to automatically\n# determine the dependencies of the libraries we depend on, and\n# a lot of details change with each different build environment.\n#\n\noption(BUILD_STATIC\n    \"Link statically against most libraries, if possible\" OFF)\n\noption(BUILD_STATIC_GCC\n    \"Link statically against only libgcc and libstdc++\" OFF)\n\nif(BUILD_STATIC)\n  message(STATUS \"Attempting to link static binaries...\")\n\n  set(BUILD_STATIC_GCC 1)\n\n  set(JPEG_LIBRARIES \"-Wl,-Bstatic -ljpeg -Wl,-Bdynamic\")\n  set(ZLIB_LIBRARIES \"-Wl,-Bstatic -lz -Wl,-Bdynamic\")\n  set(PIXMAN_LIBRARIES \"-Wl,-Bstatic -lpixman-1 -Wl,-Bdynamic\")\n\n  # FIXME: This code has not yet been tested\n  if(UNIX AND NOT APPLE)\n    if (PIPEWIRE_FOUND)\n      set(PIPEWIRE_LIBRARIES, \"-Wl,-Bstatic -lpipewire-0.3 -Wl, -Bdynamic\")\n    endif()\n    if (UUID_FOUND)\n      set(UUID_LIBRARIES, \"-Wl,-Bstatic -luuid -Wl, -Bdynamic\")\n    endif()\n    if (GLIB_FOUND)\n      set(GLIB_LIBRARIES, \"-Wl,-Bstatic -lglib-2.0 -Wl, -Bdynamic\")\n    endif()\n    if (GIO_FOUND)\n      set(GIO_LIBRARIES, \"-Wl,-Bstatic  -lgio-2.0 -lgobject-2.0 -lglib-2.0 -Wl, -Bdynamic\")\n    endif()\n    if (GOBJECT_FOUND)\n      set(GOBJECT_LIBRARIES, \"-Wl,-Bstatic -lgobject-2.0 -lglib-2.0 -Wl, -Bdynamic\")\n    endif()\n  endif()\n\n  # gettext is included in libc on many unix systems\n  check_function_exists(dgettext LIBC_HAS_DGETTEXT)\n  if(NOT LIBC_HAS_DGETTEXT)\n    FIND_LIBRARY(UNISTRING_LIBRARY NAMES unistring libunistring)\n\n    set(Intl_LIBRARIES \"-Wl,-Bstatic -lintl\")\n\n    if(UNISTRING_LIBRARY)\n      set(Intl_LIBRARIES \"${Intl_LIBRARIES} -lunistring\")\n    endif()\n\n    set(Intl_LIBRARIES \"${Intl_LIBRARIES} -Wl,-Bdynamic\")\n\n    if(APPLE)\n      set(Intl_LIBRARIES \"${Intl_LIBRARIES} -liconv\")\n    else()\n      set(Intl_LIBRARIES \"${Intl_LIBRARIES} -Wl,-Bstatic\")\n      set(Intl_LIBRARIES \"${Intl_LIBRARIES} -liconv\")\n      set(Intl_LIBRARIES \"${Intl_LIBRARIES} -Wl,-Bdynamic\")\n    endif()\n\n    if(APPLE)\n      set(Intl_LIBRARIES \"${Intl_LIBRARIES} -framework Carbon\")\n    endif()\n  endif()\n\n  if(GNUTLS_FOUND)\n    # GnuTLS has historically had different crypto backends\n    FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle\n      HINTS ${PC_GNUTLS_LIBDIR} ${PC_GNUTLS_LIBRARY_DIRS})\n    FIND_LIBRARY(TASN1_LIBRARY NAMES tasn1 libtasn1\n      HINTS ${PC_GNUTLS_LIBDIR} ${PC_GNUTLS_LIBRARY_DIRS})\n    FIND_LIBRARY(IDN2_LIBRARY NAMES idn2 libidn2\n      HINTS ${PC_GNUTLS_LIBDIR} ${PC_GNUTLS_LIBRARY_DIRS})\n    FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd\n      HINTS ${PC_GNUTLS_LIBDIR} ${PC_GNUTLS_LIBRARY_DIRS})\n\n    set(GNUTLS_LIBRARIES \"-Wl,-Bstatic -lgnutls\")\n\n    if(TASN1_LIBRARY)\n      set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -ltasn1\")\n    endif()\n    if(NETTLE_LIBRARY)\n      set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -lhogweed -lnettle -lgmp\")\n    endif()\n    if(IDN2_LIBRARY)\n      set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -lidn2\")\n    endif()\n    if(ZSTD_LIBRARY)\n      set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -lzstd\")\n    endif()\n\n    set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -Wl,-Bdynamic\")\n\n    if (WIN32)\n      FIND_LIBRARY(P11KIT_LIBRARY NAMES p11-kit libp11-kit\n        HINTS ${PC_GNUTLS_LIBDIR} ${PC_GNUTLS_LIBRARY_DIRS})\n      FIND_LIBRARY(UNISTRING_LIBRARY NAMES unistring libunistring\n        HINTS ${PC_GNUTLS_LIBDIR} ${PC_GNUTLS_LIBRARY_DIRS})\n\n      # GnuTLS uses various crypto-api stuff\n      set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -lcrypt32 -lncrypt -lbcrypt\")\n      # And sockets\n      set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -lws2_32\")\n\n      # p11-kit only available as dynamic library for MSYS2 on Windows and dynamic linking of unistring is required\n      if(P11KIT_LIBRARY)\n        set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -lp11-kit\")\n      endif()\n      if(UNISTRING_LIBRARY)\n        set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -lunistring\")\n      endif()\n    endif()\n\n    if(${CMAKE_SYSTEM_NAME} MATCHES \"SunOS\")\n      # nanosleep() lives here on Solaris\n      set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -lrt\")\n      # and socket functions are hidden here\n      set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} -lsocket\")\n    endif()\n\n    # GnuTLS uses gettext and zlib, so make sure those are always\n    # included and in the proper order\n    set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} ${ZLIB_LIBRARIES}\")\n    set(GNUTLS_LIBRARIES \"${GNUTLS_LIBRARIES} ${Intl_LIBRARIES}\")\n\n    # The last variables might introduce whitespace, which CMake\n    # throws a hissy fit about\n    string(STRIP ${GNUTLS_LIBRARIES} GNUTLS_LIBRARIES)\n  endif()\n\n  if(NETTLE_FOUND)\n    set(NETTLE_LIBRARIES \"-Wl,-Bstatic -lnettle -Wl,-Bdynamic\")\n    set(HOGWEED_LIBRARIES \"-Wl,-Bstatic -lhogweed -lnettle -lgmp -Wl,-Bdynamic\")\n  endif()\n\n  if(DEFINED FLTK_LIBRARIES)\n    set(FLTK_LIBRARIES \"-Wl,-Bstatic -lfltk_images -lpng -ljpeg -lfltk -Wl,-Bdynamic\")\n\n    if(WIN32)\n      set(FLTK_LIBRARIES \"${FLTK_LIBRARIES} -lcomctl32\")\n    elseif(APPLE)\n      set(FLTK_LIBRARIES \"${FLTK_LIBRARIES} -framework Cocoa\")\n    else()\n      set(FLTK_LIBRARIES \"${FLTK_LIBRARIES} -lm -ldl\")\n    endif()\n\n    if(X11_FOUND AND NOT APPLE)\n      if(${CMAKE_SYSTEM_NAME} MATCHES \"SunOS\")\n        set(FLTK_LIBRARIES \"${FLTK_LIBRARIES} ${X11_Xcursor_LIB} ${X11_Xfixes_LIB} -Wl,-Bstatic -lXft -Wl,-Bdynamic -lfontconfig -lXrender -lXext -R/usr/sfw/lib -L=/usr/sfw/lib -lfreetype -lsocket -lnsl\")\n      else()\n        set(FLTK_LIBRARIES \"${FLTK_LIBRARIES} -Wl,-Bstatic -lXcursor -lXfixes -lXft -lfontconfig -lexpat -lfreetype -lpng -lbz2 -luuid -lXrender -lXext -lXinerama -Wl,-Bdynamic\")\n      endif()\n\n      set(FLTK_LIBRARIES \"${FLTK_LIBRARIES} -lX11\")\n    endif()\n  endif()\n\n  # X11 libraries change constantly on Linux systems so we have to link\n  # them statically, even libXext. libX11 is somewhat stable, although\n  # even it has had an ABI change once or twice.\n  if(X11_FOUND AND NOT ${CMAKE_SYSTEM_NAME} MATCHES \"SunOS\")\n    set(X11_LIBRARIES \"-Wl,-Bstatic -lXext -Wl,-Bdynamic -lX11\")\n    if(X11_XTest_LIB)\n      set(X11_XTest_LIB \"-Wl,-Bstatic -lXtst -Wl,-Bdynamic\")\n    endif()\n    if(X11_Xdamage_LIB)\n      set(X11_Xdamage_LIB \"-Wl,-Bstatic -lXdamage -Wl,-Bdynamic\")\n    endif()\n    if(X11_Xrandr_LIB)\n      set(X11_Xrandr_LIB \"-Wl,-Bstatic -lXrandr -lXrender -Wl,-Bdynamic\")\n    endif()\n    if(X11_Xi_LIB)\n      set(X11_Xi_LIB \"-Wl,-Bstatic -lXi -Wl,-Bdynamic\")\n    endif()\n  endif()\nendif()\n\nif(BUILD_STATIC_GCC)\n  set(CMAKE_C_LINK_EXECUTABLE \"${CMAKE_C_LINK_EXECUTABLE} -static-libgcc\")\n  set(CMAKE_CXX_LINK_EXECUTABLE \"${CMAKE_CXX_LINK_EXECUTABLE} -static-libstdc++ -static-libgcc\")\n  if(ENABLE_ASAN)\n    set(CMAKE_C_LINK_EXECUTABLE \"${CMAKE_C_LINK_EXECUTABLE} -static-libasan\")\n    set(CMAKE_CXX_LINK_EXECUTABLE \"${CMAKE_CXX_LINK_EXECUTABLE} -static-libasan\")\n  endif()\n  if(ENABLE_TSAN)\n    set(CMAKE_C_LINK_EXECUTABLE \"${CMAKE_C_LINK_EXECUTABLE} -static-libtsan\")\n    set(CMAKE_CXX_LINK_EXECUTABLE \"${CMAKE_CXX_LINK_EXECUTABLE} -static-libtsan\")\n  endif()\nendif()\n"
  },
  {
    "path": "cmake/cmake_uninstall.cmake.in",
    "content": "# This code is from the CMake FAQ\n\nif (NOT EXISTS \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\")\n  message(FATAL_ERROR \"Cannot find install manifest: \\\"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\\\"\")\nendif(NOT EXISTS \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\")\n\nfile(READ \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\" files)\nstring(REGEX REPLACE \"\\n\" \";\" files \"${files}\")\nlist(REVERSE files)\nforeach (file ${files})\n  message(STATUS \"Uninstalling \\\"$ENV{DESTDIR}${file}\\\"\")\n    if (EXISTS \"$ENV{DESTDIR}${file}\")\n      execute_process(\n        COMMAND @CMAKE_COMMAND@ -E remove \"$ENV{DESTDIR}${file}\"\n        OUTPUT_VARIABLE rm_out\n        RESULT_VARIABLE rm_retval\n      )\n    if(NOT ${rm_retval} EQUAL 0)\n      message(FATAL_ERROR \"Problem when removing \\\"$ENV{DESTDIR}${file}\\\"\")\n    endif (NOT ${rm_retval} EQUAL 0)\n  else (EXISTS \"$ENV{DESTDIR}${file}\")\n    message(STATUS \"File \\\"$ENV{DESTDIR}${file}\\\" does not exist.\")\n  endif (EXISTS \"$ENV{DESTDIR}${file}\")\nendforeach(file)\n"
  },
  {
    "path": "common/CMakeLists.txt",
    "content": "add_subdirectory(core)\nadd_subdirectory(rdr)\nadd_subdirectory(network)\nadd_subdirectory(rfb)\n\n# For any convenience libraries that are linked into libvnc.so, we need to\n# explicitly build their corresponding sources using PIC.  WIN32 is excluded\n# because PIC code does not exist on that platform and MinGW complains if -fPIC\n# is passed (additionally, libvnc is not used on Windows.)\n\nif(NOT WIN32)\n  set_target_properties(core rdr network rfb\n    PROPERTIES COMPILE_FLAGS -fPIC)\nendif()\n"
  },
  {
    "path": "common/core/CMakeLists.txt",
    "content": "add_library(core STATIC\n  Configuration.cxx\n  Exception.cxx\n  Logger.cxx\n  Logger_file.cxx\n  Logger_stdio.cxx\n  LogWriter.cxx\n  Region.cxx\n  Timer.cxx\n  string.cxx\n  time.cxx\n  xdgdirs.cxx)\n\ntarget_include_directories(core PUBLIC ${CMAKE_SOURCE_DIR}/common)\ntarget_include_directories(core SYSTEM PUBLIC ${PIXMAN_INCLUDE_DIRS})\ntarget_link_libraries(core ${PIXMAN_LIBRARIES})\n\nif(UNIX)\n  target_sources(core PRIVATE Logger_syslog.cxx)\nendif()\n\nif(WIN32)\n  target_link_libraries(core ws2_32)\nendif()\n\nif(UNIX)\n  target_sources(core PRIVATE Logger_syslog.cxx)\nendif()\n\nif(UNIX)\n  libtool_create_control_file(core)\nendif()\n"
  },
  {
    "path": "common/core/Configuration.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2004-2005 Cendio AB.\n * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB\n * Copyright 2011-2025 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Configuration.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <stdlib.h>\n#include <ctype.h>\n#include <string.h>\n\n#include <algorithm>\n#include <stdexcept>\n\n#include <core/Configuration.h>\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rdr/HexOutStream.h>\n#include <rdr/HexInStream.h>\n\nusing namespace core;\n\nstatic LogWriter vlog(\"Config\");\n\n\n// -=- The Global Configuration object\nConfiguration* Configuration::global_ = nullptr;\n\nConfiguration* Configuration::global() {\n  if (!global_)\n    global_ = new Configuration();\n  return global_;\n}\n\n// -=- Configuration implementation\n\nbool Configuration::set(const char* paramName, const char* val,\n                        bool immutable)\n{\n  for (VoidParameter* current: params) {\n    if (strcasecmp(current->getName(), paramName) == 0) {\n      bool b = current->setParam(val);\n      if (b && immutable) \n\tcurrent->setImmutable();\n      return b;\n    }\n  }\n  return false;\n}\n\nVoidParameter* Configuration::get(const char* param)\n{\n  for (VoidParameter* current: params) {\n    if (strcasecmp(current->getName(), param) == 0)\n      return current;\n  }\n  return nullptr;\n}\n\nvoid Configuration::list(int width, int nameWidth) {\n  for (VoidParameter* current: params) {\n    std::string def_str = current->getDefaultStr();\n    std::string desc_str = current->getDescription();\n    if (!def_str.empty())\n      desc_str += \" (default=\" + def_str + \")\";\n    const char* desc = desc_str.c_str();\n    fprintf(stderr,\"  %-*s -\", nameWidth, current->getName());\n    int column = strlen(current->getName());\n    if (column < nameWidth) column = nameWidth;\n    column += 4;\n    while (true) {\n      if (desc[0] == '\\0')\n        break;\n\n      int wordLen = strcspn(desc, \" \\f\\n\\r\\t\\v,\");\n      if (wordLen == 0) {\n        desc++;\n        continue;\n      }\n\n      if (desc[wordLen] == ',')\n        wordLen++;\n\n      if (column + wordLen + 1 > width) {\n        fprintf(stderr,\"\\n%*s\",nameWidth+4,\"\");\n        column = nameWidth+4;\n      }\n      fprintf(stderr, \" \");\n      column++;\n\n      fprintf(stderr, \"%.*s\", wordLen, desc);\n      column += wordLen;\n      desc += wordLen;\n    }\n    fprintf(stderr,\"\\n\");\n  }\n}\n\n\nbool Configuration::remove(const char* param) {\n  std::list<VoidParameter*>::iterator iter;\n\n  iter = std::find_if(params.begin(), params.end(),\n                      [param](VoidParameter* p) {\n                        return strcasecmp(p->getName(), param) == 0;\n                      });\n  if (iter == params.end())\n    return false;\n\n  params.erase(iter);\n  return true;\n}\n\nint Configuration::handleArg(int argc, char* argv[], int index)\n{\n  std::string param, val;\n  const char* equal = strchr(argv[index], '=');\n\n  if (equal == argv[index])\n    return 0;\n\n  if (equal) {\n    param.assign(argv[index], equal-argv[index]);\n    val.assign(equal+1);\n  } else {\n    param.assign(argv[index]);\n  }\n\n  if ((param.length() > 0) && (param[0] == '-')) {\n    // allow gnu-style --<option>\n    if ((param.length() > 1) && (param[1] == '-'))\n      param = param.substr(2);\n    else\n      param = param.substr(1);\n  } else {\n    // All command line arguments need either an initial '-', or an '='\n    if (!equal)\n      return 0;\n  }\n\n  if (equal)\n    return set(param.c_str(), val.c_str()) ? 1 : 0;\n\n  for (VoidParameter* current: params) {\n    if (strcasecmp(current->getName(), param.c_str()) != 0)\n      continue;\n\n    // We need to resolve an ambiguity for booleans\n    if (dynamic_cast<BoolParameter*>(current) != nullptr) {\n      if (index+1 < argc) {\n        // FIXME: Should not duplicate the list of values here\n        if ((strcasecmp(argv[index+1], \"0\") == 0) ||\n            (strcasecmp(argv[index+1], \"1\") == 0) ||\n            (strcasecmp(argv[index+1], \"on\") == 0) ||\n            (strcasecmp(argv[index+1], \"off\") == 0) ||\n            (strcasecmp(argv[index+1], \"true\") == 0) ||\n            (strcasecmp(argv[index+1], \"false\") == 0) ||\n            (strcasecmp(argv[index+1], \"yes\") == 0) ||\n            (strcasecmp(argv[index+1], \"no\") == 0)) {\n            return current->setParam(argv[index+1]) ? 2 : 0;\n        }\n      }\n    }\n\n    if (current->setParam())\n      return 1;\n\n    if (index+1 >= argc)\n      return 0;\n\n    return current->setParam(argv[index+1]) ? 2 : 0;\n  }\n\n  return 0;\n}\n\n\n// -=- VoidParameter\n\nVoidParameter::VoidParameter(const char* name_, const char* desc_)\n  : immutable(false), name(name_), description(desc_)\n{\n  Configuration *conf;\n\n  conf = Configuration::global();\n  conf->params.push_back(this);\n  conf->params.sort([](const VoidParameter* a, const VoidParameter* b) {\n    return strcasecmp(a->getName(), b->getName()) < 0;\n  });\n}\n\nVoidParameter::~VoidParameter() {\n  Configuration *conf;\n\n  conf = Configuration::global();\n  conf->params.remove(this);\n}\n\nconst char*\nVoidParameter::getName() const {\n  return name;\n}\n\nconst char*\nVoidParameter::getDescription() const {\n  return description;\n}\n\nbool VoidParameter::setParam() {\n  return false;\n}\n\nbool VoidParameter::isDefault() const {\n  return getDefaultStr() == getValueStr();\n}\n\nvoid\nVoidParameter::setImmutable() {\n  vlog.debug(\"Set immutable %s\", getName());\n  immutable = true;\n}\n\n// -=- AliasParameter\n\nAliasParameter::AliasParameter(const char* name_, const char* desc_,\n                               VoidParameter* param_)\n  : VoidParameter(name_, desc_), param(param_) {\n}\n\nbool\nAliasParameter::setParam(const char* v) {\n  return param->setParam(v);\n}\n\nbool AliasParameter::setParam() {\n  return param->setParam();\n}\n\nstd::string AliasParameter::getDefaultStr() const {\n  return \"\";\n}\n\nstd::string AliasParameter::getValueStr() const {\n  return param->getValueStr();\n}\n\nvoid\nAliasParameter::setImmutable() {\n  vlog.debug(\"Set immutable %s (Alias)\", getName());\n  param->setImmutable();\n}\n\n\n// -=- BoolParameter\n\nBoolParameter::BoolParameter(const char* name_, const char* desc_, bool v)\n: VoidParameter(name_, desc_), value(v), def_value(v) {\n}\n\nbool\nBoolParameter::setParam(const char* v) {\n  if (immutable) return true;\n\n  if (*v == 0 || strcasecmp(v, \"1\") == 0 || strcasecmp(v, \"on\") == 0\n      || strcasecmp(v, \"true\") == 0 || strcasecmp(v, \"yes\") == 0)\n    setParam(true);\n  else if (strcasecmp(v, \"0\") == 0 || strcasecmp(v, \"off\") == 0\n           || strcasecmp(v, \"false\") == 0 || strcasecmp(v, \"no\") == 0)\n    setParam(false);\n  else {\n    vlog.error(\"Bool parameter %s: Invalid value '%s'\", getName(), v);\n    return false;\n  }\n\n  return true;\n}\n\nbool BoolParameter::setParam() {\n  setParam(true);\n  return true;\n}\n\nvoid BoolParameter::setParam(bool b) {\n  if (immutable) return;\n  value = b;\n  vlog.debug(\"Set %s(Bool) to %s\", getName(), getValueStr().c_str());\n}\n\nstd::string BoolParameter::getDefaultStr() const {\n  return def_value ? \"on\" : \"off\";\n}\n\nstd::string BoolParameter::getValueStr() const {\n  return value ? \"on\" : \"off\";\n}\n\nBoolParameter::operator bool() const {\n  return value;\n}\n\n// -=- IntParameter\n\nIntParameter::IntParameter(const char* name_, const char* desc_, int v,\n                           int minValue_, int maxValue_)\n  : VoidParameter(name_, desc_), value(v), def_value(v),\n    minValue(minValue_), maxValue(maxValue_)\n{\n  if (v < minValue || v > maxValue) {\n    vlog.error(\"Invalid default value %d for %s\", v, getName());\n    throw std::invalid_argument(\"Invalid default value\");\n  }\n}\n\nbool\nIntParameter::setParam(const char* v) {\n  char* end;\n  long n;\n  if (immutable) return true;\n  n = strtol(v, &end, 0);\n  if ((*end != 0) || (n < INT_MIN) || (n > INT_MAX)) {\n    vlog.error(\"Int parameter %s: Invalid value '%s'\", getName(), v);\n    return false;\n  }\n  return setParam(n);\n}\n\nbool\nIntParameter::setParam(int v) {\n  if (immutable) return true;\n  if (v < minValue || v > maxValue) {\n    vlog.error(\"Int parameter %s: Invalid value '%d'\", getName(), v);\n    return false;\n  }\n  vlog.debug(\"Set %s(Int) to %d\", getName(), v);\n  value = v;\n  return true;\n}\n\nstd::string IntParameter::getDefaultStr() const {\n  char result[16];\n  sprintf(result, \"%d\", def_value);\n  return result;\n}\n\nstd::string IntParameter::getValueStr() const {\n  char result[16];\n  sprintf(result, \"%d\", value);\n  return result;\n}\n\nIntParameter::operator int() const {\n  return value;\n}\n\n// -=- StringParameter\n\nStringParameter::StringParameter(const char* name_, const char* desc_,\n                                 const char* v)\n  : VoidParameter(name_, desc_), value(v?v:\"\"), def_value(v?v:\"\")\n{\n  if (!v) {\n    vlog.error(\"Default value <null> for %s not allowed\",name_);\n    throw std::invalid_argument(\"Default value <null> not allowed\");\n  }\n}\n\nbool StringParameter::setParam(const char* v) {\n  if (immutable) return true;\n  if (!v)\n    throw std::invalid_argument(\"setParam(<null>) not allowed\");\n  vlog.debug(\"Set %s(String) to %s\", getName(), v);\n  value = v;\n  return true;\n}\n\nstd::string StringParameter::getDefaultStr() const {\n  return def_value;\n}\n\nstd::string StringParameter::getValueStr() const {\n  return value;\n}\n\nStringParameter::operator const char *() const {\n  return value.c_str();\n}\n\n// -=- EnumParameter\n\nEnumParameter::EnumParameter(const char* name_, const char* desc_,\n                             const std::set<const char*>& enums_,\n                             const char* v)\n  : VoidParameter(name_, desc_), value(v?v:\"\"), def_value(v?v:\"\")\n{\n  if (!v) {\n    vlog.error(\"Default value <null> for %s not allowed\", name_);\n    throw std::invalid_argument(\"Default value <null> not allowed\");\n  }\n\n  for (const char* e: enums_) {\n    if (!e) {\n      vlog.error(\"Enumeration <null> for %s not allowed\", name_);\n      throw std::invalid_argument(\"Enumeration <null> not allowed\");\n    }\n    enums.insert(e);\n  }\n\n  if (std::find(enums.begin(), enums.end(), def_value) == enums.end()) {\n    vlog.error(\"Default value %s for %s is not in list of valid values\",\n               def_value.c_str(), name_);\n    throw std::invalid_argument(\"Default value is not in list of valid values\");\n  }\n}\n\nbool EnumParameter::setParam(const char* v)\n{\n  std::set<std::string>::const_iterator iter;\n  if (immutable) return true;\n  if (!v)\n    throw std::invalid_argument(\"setParam(<null>) not allowed\");\n  iter = std::find_if(enums.begin(), enums.end(),\n                      [v](const std::string& e) {\n                        return strcasecmp(e.c_str(), v) == 0;\n                      });\n  if (iter == enums.end()) {\n    vlog.error(\"Enum parameter %s: Invalid value '%s'\", getName(), v);\n    return false;\n  }\n  vlog.debug(\"Set %s(Enum) to %s\", getName(), iter->c_str());\n  value = *iter;\n  return true;\n}\n\nstd::string EnumParameter::getDefaultStr() const\n{\n  return def_value;\n}\n\nstd::string EnumParameter::getValueStr() const\n{\n  return value;\n}\n\nbool EnumParameter::operator==(const char* other) const\n{\n  return strcasecmp(value.c_str(), other) == 0;\n}\n\nbool EnumParameter::operator==(const std::string& other) const\n{\n  return *this == other.c_str();\n}\n\nbool EnumParameter::operator!=(const char* other) const\n{\n  return strcasecmp(value.c_str(), other) != 0;\n}\n\nbool EnumParameter::operator!=(const std::string& other) const\n{\n  return *this != other.c_str();\n}\n\n// -=- BinaryParameter\n\nBinaryParameter::BinaryParameter(const char* name_, const char* desc_,\n\t\t\t\t const uint8_t* v, size_t l)\n: VoidParameter(name_, desc_),\n  value(nullptr), length(0), def_value(nullptr), def_length(0) {\n  if (l) {\n    assert(v);\n    value = new uint8_t[l];\n    length = l;\n    memcpy(value, v, l);\n    def_value = new uint8_t[l];\n    def_length = l;\n    memcpy(def_value, v, l);\n  }\n}\nBinaryParameter::~BinaryParameter() {\n  delete [] value;\n  delete [] def_value;\n}\n\nbool BinaryParameter::setParam(const char* v) {\n  if (immutable) return true;\n  std::vector<uint8_t> newValue = hexToBin(v, strlen(v));\n  if (newValue.empty() && strlen(v) > 0)\n    return false;\n  setParam(newValue.data(), newValue.size());\n  return true;\n}\n\nvoid BinaryParameter::setParam(const uint8_t* v, size_t len) {\n  if (immutable) return; \n  vlog.debug(\"Set %s(Binary)\", getName());\n  delete [] value;\n  value = nullptr;\n  length = 0;\n  if (len) {\n    assert(v);\n    value = new uint8_t[len];\n    length = len;\n    memcpy(value, v, len);\n  }\n}\n\nstd::string BinaryParameter::getDefaultStr() const {\n  return binToHex(def_value, def_length);\n}\n\nstd::string BinaryParameter::getValueStr() const {\n  return binToHex(value, length);\n}\n\nstd::vector<uint8_t> BinaryParameter::getData() const {\n  std::vector<uint8_t> out(length);\n  memcpy(out.data(), value, length);\n  return out;\n}\n\n// -=- ListParameter template\n\ntemplate<typename ValueType>\nListParameter<ValueType>::ListParameter(const char* name_,\n                                        const char* desc_,\n                                        const ListType& v)\n  : VoidParameter(name_, desc_), value(v), def_value(v)\n{\n}\n\ntemplate<typename ValueType>\nbool ListParameter<ValueType>::setParam(const char* v)\n{\n  std::vector<std::string> entries;\n  ListType new_value;\n\n  if (immutable)\n    return true;\n\n  // setParam({}) ends up as setParam(nullptr)\n  if (v != nullptr)\n    entries = split(v, ',');\n\n  for (std::string& entry : entries) {\n    ValueType e;\n\n    entry.erase(0, entry.find_first_not_of(\" \\f\\n\\r\\t\\v\"));\n    entry.erase(entry.find_last_not_of(\" \\f\\n\\r\\t\\v\")+1);\n\n    // Special case, entire v was just whitespace\n    if (entry.empty() && (entries.size() == 1))\n      break;\n\n    if (!decodeEntry(entry.c_str(), &e)) {\n      vlog.error(\"List parameter %s: Invalid value '%s'\",\n                 getName(), entry.c_str());\n      return false;\n    }\n\n    new_value.push_back(e);\n  }\n\n  return setParam(new_value);\n}\n\ntemplate<typename ValueType>\nbool ListParameter<ValueType>::setParam(const ListType& v)\n{\n  ListType vnorm;\n  if (immutable)\n    return true;\n  for (const ValueType& entry : v) {\n    if (!validateEntry(entry)) {\n      vlog.error(\"List parameter %s: Invalid value '%s'\", getName(),\n                 encodeEntry(entry).c_str());\n      return false;\n    }\n    vnorm.push_back(normaliseEntry(entry));\n  }\n  value = vnorm;\n  vlog.debug(\"set %s(List) to %s\", getName(), getValueStr().c_str());\n  return true;\n}\n\ntemplate<typename ValueType>\nstd::string ListParameter<ValueType>::getDefaultStr() const\n{\n  std::string result;\n\n  for (ValueType entry : def_value) {\n    // FIXME: Might want to add a space here as well for readability,\n    //        but this would sacrifice backward compatibility\n    if (!result.empty())\n      result += ',';\n    result += encodeEntry(entry);\n  }\n\n  return result;\n}\n\ntemplate<typename ValueType>\nstd::string ListParameter<ValueType>::getValueStr() const\n{\n  std::string result;\n\n  for (ValueType entry : value) {\n    // FIXME: Might want to add a space here as well for readability,\n    //        but this would sacrifice backward compatibility\n    if (!result.empty())\n      result += ',';\n    result += encodeEntry(entry);\n  }\n\n  return result;\n}\n\ntemplate<typename ValueType>\ntypename ListParameter<ValueType>::const_iterator ListParameter<ValueType>::begin() const\n{\n  return value.begin();\n}\n\ntemplate<typename ValueType>\ntypename ListParameter<ValueType>::const_iterator ListParameter<ValueType>::end() const\n{\n  return value.end();\n}\n\ntemplate<typename ValueType>\nbool ListParameter<ValueType>::validateEntry(const ValueType& /*entry*/) const\n{\n  return true;\n}\n\ntemplate<typename ValueType>\nValueType ListParameter<ValueType>::normaliseEntry(const ValueType& entry) const\n{\n  return entry;\n}\n\n// -=- IntListParameter\n\ntemplate class core::ListParameter<int>;\n\nIntListParameter::IntListParameter(const char* name_, const char* desc_,\n                                   const ListType& v,\n                                   int minValue_, int maxValue_)\n  : ListParameter<int>(name_, desc_, v),\n    minValue(minValue_), maxValue(maxValue_)\n{\n  for (int entry : v) {\n    if (!validateEntry(entry)) {\n      vlog.error(\"Invalid default value %d for %s\", entry, getName());\n      throw std::invalid_argument(\"Invalid default value\");\n    }\n  }\n}\n\nbool IntListParameter::decodeEntry(const char* entry, int* out) const\n{\n  long n;\n  char *end;\n\n  assert(entry);\n  assert(out);\n\n  if (entry[0] == '\\0')\n    return false;\n\n  n = strtol(entry, &end, 0);\n  if ((*end != 0) || (n < INT_MIN) || (n > INT_MAX))\n    return false;\n\n  *out = n;\n\n  return true;\n}\n\nstd::string IntListParameter::encodeEntry(const int& entry) const\n{\n  char valstr[16];\n  sprintf(valstr, \"%d\", entry);\n  return valstr;\n}\n\nbool IntListParameter::validateEntry(const int& entry) const\n{\n  return (entry >= minValue) && (entry <= maxValue);\n}\n\n// -=- StringListParameter\n\ntemplate class core::ListParameter<std::string>;\n\nStringListParameter::StringListParameter(const char* name_,\n                                         const char* desc_,\n                                         const std::list<const char*>& v_)\n  : ListParameter<std::string>(name_, desc_, {})\n{\n  for (const char* v: v_) {\n    if (!v) {\n      vlog.error(\"Default value <null> for %s not allowed\", name_);\n      throw std::invalid_argument(\"Default value <null> not allowed\");\n    }\n    value.push_back(v);\n    def_value.push_back(v);\n  }\n}\n\nStringListParameter::const_iterator StringListParameter::begin() const\n{\n  return ListParameter<std::string>::begin();\n}\n\nStringListParameter::const_iterator StringListParameter::end() const\n{\n  return ListParameter<std::string>::end();\n}\n\nbool StringListParameter::decodeEntry(const char* entry, std::string* out) const\n{\n  *out = entry;\n  return true;\n}\n\nstd::string StringListParameter::encodeEntry(const std::string& entry) const\n{\n  return entry;\n}\n\n// -=- EnumListEntry\n\nEnumListEntry::EnumListEntry(const std::string& v)\n  : value(v)\n{\n}\n\nstd::string EnumListEntry::getValueStr() const\n{\n  return value;\n}\n\nbool EnumListEntry::operator==(const char* other) const\n{\n  return strcasecmp(value.c_str(), other) == 0;\n}\n\nbool EnumListEntry::operator==(const std::string& other) const\n{\n  return *this == other.c_str();\n}\n\nbool EnumListEntry::operator!=(const char* other) const\n{\n  return strcasecmp(value.c_str(), other) != 0;\n}\n\nbool EnumListEntry::operator!=(const std::string& other) const\n{\n  return *this != other.c_str();\n}\n\n// -=- EnumListParameter\n\nEnumListParameter::EnumListParameter(const char* name_,\n                                     const char* desc_,\n                                     const std::set<const char*>& enums_,\n                                     const std::list<const char*>& v_)\n  : ListParameter<std::string>(name_, desc_, {})\n{\n  for (const char* v: v_) {\n    if (!v) {\n      vlog.error(\"Default value <null> for %s not allowed\", name_);\n      throw std::invalid_argument(\"Default value <null> not allowed\");\n    }\n    value.push_back(v);\n    def_value.push_back(v);\n  }\n\n  for (const char* e: enums_) {\n    if (!e) {\n      vlog.error(\"Enumeration <null> for %s not allowed\", name_);\n      throw std::invalid_argument(\"Enumeration <null> not allowed\");\n    }\n    enums.insert(e);\n  }\n\n  for (const std::string& def_entry : def_value) {\n    if (std::find(enums.begin(), enums.end(), def_entry) == enums.end()) {\n      vlog.error(\"Default value %s for %s is not in list of valid values\",\n                 def_entry.c_str(), name_);\n      throw std::invalid_argument(\"Default value is not in list of valid values\");\n    }\n  }\n}\n\nEnumListParameter::const_iterator EnumListParameter::begin() const\n{\n  return ListParameter<std::string>::begin();\n}\n\nEnumListParameter::const_iterator EnumListParameter::end() const\n{\n  return ListParameter<std::string>::end();\n}\n\nbool EnumListParameter::decodeEntry(const char* entry, std::string* out) const\n{\n  *out = entry;\n  return true;\n}\n\nstd::string EnumListParameter::encodeEntry(const std::string& entry) const\n{\n  return entry;\n}\n\nbool EnumListParameter::validateEntry(const std::string& entry) const\n{\n  for (const std::string& e : enums) {\n    if (strcasecmp(e.c_str(), entry.c_str()) == 0)\n      return true;\n  }\n  return false;\n}\n\nstd::string EnumListParameter::normaliseEntry(const std::string& entry) const\n{\n  for (const std::string& e : enums) {\n    if (strcasecmp(e.c_str(), entry.c_str()) == 0)\n      return e;\n  }\n  throw std::logic_error(\"Entry is not in list of valid values\");\n}\n"
  },
  {
    "path": "common/core/Configuration.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2025 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Configuration.h\n//\n// This header defines a set of classes used to represent configuration\n// parameters of different types.  Instances of the different parameter\n// types are associated with instances of the Configuration class, and\n// are each given a unique name.  The Configuration class provides a\n// generic API through which parameters may be located by name and their\n// value set, thus removing the need to write platform-specific code.\n// Simply defining a new parameter and associating it with a Configuration\n// will allow it to be configured by the user.\n//\n// If no Configuration is specified when creating a Parameter, then the\n// global Configuration will be assumed.\n//\n// Configurations can be \"chained\" into groups.  Each group has a root\n// Configuration, a pointer to which should be passed to the constructors\n// of the other group members.  set() and get() operations called on the\n// root will iterate through all of the group's members.\n//\n// NB: On platforms that support Threading, locking is performed to protect\n//     complex parameter types from concurrent access (e.g. strings).\n// NB: NO LOCKING is performed when linking Configurations to groups\n//     or when adding Parameters to Configurations.\n\n#ifndef __CORE_CONFIGURATION_H__\n#define __CORE_CONFIGURATION_H__\n\n#include <limits.h>\n#include <stdint.h>\n\n#include <list>\n#include <set>\n#include <string>\n#include <vector>\n\nnamespace core {\n\n  class VoidParameter;\n\n  // -=- Configuration\n  //     Class used to access parameters.\n\n  class Configuration {\n  public:\n    // - Create a new Configuration object\n    Configuration() {}\n\n    // - Set named parameter to value\n    bool set(const char* param, const char* value, bool immutable=false);\n\n    // - Get named parameter\n    VoidParameter* get(const char* param);\n\n    // - List the parameters of this Configuration group\n    void list(int width=79, int nameWidth=10);\n\n    // - Remove a parameter from this Configuration group\n    bool remove(const char* param);\n\n    // - handleArg\n    //   Parse a command line argument into a parameter, returning how\n    //   many arguments were consumed\n    int handleArg(int argc, char* argv[], int index);\n\n\n    // - Iterate over all parameters\n    std::list<VoidParameter*>::iterator begin() { return params.begin(); }\n    std::list<VoidParameter*>::iterator end() { return params.end(); }\n\n    // - Returns the number of parameters\n    int size() { return params.size(); }\n\n    // - Get the Global Configuration object\n    //   NB: This call does NOT lock the Configuration system.\n    //       ALWAYS ensure that if you have ANY global Parameters,\n    //       then they are defined as global objects, to ensure that\n    //       global() is called when only the main thread is running.\n    static Configuration* global();\n\n    // - Container for process-wide Global parameters\n    static bool setParam(const char* param, const char* value, bool immutable=false) {\n      return global()->set(param, value, immutable);\n    }\n    static VoidParameter* getParam(const char* param) { return global()->get(param); }\n    static void listParams(int width=79, int nameWidth=10) {\n      global()->list(width, nameWidth);\n    }\n    static bool removeParam(const char* param) {\n      return global()->remove(param);\n    }\n    static int handleParamArg(int argc, char* argv[], int index) {\n      return global()->handleArg(argc, argv, index);\n    }\n\n  private:\n    friend class VoidParameter;\n\n    // - List of Parameters\n    std::list<VoidParameter*> params;\n\n    // The process-wide, Global Configuration object\n    static Configuration* global_;\n  };\n\n  // -=- VoidParameter\n  //     Configuration parameter base-class.\n\n  class VoidParameter {\n  public:\n    VoidParameter(const char* name_, const char* desc_);\n    virtual  ~VoidParameter();\n    const char* getName() const;\n    const char* getDescription() const;\n\n    virtual bool setParam(const char* value)  = 0;\n    virtual bool setParam();\n    virtual std::string getDefaultStr() const = 0;\n    virtual std::string getValueStr() const = 0;\n\n    virtual bool isDefault() const;\n\n    virtual void setImmutable();\n\n  protected:\n    friend class Configuration;\n\n    VoidParameter* _next;\n    bool immutable;\n    const char* name;\n    const char* description;\n  };\n\n  class AliasParameter : public VoidParameter {\n  public:\n    AliasParameter(const char* name_, const char* desc_,VoidParameter* param_);\n    bool setParam(const char* value) override;\n    bool setParam() override;\n    std::string getDefaultStr() const override;\n    std::string getValueStr() const override;\n    void setImmutable() override;\n  private:\n    VoidParameter* param;\n  };\n\n  class BoolParameter : public VoidParameter {\n  public:\n    BoolParameter(const char* name_, const char* desc_, bool v);\n    bool setParam(const char* value) override;\n    bool setParam() override;\n    virtual void setParam(bool b);\n    std::string getDefaultStr() const override;\n    std::string getValueStr() const override;\n    operator bool() const;\n  protected:\n    bool value;\n    bool def_value;\n  };\n\n  class IntParameter : public VoidParameter {\n  public:\n    IntParameter(const char* name_, const char* desc_, int v,\n                 int minValue=INT_MIN, int maxValue=INT_MAX);\n    using VoidParameter::setParam;\n    bool setParam(const char* value) override;\n    virtual bool setParam(int v);\n    std::string getDefaultStr() const override;\n    std::string getValueStr() const override;\n    operator int() const;\n  protected:\n    int value;\n    int def_value;\n    int minValue, maxValue;\n  };\n\n  class StringParameter : public VoidParameter {\n  public:\n    StringParameter(const char* name_, const char* desc_, const char* v);\n    bool setParam(const char* value) override;\n    std::string getDefaultStr() const override;\n    std::string getValueStr() const override;\n    operator const char*() const;\n  protected:\n    std::string value;\n    std::string def_value;\n  };\n\n  class EnumParameter : public VoidParameter {\n  public:\n    EnumParameter(const char* name_, const char* desc_,\n                  const std::set<const char*>& enums, const char* v);\n    bool setParam(const char* value) override;\n    std::string getDefaultStr() const override;\n    std::string getValueStr() const override;\n    bool operator==(const char* other) const;\n    bool operator==(const std::string& other) const;\n    bool operator!=(const char* other) const;\n    bool operator!=(const std::string& other) const;\n    // operator const char*() omitted on purpose to force usage of above\n    // comparison operators\n  protected:\n    std::string value;\n    std::string def_value;\n    std::set<std::string> enums;\n  };\n\n  class BinaryParameter : public VoidParameter {\n  public:\n    BinaryParameter(const char* name_, const char* desc_,\n                    const uint8_t* v, size_t l);\n    using VoidParameter::setParam;\n    ~BinaryParameter() override;\n    bool setParam(const char* value) override;\n    virtual void setParam(const uint8_t* v, size_t l);\n    std::string getDefaultStr() const override;\n    std::string getValueStr() const override;\n\n    std::vector<uint8_t> getData() const;\n\n  protected:\n    uint8_t* value;\n    size_t length;\n    uint8_t* def_value;\n    size_t def_length;\n  };\n\n  template<typename ValueType>\n  class ListParameter : public VoidParameter {\n  public:\n    typedef std::list<ValueType> ListType;\n    typedef typename ListType::const_iterator const_iterator;\n\n    ListParameter(const char* name_, const char* desc_,\n                  const ListType& v);\n    using VoidParameter::setParam;\n    bool setParam(const char* value) override;\n    virtual bool setParam(const ListType& v);\n    std::string getDefaultStr() const override;\n    std::string getValueStr() const override;\n\n    const_iterator begin() const;\n    const_iterator end() const;\n\n  protected:\n    virtual bool decodeEntry(const char* entry, ValueType* out) const = 0;\n    virtual std::string encodeEntry(const ValueType& entry) const = 0;\n    virtual bool validateEntry(const ValueType& entry) const;\n    virtual ValueType normaliseEntry(const ValueType& entry) const;\n\n  protected:\n    ListType value;\n    ListType def_value;\n  };\n\n  class IntListParameter : public ListParameter<int> {\n  public:\n    IntListParameter(const char* name_, const char* desc_,\n                     const ListType& v,\n                     int minValue=INT_MIN, int maxValue=INT_MAX);\n  protected:\n    bool decodeEntry(const char* entry, int* out) const override;\n    std::string encodeEntry(const int& entry) const override;\n    bool validateEntry(const int& entry) const override;\n\n  protected:\n    int minValue, maxValue;\n  };\n\n  class StringListParameter : public ListParameter<std::string> {\n  public:\n    StringListParameter(const char* name_, const char* desc_,\n                        const std::list<const char*>& v);\n\n    class const_iterator :  public ListType::const_iterator {\n    public:\n      const_iterator(const ListType::const_iterator& it) : ListType::const_iterator(it) {}\n      const char* operator*() const { return (ListType::const_iterator::operator*()).c_str(); }\n    };\n\n    const_iterator begin() const;\n    const_iterator end() const;\n\n  protected:\n    bool decodeEntry(const char* entry, std::string* out) const override;\n    std::string encodeEntry(const std::string& entry) const override;\n  };\n\n  class EnumListEntry {\n  public:\n    EnumListEntry(const std::string& v);\n    std::string getValueStr() const;\n    bool operator==(const char* other) const;\n    bool operator==(const std::string& other) const;\n    bool operator!=(const char* other) const;\n    bool operator!=(const std::string& other) const;\n    // operator const char*() omitted on purpose to force usage of above\n    // comparison operators\n  protected:\n    std::string value;\n  };\n\n  class EnumListParameter : public ListParameter<std::string> {\n  public:\n    EnumListParameter(const char* name_, const char* desc_,\n                      const std::set<const char*>& enums,\n                      const std::list<const char*>& v);\n\n    class const_iterator :  public ListType::const_iterator {\n    public:\n      const_iterator(const ListType::const_iterator& it) : ListType::const_iterator(it) {}\n      const EnumListEntry operator*() const { return EnumListEntry(ListType::const_iterator::operator*()); }\n      const EnumListEntry operator->() const { return EnumListEntry(*ListType::const_iterator::operator->()); }\n    };\n\n    const_iterator begin() const;\n    const_iterator end() const;\n\n  protected:\n    bool decodeEntry(const char* entry, std::string* out) const override;\n    std::string encodeEntry(const std::string& entry) const override;\n    bool validateEntry(const std::string& entry) const override;\n    std::string normaliseEntry(const std::string& entry) const override;\n\n  protected:\n    std::set<std::string> enums;\n  };\n\n};\n\n#endif // __CORE_CONFIGURATION_H__\n"
  },
  {
    "path": "common/core/Exception.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2010 TigerVNC Team\n * Copyright 2014-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <stdarg.h>\n\n#include <core/Exception.h>\n#include <core/string.h>\n\n#ifdef _WIN32\n#include <winsock2.h>\n#include <windows.h>\n#include <ws2tcpip.h>\n#else\n#include <netdb.h>\n#endif\n\n#include <string.h>\n\nusing namespace core;\n\n\ngetaddrinfo_error::getaddrinfo_error(const char* s, int err_) noexcept\n  : std::runtime_error(core::format(\"%s: %s (%d)\", s,\n                                    strerror(err_).c_str(), err_)),\n    err(err_)\n{\n}\n\ngetaddrinfo_error::getaddrinfo_error(const std::string& s,\n                                     int err_) noexcept\n  : std::runtime_error(core::format(\"%s: %s (%d)\", s.c_str(),\n                                    strerror(err_).c_str(), err_)),\n    err(err_)\n{\n}\n\nstd::string getaddrinfo_error::strerror(int err_) const noexcept\n{\n#ifdef _WIN32\n  char str[256];\n\n  WideCharToMultiByte(CP_UTF8, 0, gai_strerrorW(err_), -1, str,\n                      sizeof(str), nullptr, nullptr);\n\n  return str;\n#else\n  return gai_strerror(err_);\n#endif\n}\n\nposix_error::posix_error(const char* what_arg, int err_) noexcept\n  : std::runtime_error(core::format(\"%s: %s (%d)\", what_arg,\n                                    strerror(err_).c_str(), err_)),\n    err(err_)\n{\n}\n\nposix_error::posix_error(const std::string& what_arg, int err_) noexcept\n  : std::runtime_error(core::format(\"%s: %s (%d)\", what_arg.c_str(),\n                                    strerror(err_).c_str(), err_)),\n    err(err_)\n{\n}\n\nstd::string posix_error::strerror(int err_) const noexcept\n{\n#ifdef _WIN32\n  char str[256];\n\n  WideCharToMultiByte(CP_UTF8, 0, _wcserror(err_), -1, str,\n                      sizeof(str), nullptr, nullptr);\n\n  return str;\n#else\n  return ::strerror(err_);\n#endif\n}\n\n#ifdef WIN32\nwin32_error::win32_error(const char* what_arg, unsigned err_) noexcept\n  : std::runtime_error(core::format(\"%s: %s (%d)\", what_arg,\n                                    strerror(err_).c_str(), err_)),\n    err(err_)\n{\n}\n\nwin32_error::win32_error(const std::string& what_arg,\n                         unsigned err_) noexcept\n  : std::runtime_error(core::format(\"%s: %s (%d)\", what_arg.c_str(),\n                                    strerror(err_).c_str(), err_)),\n    err(err_)\n{\n}\n\nstd::string win32_error::strerror(unsigned err_) const noexcept\n{\n  wchar_t wstr[256];\n  char str[256];\n\n  FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n                 nullptr, err_, 0, wstr, sizeof(wstr), nullptr);\n  WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str,\n                      sizeof(str), nullptr, nullptr);\n\n  int l = strlen(str);\n  if ((l >= 2) && (str[l-2] == '\\r') && (str[l-1] == '\\n'))\n      str[l-2] = 0;\n\n  return str;\n}\n#endif\n"
  },
  {
    "path": "common/core/Exception.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2010 TigerVNC Team\n * Copyright 2015-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __CORE_EXCEPTION_H__\n#define __CORE_EXCEPTION_H__\n\n#include <stdexcept>\n#include <string>\n\nnamespace core {\n\n  class posix_error : public std::runtime_error {\n  public:\n    int err;\n    posix_error(const char* what_arg, int err_) noexcept;\n    posix_error(const std::string& what_arg, int err_) noexcept;\n  private:\n    std::string strerror(int err_) const noexcept;\n  };\n\n#ifdef WIN32\n  class win32_error : public std::runtime_error {\n  public:\n    unsigned err;\n    win32_error(const char* what_arg, unsigned err_) noexcept;\n    win32_error(const std::string& what_arg, unsigned err_) noexcept;\n  private:\n    std::string strerror(unsigned err_) const noexcept;\n  };\n#endif\n\n#ifdef WIN32\n  class socket_error : public win32_error {\n  public:\n    socket_error(const char* what_arg, unsigned err_) noexcept : win32_error(what_arg, err_) {}\n    socket_error(const std::string& what_arg, unsigned err_) noexcept : win32_error(what_arg, err_) {}\n  };\n#else\n  class socket_error : public posix_error {\n  public:\n    socket_error(const char* what_arg, unsigned err_) noexcept : posix_error(what_arg, err_) {}\n    socket_error(const std::string& what_arg, unsigned err_) noexcept : posix_error(what_arg, err_) {}\n  };\n#endif\n\n  class getaddrinfo_error : public std::runtime_error {\n  public:\n    int err;\n    getaddrinfo_error(const char* s, int err_) noexcept;\n    getaddrinfo_error(const std::string& s, int err_) noexcept;\n  private:\n    std::string strerror(int err_) const noexcept;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/core/LogWriter.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- LogWriter.cxx - client-side logging interface\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <core/Configuration.h>\n#include <core/LogWriter.h>\n#include <core/string.h>\n\nusing namespace core;\n\nLogParameter core::logParams;\n\nLogWriter::LogWriter(const char* name)\n  : m_name(name), m_level(0), m_log(nullptr), m_next(log_writers) {\n  log_writers = this;\n}\n\nLogWriter::~LogWriter() {\n  // *** Should remove this logger here!\n}\n\nvoid LogWriter::setLog(Logger *logger) {\n  m_log = logger;\n}\n\nvoid LogWriter::setLevel(int level) {\n  m_level = level;\n}\n\nvoid\nLogWriter::listLogWriters(int /*width*/) {\n  // *** make this respect width...\n  LogWriter* current = log_writers;\n  fprintf(stderr, \"  \");\n  while (current) {\n    fprintf(stderr, \"%s\", current->m_name);\n    current = current->m_next;\n    if (current) fprintf(stderr, \", \");\n  }\n  fprintf(stderr, \"\\n\");\n}\n\nLogWriter* LogWriter::log_writers;\n\nLogWriter*\nLogWriter::getLogWriter(const char* name) {\n  LogWriter* current = log_writers;\n  while (current) {\n    if (strcasecmp(name, current->m_name) == 0) return current;\n      current = current->m_next;\n    }\n  return nullptr;\n}\n\nbool LogWriter::setLogParams(const char* params) {\n  std::vector<std::string> parts;\n  parts = split(params, ':');\n  if (parts.size() != 3) {\n    fprintf(stderr, \"Failed to parse log params:%s\\n\",params);\n    return false;\n  }\n  int level = atoi(parts[2].c_str());\n  Logger* logger = nullptr;\n  if (!parts[1].empty()) {\n    logger = Logger::getLogger(parts[1].c_str());\n    if (!logger)\n      fprintf(stderr, \"No logger found! %s\\n\", parts[1].c_str());\n  }\n  if (parts[0] == \"*\") {\n    LogWriter* current = log_writers;\n    while (current) {\n      current->setLog(logger);\n      current->setLevel(level);\n      current = current->m_next;\n    }\n    return true;\n  } else {\n    LogWriter* logwriter = getLogWriter(parts[0].c_str());\n    if (!logwriter) {\n      fprintf(stderr, \"No logwriter found! %s\\n\", parts[0].c_str());\n    } else {\n      logwriter->setLog(logger);\n      logwriter->setLevel(level);\n      return true;\n    }\n  }\n  return false;\n}\n\n\nLogParameter::LogParameter()\n  : StringListParameter(\"Log\",\n    \"Specifies which log output should be directed to \"\n    \"which target logger, and the level of output to log. \"\n    \"Format is <log>:<target>:<level>[, ...].\",\n    {})\n{\n}\n\nbool LogParameter::setParam(const char* v) {\n  if (immutable) return true;\n  LogWriter::setLogParams(\"*::0\");\n  if (!StringListParameter::setParam(v))\n    return false;\n  for (const char* part : *this) {\n    if (part[0] == '\\0')\n        continue;\n    if (!LogWriter::setLogParams(part))\n      return false;\n  }\n  return true;\n}\n"
  },
  {
    "path": "common/core/LogWriter.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- LogWriter.h - The Log writer class.\n\n#ifndef __CORE_LOG_WRITER_H__\n#define __CORE_LOG_WRITER_H__\n\n#include <stdarg.h>\n\n#include <core/Configuration.h>\n#include <core/Logger.h>\n\n// Each log writer instance has a unique textual name,\n// and is attached to a particular Log instance and\n// is assigned a particular log level.\n\n#define DEF_LOGFUNCTION(name, level) \\\n  inline void v##name(const char* fmt, va_list ap) \\\n    __attribute__((__format__ (__printf__, 2, 0))) \\\n  { \\\n    if (m_log && (level <= m_level))        \\\n      m_log->write(level, m_name, fmt, ap); \\\n  } \\\n  inline void name(const char* fmt, ...) \\\n    __attribute__((__format__ (__printf__, 2, 3))) \\\n  { \\\n    if (m_log && (level <= m_level)) {     \\\n      va_list ap; va_start(ap, fmt);       \\\n      m_log->write(level, m_name, fmt, ap);\\\n      va_end(ap);                          \\\n    }                                      \\\n  }\n\nnamespace core {\n\n  class LogWriter {\n  public:\n    LogWriter(const char* name);\n    ~LogWriter();\n\n    const char *getName() {return m_name;}\n\n    void setLog(Logger *logger);\n    void setLevel(int level);\n    int getLevel(void) { return m_level; }\n\n    inline void write(int level, const char* format, ...)\n      __attribute__((__format__ (__printf__, 3, 4)))\n    {\n      if (m_log && (level <= m_level)) {\n        va_list ap;\n        va_start(ap, format);\n        m_log->write(level, m_name, format, ap);\n        va_end(ap);\n      }\n    }\n\n    static const int LEVEL_ERROR  = 0;\n    static const int LEVEL_STATUS = 10;\n    static const int LEVEL_INFO   = 30;\n    static const int LEVEL_DEBUG  = 100;\n\n    DEF_LOGFUNCTION(error, LEVEL_ERROR)\n    DEF_LOGFUNCTION(status, LEVEL_STATUS)\n    DEF_LOGFUNCTION(info, LEVEL_INFO)\n    DEF_LOGFUNCTION(debug, LEVEL_DEBUG)\n\n    // -=- DIAGNOSTIC & HELPER ROUTINES\n\n    static void listLogWriters(int width=79);\n\n    // -=- CLASS FIELDS & FUNCTIONS\n\n    static LogWriter* log_writers;\n\n    static LogWriter* getLogWriter(const char* name);\n\n    static bool setLogParams(const char* params);\n\n  private:\n    const char* m_name;\n    int m_level;\n    Logger* m_log;\n    LogWriter* m_next;\n  };\n\n  class LogParameter : public StringListParameter {\n  public:\n    LogParameter();\n    bool setParam(const char* v) override;\n    // We explicitly don't inherit setParam(std::list) as we want to\n    // force callers to use the above method to parse the values\n  };\n  extern LogParameter logParams;\n\n};\n\n#endif // __CORE_LOG_WRITER_H__\n"
  },
  {
    "path": "common/core/Logger.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Logger.cxx - support for the Logger and LogWriter classes\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdarg.h>\n#include <stdio.h>\n#include <string.h>\n\n#include <core/Logger.h>\n#include <core/LogWriter.h>\n\nusing namespace core;\n\nLogger* Logger::loggers = nullptr;\n\nLogger::Logger(const char* name)\n  : registered(false), m_name(name), m_next(nullptr)\n{\n}\n\nLogger::~Logger() {\n  // *** Should remove this logger here!\n}\n\nvoid Logger::write(int level, const char *logname, const char* format,\n                   va_list ap)\n{\n  // - Format the supplied data, and pass it to the\n  //   actual log_message function\n  //   The log level is included as a hint for loggers capable of representing\n  //   different log levels in some way.\n  char buf1[4096];\n  vsnprintf(buf1, sizeof(buf1)-1, format, ap);\n  buf1[sizeof(buf1)-1] = 0;\n  char *buf = buf1;\n  while (true) {\n    char *end = strchr(buf, '\\n');\n    if (end)\n      *end = '\\0';\n    write(level, logname, buf);\n    if (!end)\n      break;\n    buf = end + 1;\n  }\n}\n\nvoid\nLogger::registerLogger() {\n  if (!registered) {\n    registered = true;\n    m_next = loggers;\n    loggers=this;\n  }\n}\n    \nLogger*\nLogger::getLogger(const char* name) {\n  Logger* current = loggers;\n  while (current) {\n    if (strcasecmp(name, current->m_name) == 0) return current;\n    current = current->m_next;\n  }\n  return nullptr;\n}\n\nvoid\nLogger::listLoggers() {\n  Logger* current = loggers;\n  while (current) {\n    printf(\"  %s\\n\", current->m_name);\n    current = current->m_next;\n  }\n}\n\n\n"
  },
  {
    "path": "common/core/Logger.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Logger.h - The Logger class.\n\n#ifndef __CORE_LOGGER_H__\n#define __CORE_LOGGER_H__\n\n#include <stdarg.h>\n#include <stdio.h>\n\n// Each log writer instance has a unique textual name,\n// and is attached to a particular Logger instance and\n// is assigned a particular log level.\n\nnamespace core {\n\n  class Logger {\n  public:\n\n    // -=- Create / Destroy a logger\n\n    Logger(const char* name);\n    virtual ~Logger();\n\n    // -=- Get the name of a logger\n\n    const char *getName() {return m_name;}\n\n    // -=- Write data to a log\n\n    virtual void write(int level, const char *logname, const char *text) = 0;\n    void write(int level, const char *logname, const char* format, va_list ap)\n        __attribute__((__format__ (__printf__, 4, 0)));\n\n    // -=- Register a logger\n\n    void registerLogger();\n\n    // -=- CLASS FIELDS & FUNCTIONS\n\n    static Logger* loggers;\n\n    static Logger* getLogger(const char* name);\n\n    static void listLoggers();\n\n  private:\n    bool registered;\n    const char *m_name;\n    Logger *m_next;\n  };\n\n};\n\n#endif // __CORE_LOGGER_H__\n"
  },
  {
    "path": "common/core/Logger_file.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Logger_file.cxx - Logger instance for a file\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <core/Logger_file.h>\n\nusing namespace core;\n\nLogger_File::Logger_File(const char* loggerName)\n  : Logger(loggerName), indent(13), width(79), m_file(nullptr),\n    m_lastLogTime(0)\n{\n  m_filename[0] = '\\0';\n}\n\nLogger_File::~Logger_File()\n{\n  closeFile();\n}\n\nvoid Logger_File::write(int /*level*/, const char *logname, const char *message)\n{\n  if (!m_file) {\n    if (m_filename[0] == '\\0')\n      return;\n    char bakFilename[PATH_MAX];\n    if (snprintf(bakFilename, sizeof(bakFilename),\n                 \"%s.bak\", m_filename) >= (int)sizeof(bakFilename)) {\n      remove(m_filename);\n    } else {\n      remove(bakFilename);\n      rename(m_filename, bakFilename);\n    }\n    m_file = fopen(m_filename, \"w+\");\n    if (!m_file) return;\n  }\n\n  time_t current = time(nullptr);\n  if (current != m_lastLogTime) {\n    m_lastLogTime = current;\n    fprintf(m_file, \"\\n%s\", ctime(&m_lastLogTime));\n  }\n\n  fprintf(m_file,\" %s:\", logname);\n  int column = strlen(logname) + 2;\n  if (column < indent) {\n    fprintf(m_file,\"%*s\",indent-column,\"\");\n    column = indent;\n  }\n  while (true) {\n    const char* s = strchr(message, ' ');\n    int wordLen;\n    if (s) wordLen = s-message;\n    else wordLen = strlen(message);\n\n    if (column + wordLen + 1 > width) {\n      fprintf(m_file,\"\\n%*s\",indent,\"\");\n      column = indent;\n    }\n    fprintf(m_file,\" %.*s\",wordLen,message);\n    column += wordLen + 1;\n    message += wordLen + 1;\n    if (!s) break;\n  }\n  fprintf(m_file,\"\\n\");\n  fflush(m_file);\n}\n\nvoid Logger_File::setFilename(const char* filename)\n{\n  closeFile();\n  m_filename[0] = '\\0';\n  if (strlen(filename) >= sizeof(m_filename))\n    return;\n  strcpy(m_filename, filename);\n}\n\nvoid Logger_File::setFile(FILE* file)\n{\n  closeFile();\n  m_file = file;\n}\n\nvoid Logger_File::closeFile()\n{\n  if (m_file) {\n    fclose(m_file);\n    m_file = nullptr;\n  }\n}\n\nstatic Logger_File logger(\"file\");\n\nbool core::initFileLogger(const char* filename)\n{\n  logger.setFilename(filename);\n  logger.registerLogger();\n  return true;\n}\n"
  },
  {
    "path": "common/core/Logger_file.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Logger_file - log to a file\n\n#ifndef __CORE_LOGGER_FILE_H__\n#define __CORE_LOGGER_FILE_H__\n\n#include <time.h>\n#include <limits.h>\n\n#include <core/Logger.h>\n\nnamespace core {\n\n  class Logger_File : public Logger {\n  public:\n    Logger_File(const char* loggerName);\n    ~Logger_File();\n\n    void write(int level, const char *logname, const char *message) override;\n    void setFilename(const char* filename);\n    void setFile(FILE* file);\n\n    int indent;\n    int width;\n\n  protected:\n    void closeFile();\n    char m_filename[PATH_MAX];\n    FILE* m_file;\n    time_t m_lastLogTime;\n  };\n\n  bool initFileLogger(const char* filename);\n};\n\n#endif\n"
  },
  {
    "path": "common/core/Logger_stdio.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Logger_stdio.cxx - Logger instances for stderr and stdout\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Logger_stdio.h>\n\nusing namespace core;\n\nstatic Logger_StdIO logStdErr(\"stderr\", stderr);\nstatic Logger_StdIO logStdOut(\"stdout\", stdout);\n\nbool core::initStdIOLoggers()\n{\n  logStdErr.registerLogger();\n  logStdOut.registerLogger();\n  return true;\n}\n"
  },
  {
    "path": "common/core/Logger_stdio.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Logger_stdio - standard output logger instances\n\n#ifndef __CORE_LOGGER_STDIO_H__\n#define __CORE_LOGGER_STDIO_H__\n\n#include <core/Logger_file.h>\n\nnamespace core {\n\n  class Logger_StdIO : public Logger_File {\n  public:\n    Logger_StdIO(const char *name, FILE* file) : Logger_File(name) {\n      setFile(file);\n    }\n  };\n\n  bool initStdIOLoggers();\n\n};\n\n#endif\n"
  },
  {
    "path": "common/core/Logger_syslog.cxx",
    "content": "/* Copyright (C) 2015 TigerVNC\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Logger_syslog.cxx - Logger instance for a syslog\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <syslog.h>\n\n#include <core/Logger_syslog.h>\n#include <core/LogWriter.h>\n\nusing namespace core;\n\n\nLogger_Syslog::Logger_Syslog(const char* loggerName)\n  : Logger(loggerName)\n{\n  openlog(nullptr, LOG_CONS | LOG_PID, LOG_USER);\n}\n\nLogger_Syslog::~Logger_Syslog()\n{\n  closelog();\n}\n\nvoid Logger_Syslog::write(int level, const char *logname, const char *message)\n{\n  // Convert our priority level into syslog level\n  int priority;\n  if (level >= LogWriter::LEVEL_DEBUG) {\n    priority = LOG_DEBUG;\n  } else if (level >= LogWriter::LEVEL_INFO) {\n    priority = LOG_INFO;\n  } else if (level >= LogWriter::LEVEL_STATUS) {\n    priority = LOG_NOTICE;\n  } else {\n    priority = LOG_ERR;\n  }\n\n  syslog(priority, \"%s: %s\", logname, message);\n}\n\nstatic Logger_Syslog logger(\"syslog\");\n\nvoid core::initSyslogLogger()\n{\n  logger.registerLogger();\n}\n"
  },
  {
    "path": "common/core/Logger_syslog.h",
    "content": "/* Copyright (C) 2015 TigerVNC\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Logger_syslog - log to syslog\n\n#ifndef __CORE_LOGGER_SYSLOG_H__\n#define __CORE_LOGGER_SYSLOG_H__\n\n#include <time.h>\n\n#include <core/Logger.h>\n\nnamespace core {\n\n  class Logger_Syslog : public Logger {\n  public:\n    Logger_Syslog(const char* loggerName);\n    virtual ~Logger_Syslog();\n\n    void write(int level, const char *logname, const char *message) override;\n  };\n\n  void initSyslogLogger();\n};\n\n#endif\n"
  },
  {
    "path": "common/core/Rect.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// core::Rect and core::Point structures\n\n#ifndef __CORE_RECT_INCLUDED__\n#define __CORE_RECT_INCLUDED__\n\n#include <algorithm>\n\nnamespace core {\n\n  // core::Point\n  //\n  // Represents a point in 2D space, by X and Y coordinates.\n  // Can also be used to represent a delta, or offset, between\n  // two Points.\n  // Functions are provided to allow Points to be compared for\n  // equality and translated by a supplied offset.\n  // Functions are also provided to negate offset Points.\n\n  struct Point {\n    Point() : x(0), y(0) {}\n    Point(int x_, int y_) : x(x_), y(y_) {}\n    inline Point negate() const\n      __attribute__ ((warn_unused_result))\n      {return Point(-x, -y);}\n    inline bool operator==(const Point &p) const {return x==p.x && y==p.y;}\n    inline bool operator!=(const Point &p) const {return x!=p.x || y!=p.y;}\n    inline Point translate(const Point &p) const\n      __attribute__ ((warn_unused_result))\n      {return Point(x+p.x, y+p.y);}\n    inline Point subtract(const Point &p) const\n      __attribute__ ((warn_unused_result))\n      {return Point(x-p.x, y-p.y);}\n    int x, y;\n  };\n\n  // core::Rect\n  //\n  // Represents a rectangular region defined by its top-left (tl)\n  // and bottom-right (br) Points.\n  // Rects may be compared for equality, checked to determine whether\n  // or not they are empty, cleared (made empty), or intersected with\n  // one another.  The bounding rectangle of two existing Rects\n  // may be calculated, as may the area of a Rect.\n  // Rects may also be translated, in the same way as Points, by\n  // an offset specified in a Point structure.\n\n  struct Rect {\n    Rect() {}\n    Rect(Point tl_, Point br_) : tl(tl_), br(br_) {}\n    Rect(int x1, int y1, int x2, int y2) : tl(x1, y1), br(x2, y2) {}\n    inline void setXYWH(int x, int y, int w, int h) {\n      tl.x = x; tl.y = y; br.x = x+w; br.y = y+h;\n    }\n    inline Rect intersect(const Rect &r) const\n      __attribute__ ((warn_unused_result))\n    {\n      Rect result;\n      result.tl.x = std::max(tl.x, r.tl.x);\n      result.tl.y = std::max(tl.y, r.tl.y);\n      result.br.x = std::max(std::min(br.x, r.br.x), result.tl.x);\n      result.br.y = std::max(std::min(br.y, r.br.y), result.tl.y);\n      return result;\n    }\n    inline Rect union_boundary(const Rect &r) const\n      __attribute__ ((warn_unused_result))\n    {\n      if (r.is_empty()) return *this;\n      if (is_empty()) return r;\n      Rect result;\n      result.tl.x = std::min(tl.x, r.tl.x);\n      result.tl.y = std::min(tl.y, r.tl.y);\n      result.br.x = std::max(br.x, r.br.x);\n      result.br.y = std::max(br.y, r.br.y);\n      return result;\n    }\n    inline Rect translate(const Point &p) const\n      __attribute__ ((warn_unused_result))\n    {\n      return Rect(tl.translate(p), br.translate(p));\n    }\n    inline bool operator==(const Rect &r) const {return r.tl == tl && r.br == br;}\n    inline bool operator!=(const Rect &r) const {return r.tl != tl || r.br != br;}\n    inline bool is_empty() const {return (tl.x >= br.x) || (tl.y >= br.y);}\n    inline void clear() {tl = Point(); br = Point();}\n    inline bool enclosed_by(const Rect &r) const {\n      return (tl.x>=r.tl.x) && (tl.y>=r.tl.y) && (br.x<=r.br.x) && (br.y<=r.br.y);\n    }\n    inline bool overlaps(const Rect &r) const {\n      return tl.x < r.br.x && tl.y < r.br.y && br.x > r.tl.x && br.y > r.tl.y;\n    }\n    inline int area() const {return is_empty() ? 0 : (br.x-tl.x)*(br.y-tl.y);}\n    inline Point dimensions() const {return Point(width(), height());}\n    inline int width() const {return br.x-tl.x;}\n    inline int height() const {return br.y-tl.y;}\n    inline bool contains(const Point &p) const {\n      return (tl.x<=p.x) && (tl.y<=p.y) && (br.x>p.x) && (br.y>p.y);\n    }\n    Point tl;\n    Point br;\n  };\n}\n#endif // __CORE_RECT_INCLUDED__\n"
  },
  {
    "path": "common/core/Region.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2016-2020 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n#include <core/Region.h>\n\nextern \"C\" {\n#include <pixman.h>\n}\n\nusing namespace core;\n\nstatic LogWriter vlog(\"Region\");\n\nRegion::Region()\n{\n  rgn = new struct pixman_region16;\n  pixman_region_init(rgn);\n}\n\nRegion::Region(const Rect& r)\n{\n  rgn = new struct pixman_region16;\n  pixman_region_init_rect(rgn, r.tl.x, r.tl.y, r.width(), r.height());\n}\n\nRegion::Region(const Region& r)\n{\n  rgn = new struct pixman_region16;\n  pixman_region_init(rgn);\n  pixman_region_copy(rgn, r.rgn);\n}\n\nRegion::~Region()\n{\n  pixman_region_fini(rgn);\n  delete rgn;\n}\n\nRegion& Region::operator=(const Region& r)\n{\n  pixman_region_copy(rgn, r.rgn);\n  return *this;\n}\n\nvoid Region::clear()\n{\n  // pixman_region_clear() isn't available on some older systems\n  pixman_region_fini(rgn);\n  pixman_region_init(rgn);\n}\n\nvoid Region::reset(const Rect& r)\n{\n  pixman_region_fini(rgn);\n  pixman_region_init_rect(rgn, r.tl.x, r.tl.y, r.width(), r.height());\n}\n\nvoid Region::translate(const Point& delta)\n{\n  pixman_region_translate(rgn, delta.x, delta.y);\n}\n\nvoid Region::assign_intersect(const Region& r)\n{\n  pixman_region_intersect(rgn, rgn, r.rgn);\n}\n\nvoid Region::assign_union(const Region& r)\n{\n  pixman_region_union(rgn, rgn, r.rgn);\n}\n\nvoid Region::assign_subtract(const Region& r)\n{\n  pixman_region_subtract(rgn, rgn, r.rgn);\n}\n\nRegion Region::intersect(const Region& r) const\n{\n  Region ret;\n  pixman_region_intersect(ret.rgn, rgn, r.rgn);\n  return ret;\n}\n\nRegion Region::union_(const Region& r) const\n{\n  Region ret;\n  pixman_region_union(ret.rgn, rgn, r.rgn);\n  return ret;\n}\n\nRegion Region::subtract(const Region& r) const\n{\n  Region ret;\n  pixman_region_subtract(ret.rgn, rgn, r.rgn);\n  return ret;\n}\n\nbool Region::operator==(const Region& r) const\n{\n  return pixman_region_equal(rgn, r.rgn);\n}\n\nbool Region::operator!=(const Region& r) const\n{\n  return !pixman_region_equal(rgn, r.rgn);\n}\n\nint Region::numRects() const\n{\n  return pixman_region_n_rects(rgn);\n}\n\nbool Region::get_rects(std::vector<Rect>* rects,\n                       bool left2right, bool topdown) const\n{\n  int nRects;\n  const pixman_box16_t* boxes;\n  int xInc, yInc, i;\n\n  boxes = pixman_region_rectangles(rgn, &nRects);\n\n  rects->clear();\n  rects->reserve(nRects);\n\n  xInc = left2right ? 1 : -1;\n  yInc = topdown ? 1 : -1;\n  i = topdown ? 0 : nRects-1;\n\n  while (nRects > 0) {\n    int firstInNextBand = i;\n    int nRectsInBand = 0;\n\n    while (nRects > 0 && boxes[firstInNextBand].y1 == boxes[i].y1)\n    {\n      firstInNextBand += yInc;\n      nRects--;\n      nRectsInBand++;\n    }\n\n    if (xInc != yInc)\n      i = firstInNextBand - yInc;\n\n    while (nRectsInBand > 0) {\n      Rect r(boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2);\n      rects->push_back(r);\n      i += xInc;\n      nRectsInBand--;\n    }\n\n    i = firstInNextBand;\n  }\n\n  return !rects->empty();\n}\n\nRect Region::get_bounding_rect() const\n{\n  const pixman_box16_t* extents;\n  extents = pixman_region_extents(rgn);\n  return Rect(extents->x1, extents->y1, extents->x2, extents->y2);\n}\n\n\nvoid Region::debug_print(const char* prefix) const\n{\n  Rect extents;\n  std::vector<Rect> rects;\n  std::vector<Rect>::const_iterator iter;\n\n  extents = get_bounding_rect();\n  get_rects(&rects);\n\n  vlog.debug(\"%s num rects %3ld extents %3d,%3d %3dx%3d\",\n          prefix, (long)rects.size(), extents.tl.x, extents.tl.y,\n          extents.width(), extents.height());\n\n  for (iter = rects.begin(); iter != rects.end(); ++iter) {\n    vlog.debug(\"    rect %3d,%3d %3dx%3d\",\n               iter->tl.x, iter->tl.y, iter->width(), iter->height());\n  }\n}\n"
  },
  {
    "path": "common/core/Region.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2016-2020 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// Region class wrapper around pixman's region operations\n\n#ifndef __CORE_REGION_INCLUDED__\n#define __CORE_REGION_INCLUDED__\n\n#include <vector>\n\n#include <core/Rect.h>\n\nstruct pixman_region16;\n\nnamespace core {\n\n  struct Point;\n  struct Rect;\n\n  class Region {\n  public:\n    // Create an empty region\n    Region();\n    // Create a rectangular region\n    Region(const Rect& r);\n\n    Region(const Region& r);\n    Region &operator=(const Region& src);\n\n    ~Region();\n\n    // the following methods alter the region in place:\n\n    void clear();\n    void reset(const Rect& r);\n    void translate(const Point& delta);\n\n    void assign_intersect(const Region& r);\n    void assign_union(const Region& r);\n    void assign_subtract(const Region& r);\n\n    // the following three operations return a new region:\n\n    Region intersect(const Region& r) const\n      __attribute__ ((warn_unused_result));\n    Region union_(const Region& r) const\n      __attribute__ ((warn_unused_result));\n    Region subtract(const Region& r) const\n      __attribute__ ((warn_unused_result));\n\n    bool operator==(const Region& b) const;\n    bool operator!=(const Region& b) const;\n    int numRects() const;\n    bool is_empty() const { return numRects() == 0; }\n\n    bool get_rects(std::vector<Rect>* rects, bool left2right=true,\n                   bool topdown=true) const;\n    Rect get_bounding_rect() const;\n\n    void debug_print(const char *prefix) const;\n\n  protected:\n\n    struct pixman_region16* rgn;\n  };\n\n};\n\n#endif // __CORE_REGION_INCLUDED__\n"
  },
  {
    "path": "common/core/Timer.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2016-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Timer.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <sys/time.h>\n\n#include <algorithm>\n\n#include <core/LogWriter.h>\n#include <core/Timer.h>\n#include <core/time.h>\n\nusing namespace core;\n\n#ifndef __NO_DEFINE_VLOG__\nstatic LogWriter vlog(\"Timer\");\n#endif\n\nstd::list<Timer*> Timer::pending;\n\nint Timer::checkTimeouts() {\n  timeval start;\n\n  if (pending.empty())\n    return -1;\n\n  gettimeofday(&start, nullptr);\n  while (pending.front()->isBefore(start)) {\n    Timer* timer;\n\n    timer = pending.front();\n    pending.pop_front();\n\n    timer->lastDueTime = timer->dueTime;\n    timer->cb->handleTimeout(timer);\n\n    if (pending.empty())\n      return -1;\n  }\n  return getNextTimeout();\n}\n\nint Timer::getNextTimeout() {\n  timeval now;\n  gettimeofday(&now, nullptr);\n\n  if (pending.empty())\n    return -1;\n\n  int toWait = pending.front()->getRemainingMs();\n\n  if (toWait > pending.front()->timeoutMs) {\n    if (toWait - pending.front()->timeoutMs < 1000) {\n      vlog.info(\"gettimeofday is broken...\");\n      return toWait;\n    }\n    // Time has jumped backwards!\n    vlog.info(\"Time has moved backwards!\");\n    pending.front()->dueTime = now;\n    toWait = 0;\n  }\n\n  return toWait;\n}\n\nvoid Timer::insertTimer(Timer* t) {\n  std::list<Timer*>::iterator i;\n  for (i=pending.begin(); i!=pending.end(); i++) {\n    if (t->isBefore((*i)->dueTime)) {\n      pending.insert(i, t);\n      return;\n    }\n  }\n  pending.push_back(t);\n}\n\nvoid Timer::start(int timeoutMs_) {\n  timeval now;\n  gettimeofday(&now, nullptr);\n  stop();\n  timeoutMs = timeoutMs_;\n  dueTime = addMillis(now, timeoutMs);\n  insertTimer(this);\n}\n\nvoid Timer::repeat(int timeoutMs_) {\n  timeval now;\n\n  gettimeofday(&now, nullptr);\n\n  if (isStarted()) {\n    vlog.error(\"Incorrectly repeating already running timer\");\n    stop();\n  }\n\n  if (msBetween(&lastDueTime, &dueTime) != 0)\n    vlog.error(\"Timer incorrectly modified whilst repeating\");\n\n  if (timeoutMs_ != -1)\n    timeoutMs = timeoutMs_;\n\n  dueTime = addMillis(lastDueTime, timeoutMs);\n  if (isBefore(now)) {\n    // Time has jumped forwards, or we're not getting enough\n    // CPU time for the timers\n    dueTime = now;\n  }\n\n  insertTimer(this);\n}\n\nvoid Timer::stop() {\n  pending.remove(this);\n}\n\nbool Timer::isStarted() {\n  return std::find(pending.begin(), pending.end(),\n                   this) != pending.end();\n}\n\nint Timer::getTimeoutMs() {\n  return timeoutMs;\n}\n\nint Timer::getRemainingMs() {\n  return msUntil(&dueTime);\n}\n\nbool Timer::isBefore(timeval other) {\n  return (dueTime.tv_sec < other.tv_sec) ||\n    ((dueTime.tv_sec == other.tv_sec) &&\n     (dueTime.tv_usec < other.tv_usec));\n}\n"
  },
  {
    "path": "common/core/Timer.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2018-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __CORE_TIMER_H__\n#define __CORE_TIMER_H__\n\n#include <list>\n#include <sys/time.h>\n\nnamespace core {\n\n  /* Timer\n\n     Cross-platform timeout handling.  The caller creates instances of\n     Timer and passes a Callback implementation to each.  The Callback\n     will then be called with a pointer to the Timer instance that\n     timed-out when the timeout occurs.\n\n     The static methods of Timer are used by the main loop of the\n     application both to dispatch elapsed Timer callbacks and to\n     determine how long to wait in select() for the next timeout to\n     occur.\n\n     For classes that can be derived it's best to use MethodTimer which\n     can call a specific method on the class, thus avoiding conflicts\n     when subclassing.\n  */\n\n  struct Timer {\n\n    struct Callback {\n      // handleTimeout\n      //   Passed a pointer to the Timer that has timed out.  If the\n      //   handler returns true then the Timer is reset and left\n      //   running, causing another timeout after the appropriate\n      //   interval.\n      //   If the handler returns false then the Timer is cancelled.\n      virtual void handleTimeout(Timer* t) = 0;\n\n      virtual ~Callback() {}\n    };\n\n    // checkTimeouts()\n    //   Dispatches any elapsed Timers, and returns the number of\n    //   milliseconds until the next Timer will timeout.\n    static int checkTimeouts();\n\n    // getNextTimeout()\n    //   Returns the number of milliseconds until the next timeout,\n    //   without dispatching any elapsed Timers.\n    static int getNextTimeout();\n\n    // Create a Timer with the specified callback handler\n    Timer(Callback* cb_) {cb = cb_;}\n    ~Timer() {stop();}\n\n    // start()\n    //   Starts the timer, causing a timeout after the specified number\n    //   of milliseconds. If the timer is already active then it will\n    //   be implicitly cancelled and re-started.\n    void start(int timeoutMs_);\n\n    // repeat()\n    //   Restarts the timer in a way that repeats that last timeout.\n    //   This allows you to have a periodic timer without the risk of\n    //   accumulating drift caused by processing delays.\n    //   A new interval can be specified, otherwise the previous\n    //   interval is reused.\n    void repeat(int timeoutMs_=-1);\n\n    // stop()\n    //   Cancels the timer.\n    void stop();\n\n    // isStarted()\n    //   Determines whether the timer is started.\n    bool isStarted();\n\n    // getTimeoutMs()\n    //   Determines the previously used timeout value, if any.\n    //   Usually used with isStarted() to get the _current_ timeout.\n    int getTimeoutMs();\n\n    // getRemainingMs()\n    //   Determines how many milliseconds are left before the Timer\n    //   will timeout. Only valid for an active timer.\n    int getRemainingMs();\n\n    // isBefore()\n    //   Determine whether the Timer will timeout before the specified\n    //   time.\n    bool isBefore(timeval other);\n\n  protected:\n    timeval dueTime, lastDueTime;\n    int timeoutMs;\n    Callback* cb;\n\n    static void insertTimer(Timer* t);\n    // The list of currently active Timers, ordered by time left until\n    // timeout.\n    static std::list<Timer*> pending;\n  };\n\n  template<class T> class MethodTimer\n    : public Timer, public Timer::Callback {\n  public:\n    MethodTimer(T* obj_, void (T::*cb_)(Timer*))\n      : Timer(this), obj(obj_), cb(cb_) {}\n\n    void handleTimeout(Timer* t) override { return (obj->*cb)(t); }\n\n  private:\n    T* obj;\n    void (T::*cb)(Timer*);\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "common/core/string.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2023 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <string.h>\n\n#include <core/string.h>\n\nnamespace core {\n\n  std::string format(const char *fmt, ...)\n  {\n    va_list ap;\n    int len;\n    char *buf;\n    std::string out;\n\n    va_start(ap, fmt);\n    len = vsnprintf(nullptr, 0, fmt, ap);\n    va_end(ap);\n\n    if (len < 0)\n      return \"\";\n\n    buf = new char[len+1];\n\n    va_start(ap, fmt);\n    vsnprintf(buf, len+1, fmt, ap);\n    va_end(ap);\n\n    out = buf;\n\n    delete [] buf;\n\n    return out;\n  }\n\n  std::vector<std::string> split(const char* src,\n                                 const char delimiter)\n  {\n    std::vector<std::string> out;\n    const char *start, *stop;\n\n    if (src[0] == '\\0')\n      return out;\n\n    start = src;\n    do {\n      stop = strchr(start, delimiter);\n      if (stop == nullptr) {\n        out.push_back(start);\n      } else {\n        out.push_back(std::string(start, stop-start));\n        start = stop + 1;\n      }\n    } while (stop != nullptr);\n\n    return out;\n  }\n\n  static char intToHex(uint8_t i) {\n    if (i<=9)\n      return '0'+i;\n    else if ((i>=10) && (i<=15))\n      return 'a'+(i-10);\n    assert(false);\n    return '\\0';\n  }\n\n  void binToHex(const uint8_t* in, size_t inlen,\n                char* out, size_t outlen) {\n    if (inlen > outlen/2)\n      inlen = outlen/2;\n\n    if (inlen > 0) {\n      assert(in);\n      assert(out);\n    }\n\n    for (size_t i=0; i<inlen; i++) {\n      out[i*2] = intToHex((in[i] >> 4) & 15);\n      out[i*2+1] = intToHex((in[i] & 15));\n    }\n  }\n\n  std::string binToHex(const uint8_t* in, size_t inlen) {\n    char* buffer = new char[inlen*2+1]();\n    std::string out;\n    binToHex(in, inlen, buffer, inlen*2);\n    out = buffer;\n    delete [] buffer;\n    return out;\n  }\n\n  static bool readHexAndShift(char c, uint8_t* v) {\n    c=tolower(c);\n    if ((c >= '0') && (c <= '9'))\n      *v = (*v << 4) + (c - '0');\n    else if ((c >= 'a') && (c <= 'f'))\n      *v = (*v << 4) + (c - 'a' + 10);\n    else\n      return false;\n    return true;\n  }\n\n  bool hexToBin(const char* in, size_t inlen,\n                uint8_t* out, size_t outlen) {\n    assert(in || inlen == 0);\n    assert(out || outlen == 0);\n\n    if (inlen & 1)\n      return false;\n\n    if (inlen > outlen*2)\n      inlen = outlen*2;\n\n    for(size_t i=0; i<inlen; i+=2) {\n      uint8_t byte = 0;\n      if (!readHexAndShift(in[i], &byte) ||\n          !readHexAndShift(in[i+1], &byte))\n        return false;\n      out[i/2] = byte;\n    }\n\n    return true;\n  }\n\n  std::vector<uint8_t> hexToBin(const char* in, size_t inlen) {\n    std::vector<uint8_t> out(inlen/2);\n    if (!hexToBin(in, inlen, out.data(), inlen/2))\n      return std::vector<uint8_t>();\n    return out;\n  }\n\n  std::string convertLF(const char* src, size_t bytes)\n  {\n    size_t sz;\n    std::string out;\n\n    const char* in;\n    size_t in_len;\n\n    // Compute output size\n    sz = 0;\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      if (*in != '\\r') {\n        sz++;\n        in++;\n        in_len--;\n        continue;\n      }\n\n      if ((in_len < 2) || (*(in+1) != '\\n'))\n        sz++;\n\n      in++;\n      in_len--;\n    }\n\n    // Reserve space\n    out.reserve(sz);\n\n    // And convert\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      if (*in != '\\r') {\n        out += *in++;\n        in_len--;\n        continue;\n      }\n\n      if ((in_len < 2) || (*(in+1) != '\\n'))\n        out += '\\n';\n\n      in++;\n      in_len--;\n    }\n\n    return out;\n  }\n\n  std::string convertCRLF(const char* src, size_t bytes)\n  {\n    std::string out;\n    size_t sz;\n\n    const char* in;\n    size_t in_len;\n\n    // Compute output size\n    sz = 0;\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      sz++;\n\n      if (*in == '\\r') {\n        if ((in_len < 2) || (*(in+1) != '\\n'))\n          sz++;\n      } else if (*in == '\\n') {\n        if ((in == src) || (*(in-1) != '\\r'))\n          sz++;\n      }\n\n      in++;\n      in_len--;\n    }\n\n    // Reserve space\n    out.reserve(sz);\n\n    // And convert\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      if (*in == '\\n') {\n        if ((in == src) || (*(in-1) != '\\r'))\n          out += '\\r';\n      }\n\n      out += *in;\n\n      if (*in == '\\r') {\n        if ((in_len < 2) || (*(in+1) != '\\n'))\n          out += '\\n';\n      }\n\n      in++;\n      in_len--;\n    }\n\n    return out;\n  }\n\n  size_t ucs4ToUTF8(unsigned src, char dst[5]) {\n    if (src < 0x80) {\n      *dst++ = src;\n      *dst++ = '\\0';\n      return 1;\n    } else if (src < 0x800) {\n      *dst++ = 0xc0 | (src >> 6);\n      *dst++ = 0x80 | (src & 0x3f);\n      *dst++ = '\\0';\n      return 2;\n    } else if ((src >= 0xd800) && (src < 0xe000)) {\n      return ucs4ToUTF8(0xfffd, dst);\n    } else if (src < 0x10000) {\n      *dst++ = 0xe0 | (src >> 12);\n      *dst++ = 0x80 | ((src >> 6) & 0x3f);\n      *dst++ = 0x80 | (src & 0x3f);\n      *dst++ = '\\0';\n      return 3;\n    } else if (src < 0x110000) {\n      *dst++ = 0xf0 | (src >> 18);\n      *dst++ = 0x80 | ((src >> 12) & 0x3f);\n      *dst++ = 0x80 | ((src >> 6) & 0x3f);\n      *dst++ = 0x80 | (src & 0x3f);\n      *dst++ = '\\0';\n      return 4;\n    } else {\n      return ucs4ToUTF8(0xfffd, dst);\n    }\n  }\n\n  size_t utf8ToUCS4(const char* src, size_t max, unsigned* dst) {\n    size_t count, consumed;\n\n    *dst = 0xfffd;\n\n    if (max == 0)\n      return 0;\n\n    consumed = 1;\n\n    if ((*src & 0x80) == 0) {\n      *dst = *src;\n      count = 0;\n    } else if ((*src & 0xe0) == 0xc0) {\n      *dst = *src & 0x1f;\n      count = 1;\n    } else if ((*src & 0xf0) == 0xe0) {\n      *dst = *src & 0x0f;\n      count = 2;\n    } else if ((*src & 0xf8) == 0xf0) {\n      *dst = *src & 0x07;\n      count = 3;\n    } else {\n      // Invalid sequence, consume all continuation characters\n      src++;\n      max--;\n      while ((max-- > 0) && ((*src++ & 0xc0) == 0x80))\n        consumed++;\n      return consumed;\n    }\n\n    src++;\n    max--;\n\n    while (count--) {\n      consumed++;\n\n      // Invalid or truncated sequence?\n      if ((max == 0) || ((*src & 0xc0) != 0x80)) {\n        *dst = 0xfffd;\n        return consumed;\n      }\n\n      *dst <<= 6;\n      *dst |= *src & 0x3f;\n\n      src++;\n      max--;\n    }\n\n    // UTF-16 surrogate code point?\n    if ((*dst >= 0xd800) && (*dst < 0xe000))\n      *dst = 0xfffd;\n\n    return consumed;\n  }\n\n  size_t ucs4ToUTF16(unsigned src, wchar_t dst[3]) {\n    if ((src < 0xd800) || ((src >= 0xe000) && (src < 0x10000))) {\n      *dst++ = src;\n      *dst++ = L'\\0';\n      return 1;\n    } else if ((src >= 0x10000) && (src < 0x110000)) {\n      src -= 0x10000;\n      *dst++ = 0xd800 | ((src >> 10) & 0x03ff);\n      *dst++ = 0xdc00 | (src & 0x03ff);\n      *dst++ = L'\\0';\n      return 2;\n    } else {\n      return ucs4ToUTF16(0xfffd, dst);\n    }\n  }\n\n  size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst) {\n    *dst = 0xfffd;\n\n    if (max == 0)\n      return 0;\n\n    if ((*src < 0xd800) || (*src >= 0xe000)) {\n      *dst = *src;\n      return 1;\n    }\n\n    if (*src & 0x0400) {\n      size_t consumed;\n\n      // Invalid sequence, consume all continuation characters\n      consumed = 0;\n      while ((max > 0) && (*src & 0x0400)) {\n        src++;\n        max--;\n        consumed++;\n      }\n\n      return consumed;\n    }\n\n    *dst = *src++;\n    max--;\n\n    // Invalid or truncated sequence?\n    if ((max == 0) || ((*src & 0xfc00) != 0xdc00)) {\n      *dst = 0xfffd;\n      return 1;\n    }\n\n    *dst = 0x10000 + ((*dst & 0x03ff) << 10);\n    *dst |= *src & 0x3ff;\n\n    return 2;\n  }\n\n  std::string latin1ToUTF8(const char* src, size_t bytes) {\n    std::string out;\n    size_t sz;\n\n    const char* in;\n    size_t in_len;\n\n    // Compute output size\n    sz = 0;\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      char buf[5];\n      sz += ucs4ToUTF8(*(const unsigned char*)in, buf);\n      in++;\n      in_len--;\n    }\n\n    // Reserve space\n    out.reserve(sz);\n\n    // And convert\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      char buf[5];\n      ucs4ToUTF8(*(const unsigned char*)in, buf);\n      out += buf;\n      in++;\n      in_len--;\n    }\n\n    return out;\n  }\n\n  std::string utf8ToLatin1(const char* src, size_t bytes) {\n    std::string out;\n    size_t sz;\n\n    const char* in;\n    size_t in_len;\n\n    // Compute output size\n    sz = 0;\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      size_t len;\n      unsigned ucs;\n\n      len = utf8ToUCS4(in, in_len, &ucs);\n      in += len;\n      in_len -= len;\n      sz++;\n    }\n\n    // Reserve space\n    out.reserve(sz);\n\n    // And convert\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      size_t len;\n      unsigned ucs;\n\n      len = utf8ToUCS4(in, in_len, &ucs);\n      in += len;\n      in_len -= len;\n\n      if (ucs > 0xff)\n        out += '?';\n      else\n        out += (unsigned char)ucs;\n    }\n\n    return out;\n  }\n\n  std::string utf16ToUTF8(const wchar_t* src, size_t units)\n  {\n    std::string out;\n    size_t sz;\n\n    const wchar_t* in;\n    size_t in_len;\n\n    // Compute output size\n    sz = 0;\n    in = src;\n    in_len = units;\n    while ((in_len > 0) && (*in != '\\0')) {\n      size_t len;\n      unsigned ucs;\n      char buf[5];\n\n      len = utf16ToUCS4(in, in_len, &ucs);\n      in += len;\n      in_len -= len;\n\n      sz += ucs4ToUTF8(ucs, buf);\n    }\n\n    // Reserve space\n    out.reserve(sz);\n\n    // And convert\n    in = src;\n    in_len = units;\n    while ((in_len > 0) && (*in != '\\0')) {\n      size_t len;\n      unsigned ucs;\n      char buf[5];\n\n      len = utf16ToUCS4(in, in_len, &ucs);\n      in += len;\n      in_len -= len;\n\n      ucs4ToUTF8(ucs, buf);\n      out += buf;\n    }\n\n    return out;\n  }\n\n  std::wstring utf8ToUTF16(const char* src, size_t bytes)\n  {\n    std::wstring out;\n    size_t sz;\n\n    const char* in;\n    size_t in_len;\n\n    // Compute output size\n    sz = 0;\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      size_t len;\n      unsigned ucs;\n      wchar_t buf[3];\n\n      len = utf8ToUCS4(in, in_len, &ucs);\n      in += len;\n      in_len -= len;\n\n      sz += ucs4ToUTF16(ucs, buf);\n    }\n\n    // Reserve space\n    out.reserve(sz);\n\n    // And convert\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      size_t len;\n      unsigned ucs;\n      wchar_t buf[3];\n\n      len = utf8ToUCS4(in, in_len, &ucs);\n      in += len;\n      in_len -= len;\n\n      ucs4ToUTF16(ucs, buf);\n      out += buf;\n    }\n\n    return out;\n  }\n\n  std::string utf8ToAscii(const char* src, size_t bytes)\n  {\n    std::string out;\n    size_t sz;\n\n    const char* in;\n    size_t in_len;\n\n    // Compute output size\n    sz = 0;\n    in = src;\n    in_len = bytes;\n    while ((in_len > 0) && (*in != '\\0')) {\n      size_t len;\n      unsigned ucs;\n\n      len = utf8ToUCS4(in, in_len, &ucs);\n      in += len;\n      in_len -= len;\n      sz++;\n    }\n\n    // Reserve space\n    out.reserve(sz);\n\n    // And convert\n    in = src;\n    in_len = bytes;\n    while (in_len > 0 && *in != '\\0') {\n      size_t len;\n      unsigned ucs;\n\n      len = utf8ToUCS4(in, in_len, &ucs);\n      in += len;\n      in_len -= len;\n\n      if (ucs <= 0x7f) {\n        out += (unsigned char)ucs;\n      } else {\n        out += \"?\";\n      }\n    }\n\n    return out;\n  };\n\n  bool isValidUTF8(const char* str, size_t bytes)\n  {\n    while ((bytes > 0) && (*str != '\\0')) {\n      size_t len;\n      unsigned ucs;\n\n      len = utf8ToUCS4(str, bytes, &ucs);\n      str += len;\n      bytes -= len;\n\n      if (ucs == 0xfffd)\n        return false;\n    }\n\n    return true;\n  }\n\n  bool isValidUTF16(const wchar_t* wstr, size_t units)\n  {\n    while ((units > 0) && (*wstr != '\\0')) {\n      size_t len;\n      unsigned ucs;\n\n      len = utf16ToUCS4(wstr, units, &ucs);\n      wstr += len;\n      units -= len;\n\n      if (ucs == 0xfffd)\n        return false;\n    }\n\n    return true;\n  }\n\n  bool isValidAscii(const char *str, size_t bytes)\n  {\n    while ((bytes > 0) && (*str != '\\0')) {\n      if (!isascii(*str))\n        return false;\n      str++;\n    }\n\n    return true;\n  }\n\n  static std::string doPrefix(long long value, const char *unit,\n                              unsigned divisor, const char **prefixes,\n                              size_t prefixCount, int precision) {\n    char buffer[256];\n    double newValue;\n    size_t prefix;\n\n    newValue = value;\n    prefix = 0;\n    while (newValue >= divisor) {\n      if (prefix >= prefixCount)\n        break;\n      newValue /= divisor;\n      prefix++;\n    }\n\n    snprintf(buffer, sizeof(buffer), \"%.*g %s%s\", precision, newValue,\n             (prefix == 0) ? \"\" : prefixes[prefix-1], unit);\n    buffer[sizeof(buffer)-1] = '\\0';\n\n    return buffer;\n  }\n\n  static const char *siPrefixes[] =\n    { \"k\", \"M\", \"G\", \"T\", \"P\", \"E\", \"Z\", \"Y\" };\n  static const char *iecPrefixes[] =\n    { \"Ki\", \"Mi\", \"Gi\", \"Ti\", \"Pi\", \"Ei\", \"Zi\", \"Yi\" };\n\n  std::string siPrefix(long long value, const char *unit,\n                       int precision) {\n    return doPrefix(value, unit, 1000, siPrefixes,\n                    sizeof(siPrefixes)/sizeof(*siPrefixes),\n                    precision);\n  }\n\n  std::string iecPrefix(long long value, const char *unit,\n                        int precision) {\n    return doPrefix(value, unit, 1024, iecPrefixes,\n                    sizeof(iecPrefixes)/sizeof(*iecPrefixes),\n                    precision);\n  }\n};\n"
  },
  {
    "path": "common/core/string.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2023 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// string.h - string utility functions\n//\n\n#ifndef __CORE_STRING_H__\n#define __CORE_STRING_H__\n\n#include <stdint.h>\n\n#include <string>\n#include <vector>\n\nnamespace core {\n\n  // Formats according to printf(), with a dynamic allocation\n  std::string format(const char *fmt, ...)\n      __attribute__((__format__ (__printf__, 1, 2)));\n\n  // Splits a string with the specified delimiter\n  std::vector<std::string> split(const char* src,\n                                 const char delimiter);\n\n  // Conversion to and from a hex string\n\n  void binToHex(const uint8_t* in, size_t inlen, char* out, size_t outlen);\n  std::string binToHex(const uint8_t* in, size_t inlen);\n  bool hexToBin(const char* in, size_t inlen, uint8_t* out, size_t outlen);\n  std::vector<uint8_t> hexToBin(const char* in, size_t inlen);\n\n  // Makes sure line endings are in a certain format\n\n  std::string convertLF(const char* src, size_t bytes = (size_t)-1);\n  std::string convertCRLF(const char* src, size_t bytes = (size_t)-1);\n\n  // Convertions between various Unicode formats\n\n  size_t ucs4ToUTF8(unsigned src, char dst[5]);\n  size_t utf8ToUCS4(const char* src, size_t max, unsigned* dst);\n\n  size_t ucs4ToUTF16(unsigned src, wchar_t dst[3]);\n  size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst);\n\n  std::string latin1ToUTF8(const char* src, size_t bytes = (size_t)-1);\n  std::string utf8ToLatin1(const char* src, size_t bytes = (size_t)-1);\n\n  std::string utf16ToUTF8(const wchar_t* src, size_t units = (size_t)-1);\n  std::wstring utf8ToUTF16(const char* src, size_t bytes = (size_t)-1);\n\n  std::string utf8ToAscii(const char* src, size_t bytes = (size_t)-1);\n\n  bool isValidUTF8(const char* str, size_t bytes = (size_t)-1);\n  bool isValidUTF16(const wchar_t* wstr, size_t units = (size_t)-1);\n  bool isValidAscii(const char* str, size_t bytes = (size_t)-1);\n\n  // Convert a value to a string using the correct prefix to reduce\n  // the length of the string\n\n  std::string siPrefix(long long value, const char *unit,\n                       int precision=6);\n  std::string iecPrefix(long long value, const char *unit,\n                        int precision=6);\n}\n\n#endif\n"
  },
  {
    "path": "common/core/time.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stddef.h>\n#include <sys/time.h>\n\n#include <core/time.h>\n\nnamespace core {\n\n  unsigned msBetween(const struct timeval *first,\n                     const struct timeval *second)\n  {\n    unsigned udiff;\n\n    if (isBefore(second, first))\n      return 0;\n\n    udiff = (second->tv_sec - first->tv_sec) * 1000000 +\n            (second->tv_usec - first->tv_usec);\n\n    return (udiff + 999) / 1000;\n  }\n\n  unsigned msSince(const struct timeval *then)\n  {\n    struct timeval now;\n\n    gettimeofday(&now, nullptr);\n\n    return msBetween(then, &now);\n  }\n\n  unsigned msUntil(const struct timeval *then)\n  {\n    struct timeval now;\n\n    gettimeofday(&now, nullptr);\n\n    return msBetween(&now, then);\n  }\n\n  bool isBefore(const struct timeval *first,\n                const struct timeval *second)\n  {\n    if (first->tv_sec < second->tv_sec)\n      return true;\n    if (first->tv_sec > second->tv_sec)\n      return false;\n    if (first->tv_usec < second->tv_usec)\n      return true;\n    return false;\n  }\n\n  struct timeval addMillis(struct timeval inTime, int millis)\n  {\n    int secs = millis / 1000;\n    millis = millis % 1000;\n    inTime.tv_sec += secs;\n    inTime.tv_usec += millis * 1000;\n    if (inTime.tv_usec >= 1000000) {\n      inTime.tv_sec++;\n      inTime.tv_usec -= 1000000;\n    }\n    return inTime;\n  }\n\n}\n"
  },
  {
    "path": "common/core/time.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// time.h - time helper functions\n//\n\n#ifndef __CORE_TIME_H__\n#define __CORE_TIME_H__\n\n#include <limits.h>\n\nstruct timeval;\n\nnamespace core {\n\n  // secsToMillis() turns seconds into milliseconds, capping the value so it\n  //   can't wrap round and become -ve\n  inline int secsToMillis(int secs) {\n    return (secs < 0 || secs > (INT_MAX/1000) ? INT_MAX : secs * 1000);\n  }\n\n  // Returns time elapsed between two moments in milliseconds.\n  unsigned msBetween(const struct timeval *first,\n                     const struct timeval *second);\n\n  // Returns time elapsed since given moment in milliseconds.\n  unsigned msSince(const struct timeval *then);\n\n  // Returns time until the given moment in milliseconds.\n  unsigned msUntil(const struct timeval *then);\n\n  // Returns true if first happened before seconds\n  bool isBefore(const struct timeval *first,\n                const struct timeval *second);\n\n  // Returns a new timeval a specified number of milliseconds later than\n  // the given timeval\n  struct timeval addMillis(struct timeval inTime, int millis);\n}\n\n#endif\n"
  },
  {
    "path": "common/core/winerrno.h",
    "content": "\n/* Generated with:\ncat /usr/i686-pc-mingw32/sys-root/mingw/include/winerror.h \\\n | awk '/#define WSAE.*WSABASE/{gsub(\"WSA\", \"\"); print \"#undef \" $2 \"\\n#define \" $2 \" WSA\" $2}' \\\n | egrep -v 'EINTR|EBADF|EACCES|EFAULT|EINVAL|EMFILE|_QOS|PROVIDER|PROCTABLE'\n*/\n\n#include <winsock2.h>\n\n#undef EWOULDBLOCK\n#define EWOULDBLOCK WSAEWOULDBLOCK\n#undef EINPROGRESS\n#define EINPROGRESS WSAEINPROGRESS\n#undef EALREADY\n#define EALREADY WSAEALREADY\n#undef ENOTSOCK\n#define ENOTSOCK WSAENOTSOCK\n#undef EDESTADDRREQ\n#define EDESTADDRREQ WSAEDESTADDRREQ\n#undef EMSGSIZE\n#define EMSGSIZE WSAEMSGSIZE\n#undef EPROTOTYPE\n#define EPROTOTYPE WSAEPROTOTYPE\n#undef ENOPROTOOPT\n#define ENOPROTOOPT WSAENOPROTOOPT\n#undef EPROTONOSUPPORT\n#define EPROTONOSUPPORT WSAEPROTONOSUPPORT\n#undef ESOCKTNOSUPPORT\n#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT\n#undef EOPNOTSUPP\n#define EOPNOTSUPP WSAEOPNOTSUPP\n#undef EPFNOSUPPORT\n#define EPFNOSUPPORT WSAEPFNOSUPPORT\n#undef EAFNOSUPPORT\n#define EAFNOSUPPORT WSAEAFNOSUPPORT\n#undef EADDRINUSE\n#define EADDRINUSE WSAEADDRINUSE\n#undef EADDRNOTAVAIL\n#define EADDRNOTAVAIL WSAEADDRNOTAVAIL\n#undef ENETDOWN\n#define ENETDOWN WSAENETDOWN\n#undef ENETUNREACH\n#define ENETUNREACH WSAENETUNREACH\n#undef ENETRESET\n#define ENETRESET WSAENETRESET\n#undef ECONNABORTED\n#define ECONNABORTED WSAECONNABORTED\n#undef ECONNRESET\n#define ECONNRESET WSAECONNRESET\n#undef ENOBUFS\n#define ENOBUFS WSAENOBUFS\n#undef EISCONN\n#define EISCONN WSAEISCONN\n#undef ENOTCONN\n#define ENOTCONN WSAENOTCONN\n#undef ESHUTDOWN\n#define ESHUTDOWN WSAESHUTDOWN\n#undef ETOOMANYREFS\n#define ETOOMANYREFS WSAETOOMANYREFS\n#undef ETIMEDOUT\n#define ETIMEDOUT WSAETIMEDOUT\n#undef ECONNREFUSED\n#define ECONNREFUSED WSAECONNREFUSED\n#undef ELOOP\n#define ELOOP WSAELOOP\n#undef ENAMETOOLONG\n#define ENAMETOOLONG WSAENAMETOOLONG\n#undef EHOSTDOWN\n#define EHOSTDOWN WSAEHOSTDOWN\n#undef EHOSTUNREACH\n#define EHOSTUNREACH WSAEHOSTUNREACH\n#undef ENOTEMPTY\n#define ENOTEMPTY WSAENOTEMPTY\n#undef EPROCLIM\n#define EPROCLIM WSAEPROCLIM\n#undef EUSERS\n#define EUSERS WSAEUSERS\n#undef EDQUOT\n#define EDQUOT WSAEDQUOT\n#undef ESTALE\n#define ESTALE WSAESTALE\n#undef EREMOTE\n#define EREMOTE WSAEREMOTE\n#undef EDISCON\n#define EDISCON WSAEDISCON\n#undef ENOMORE\n#define ENOMORE WSAENOMORE\n#undef ECANCELLED\n#define ECANCELLED WSAECANCELLED\n#undef EREFUSED\n#define EREFUSED WSAEREFUSED\n"
  },
  {
    "path": "common/core/xdgdirs.cxx",
    "content": "/* Copyright (C) 2010 TightVNC Team.  All Rights Reserved.\n * Copyright 2021-2023 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <errno.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#ifndef WIN32\n#include <pwd.h>\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#else\n#include <windows.h>\n#include <wininet.h> /* MinGW needs it */\n#include <shlobj.h>\n#define stat _stat\n#define mkdir(path, mode) mkdir(path)\n#endif\n\n#include <core/xdgdirs.h>\n\nstatic const char* getvncdir(bool userDir, const char *xdg_env, const char *xdg_def)\n{\n  static char dir[PATH_MAX], legacy[PATH_MAX];\n  struct stat st;\n\n#ifndef WIN32\n  char *homedir, *xdgdir;\n  uid_t uid;\n  struct passwd *passwd;\n#else\n  BOOL ret;\n#endif\n\n#ifndef WIN32\n  homedir = getenv(\"HOME\");\n  if (homedir == nullptr) {\n    uid = getuid();\n    passwd = getpwuid(uid);\n    if (passwd == nullptr) {\n      /* Do we want emit error msg here? */\n      return nullptr;\n    }\n    homedir = passwd->pw_dir;\n  }\n\n  if (userDir)\n    return homedir;\n\n  xdgdir = getenv(xdg_env);\n  if (xdgdir != nullptr && xdgdir[0] == '/')\n    snprintf(dir, sizeof(dir), \"%s/tigervnc\", xdgdir);\n  else\n    snprintf(dir, sizeof(dir), \"%s/%s/tigervnc\", homedir, xdg_def);\n\n  snprintf(legacy, sizeof(legacy), \"%s/.vnc\", homedir);\n#else\n  (void) xdg_def;\n  (void) xdg_env;\n\n  if (userDir)\n    ret = SHGetSpecialFolderPath(nullptr, dir, CSIDL_PROFILE, FALSE);\n  else\n    ret = SHGetSpecialFolderPath(nullptr, dir, CSIDL_APPDATA, FALSE);\n\n  if (ret == FALSE)\n    return nullptr;\n\n  if (userDir)\n    return dir;\n\n  ret = SHGetSpecialFolderPath(nullptr, legacy, CSIDL_APPDATA, FALSE);\n\n  if (ret == FALSE)\n    return nullptr;\n\n  if (strlen(dir) + strlen(\"\\\\TigerVNC\") >= sizeof(dir))\n    return nullptr;\n  if (strlen(legacy) + strlen(\"\\\\vnc\") >= sizeof(legacy))\n    return nullptr;\n\n  strcat(dir, \"\\\\TigerVNC\");\n  strcat(legacy, \"\\\\vnc\");\n#endif\n  return (stat(dir, &st) != 0 && stat(legacy, &st) == 0) ? legacy : dir;\n}\n\nconst char* core::getuserhomedir()\n{\n  return getvncdir(true, nullptr, nullptr);\n}\n\nconst char* core::getvncconfigdir()\n{\n  return getvncdir(false, \"XDG_CONFIG_HOME\", \".config\");\n}\n\nconst char* core::getvncdatadir()\n{\n  return getvncdir(false, \"XDG_DATA_HOME\", \".local/share\");\n}\n\nconst char* core::getvncstatedir()\n{\n  return getvncdir(false, \"XDG_STATE_HOME\", \".local/state\");\n}\n\nint core::mkdir_p(const char *path_, mode_t mode)\n{\n  char *path = strdup(path_);\n  char *p;\n\n#ifdef WIN32\n  (void)mode;\n#endif\n\n  for (p = path + 1; *p; p++) {\n    if (*p == '/') {\n      *p = '\\0';\n      if (mkdir(path, mode) == -1) {\n        if (errno != EEXIST) {\n          free(path);\n          return -1;\n        }\n      }\n      *p = '/';\n    }\n  }\n\n  if (mkdir(path, mode) == -1) {\n    free(path);\n    return -1;\n  }\n\n  free(path);\n\n  return 0;\n}\n"
  },
  {
    "path": "common/core/xdgdirs.h",
    "content": "/* Copyright (C) 2010 TightVNC Team.  All Rights Reserved.\n * Copyright 2021-2023 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef CORE_XDGDIRS_H\n#define CORE_XDGDIRS_H\n\n#include <sys/stat.h>\n\nnamespace core {\n\n  /*\n   * Get user home directory.\n   * If HOME environment variable is set then it is used.\n   * Otherwise home directory is obtained via getpwuid function.\n   *\n   * Returns NULL on failure.\n   */\n  const char* getuserhomedir();\n\n  /*\n   * Get VNC config directory. On Unix-like systems, this is either:\n   * - $XDG_CONFIG_HOME/tigervnc\n   * - $HOME/.config/tigervnc\n   * On Windows, this is simply %APPDATA%/TigerVNC/.\n   *\n   * Returns NULL on failure.\n   */\n  const char* getvncconfigdir();\n\n  /*\n   * Get VNC data directory used for X.509 known hosts.\n   * On Unix-like systems, this is either:\n   * - $XDG_DATA_HOME/tigervnc\n   * - $HOME/.local/share/tigervnc\n   * On Windows, this is simply %APPDATA%/TigerVNC/.\n   *\n   * Returns NULL on failure.\n   */\n  const char* getvncdatadir();\n\n  /*\n   * Get VNC state (logs) directory. On Unix-like systems, this is either:\n   * - $XDG_STATE_HOME/tigervnc\n   * - $HOME/.local/state/tigervnc\n   * On Windows, this is simply %APPDATA%/TigerVNC/.\n   *\n   * Returns NULL on failure.\n   */\n  const char* getvncstatedir();\n\n  /*\n   * Create directory recursively. Useful to create the nested directory\n   * structures needed for the above directories.\n   */\n  int mkdir_p(const char *path, mode_t mode);\n}\n\n#endif /* CORE_XDGDIRS_H */\n"
  },
  {
    "path": "common/network/CMakeLists.txt",
    "content": "add_library(network STATIC\n  Socket.cxx\n  TcpSocket.cxx)\n\nif(NOT WIN32)\n  target_sources(network PRIVATE UnixSocket.cxx)\nendif()\n\ntarget_include_directories(network PUBLIC ${CMAKE_SOURCE_DIR}/common)\ntarget_link_libraries(network core rdr)\n\nif(WIN32)\n\ttarget_link_libraries(network ws2_32)\nendif()\n\nif(UNIX)\n  libtool_create_control_file(network)\nendif()\n"
  },
  {
    "path": "common/network/Socket.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#ifdef WIN32\n//#include <io.h>\n#include <winsock2.h>\n#include <ws2tcpip.h>\n#define errorNumber WSAGetLastError()\n#define SHUT_RD SD_RECEIVE\n#define SHUT_WR SD_SEND\n#define SHUT_RDWR SD_BOTH\n#else\n#define errorNumber errno\n#define closesocket close\n#include <sys/socket.h>\n#include <unistd.h>\n#include <signal.h>\n#include <fcntl.h>\n#include <errno.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rdr/FdInStream.h>\n#include <rdr/FdOutStream.h>\n\n#include <network/Socket.h>\n\nusing namespace network;\n\nstatic core::LogWriter vlog(\"Socket\");\n\n// -=- Socket initialisation\nstatic bool socketsInitialised = false;\nvoid network::initSockets() {\n  if (socketsInitialised)\n    return;\n#ifdef WIN32\n  WORD requiredVersion = MAKEWORD(2,0);\n  WSADATA initResult;\n  \n  if (WSAStartup(requiredVersion, &initResult) != 0)\n    throw core::socket_error(\"Unable to initialise Winsock2\", errorNumber);\n#else\n  signal(SIGPIPE, SIG_IGN);\n#endif\n  socketsInitialised = true;\n}\n\nbool network::isSocketListening(int sock)\n{\n  int listening = 0;\n  socklen_t listening_size = sizeof(listening);\n  if (getsockopt(sock, SOL_SOCKET, SO_ACCEPTCONN,\n                 (char *)&listening, &listening_size) < 0)\n    return false;\n  return listening != 0;\n}\n\nSocket::Socket(int fd)\n  : instream(nullptr), outstream(nullptr),\n    isShutdownRead_(false), isShutdownWrite_(false),\n    queryConnection(false)\n{\n  initSockets();\n  setFd(fd);\n}\n\nSocket::Socket()\n  : instream(nullptr), outstream(nullptr),\n    isShutdownRead_(false), isShutdownWrite_(false),\n    queryConnection(false)\n{\n  initSockets();\n}\n\nSocket::~Socket()\n{\n  if (instream && outstream)\n    closesocket(getFd());\n  delete instream;\n  delete outstream;\n}\n\nint Socket::getFd()\n{\n  return outstream->getFd();\n}\n\nvoid Socket::shutdownRead()\n{\n  instream->skip(instream->avail());\n\n  isShutdownRead_ = true;\n  ::shutdown(getFd(), SHUT_RD);\n}\n\n// if shutdownWrite() is overridden then the override MUST call on to here\nvoid Socket::shutdownWrite()\n{\n  try {\n    if (outstream->hasBufferedData()) {\n      outstream->cork(false);\n      outstream->flush();\n      if (outstream->hasBufferedData())\n        vlog.error(\"Failed to flush remaining socket data on close\");\n    }\n  } catch (std::exception& e) {\n    vlog.error(\"Failed to flush remaining socket data on close: %s\", e.what());\n  }\n\n  isShutdownWrite_ = true;\n  ::shutdown(getFd(), SHUT_WR);\n}\n\nbool Socket::isShutdownRead() const\n{\n  return isShutdownRead_;\n}\n\nbool Socket::isShutdownWrite() const\n{\n  return isShutdownWrite_;\n}\n\nvoid Socket::cork(bool enable)\n{\n  outstream->cork(enable);\n}\n\n// Was there a \"?\" in the ConnectionFilter used to accept this Socket?\nvoid Socket::setRequiresQuery()\n{\n  queryConnection = true;\n}\n\nbool Socket::requiresQuery() const\n{\n  return queryConnection;\n}\n\nvoid Socket::setFd(int fd)\n{\n#ifndef WIN32\n  // - By default, close the socket on exec()\n  fcntl(fd, F_SETFD, FD_CLOEXEC);\n#endif\n\n  instream = new rdr::FdInStream(fd);\n  outstream = new rdr::FdOutStream(fd);\n  isShutdownRead_ = false;\n  isShutdownWrite_ = false;\n}\n\nSocketListener::SocketListener(int fd_)\n  : fd(fd_), filter(nullptr)\n{\n  initSockets();\n}\n\nSocketListener::SocketListener()\n  : fd(-1), filter(nullptr)\n{\n  initSockets();\n}\n\nSocketListener::~SocketListener()\n{\n  if (fd != -1)\n    closesocket(fd);\n}\n\nvoid SocketListener::shutdown()\n{\n#ifdef WIN32\n  closesocket(fd);\n  fd = -1;\n#else\n  ::shutdown(fd, SHUT_RDWR);\n#endif\n}\n\nSocket* SocketListener::accept() {\n  int new_sock = -1;\n\n  // Accept an incoming connection\n  if ((new_sock = ::accept(fd, nullptr, nullptr)) < 0)\n    throw core::socket_error(\"Unable to accept new connection\", errorNumber);\n\n  // Create the socket object & check connection is allowed\n  Socket* s = createSocket(new_sock);\n  if (filter && !filter->verifyConnection(s)) {\n    delete s;\n    return nullptr;\n  }\n\n  return s;\n}\n\nvoid SocketListener::listen(int sock)\n{\n  // - Set it to be a listening socket\n  if (::listen(sock, 5) < 0) {\n    int e = errorNumber;\n    closesocket(sock);\n    throw core::socket_error(\"Unable to set socket to listening mode\", e);\n  }\n\n  fd = sock;\n}\n"
  },
  {
    "path": "common/network/Socket.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Socket.h - abstract base-class for any kind of network stream/socket\n\n#ifndef __NETWORK_SOCKET_H__\n#define __NETWORK_SOCKET_H__\n\n#include <list>\n\n#include <limits.h>\n\nnamespace rdr {\n  class FdInStream;\n  class FdOutStream;\n}\n\nnamespace network {\n\n  void initSockets();\n\n  bool isSocketListening(int sock);\n\n  class Socket {\n  public:\n    Socket(int fd);\n    virtual ~Socket();\n\n    rdr::FdInStream &inStream() {return *instream;}\n    rdr::FdOutStream &outStream() {return *outstream;}\n    int getFd();\n\n    void shutdownRead();\n    void shutdownWrite();\n    bool isShutdownRead() const;\n    bool isShutdownWrite() const;\n\n    void cork(bool enable);\n\n    // information about the remote end of the socket\n    virtual const char* getPeerAddress() = 0; // a string e.g. \"192.168.0.1\"\n    virtual const char* getPeerEndpoint() = 0; // <address>::<port>\n\n    // Was there a \"?\" in the ConnectionFilter used to accept this Socket?\n    void setRequiresQuery();\n    bool requiresQuery() const;\n\n  protected:\n    Socket();\n\n    void setFd(int fd);\n\n  private:\n    rdr::FdInStream* instream;\n    rdr::FdOutStream* outstream;\n    bool isShutdownRead_, isShutdownWrite_;\n    bool queryConnection;\n  };\n\n  class ConnectionFilter {\n  public:\n    virtual bool verifyConnection(Socket* s) = 0;\n    virtual ~ConnectionFilter() {}\n  };\n\n  class SocketListener {\n  public:\n    SocketListener(int fd);\n    virtual ~SocketListener();\n\n    // shutdown() stops the socket from accepting further connections\n    void shutdown();\n\n    // accept() returns a new Socket object if there is a connection\n    // attempt in progress AND if the connection passes the filter\n    // if one is installed.  Otherwise, returns 0.\n    Socket* accept();\n\n    virtual int getMyPort() = 0;\n\n    // setFilter() applies the specified filter to all new connections\n    void setFilter(ConnectionFilter* f) {filter = f;}\n    int getFd() {return fd;}\n\n  protected:\n    SocketListener();\n\n    void listen(int fd);\n\n    // createSocket() should create a new socket of the correct class\n    // for the given file descriptor\n    virtual Socket* createSocket(int fd) = 0;\n\n  protected:\n    int fd;\n    ConnectionFilter* filter;\n  };\n\n}\n\n#endif // __NETWORK_SOCKET_H__\n"
  },
  {
    "path": "common/network/TcpSocket.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#ifdef WIN32\n//#include <io.h>\n#include <winsock2.h>\n#include <ws2tcpip.h>\n#define errorNumber WSAGetLastError()\n#else\n#define errorNumber errno\n#define closesocket close\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <netinet/tcp.h>\n#include <netdb.h>\n#include <errno.h>\n#endif\n\n#include <assert.h>\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include <core/Configuration.h>\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <network/TcpSocket.h>\n\n#ifdef WIN32\n#include <core/winerrno.h>\n#endif\n\n#ifndef INADDR_NONE\n#define INADDR_NONE ((unsigned long)-1)\n#endif\n#ifndef INADDR_LOOPBACK\n#define INADDR_LOOPBACK ((unsigned long)0x7F000001)\n#endif\n\n#ifndef IN6_ARE_ADDR_EQUAL\n#define IN6_ARE_ADDR_EQUAL(a,b) \\\n  (memcmp ((const void*)(a), (const void*)(b), sizeof (struct in6_addr)) == 0)\n#endif\n\n// Missing on older Windows and OS X\n#ifndef AI_NUMERICSERV\n#define AI_NUMERICSERV 0\n#endif\n\nusing namespace network;\n\nstatic core::LogWriter vlog(\"TcpSocket\");\n\nstatic core::BoolParameter UseIPv4(\"UseIPv4\", \"Use IPv4 for incoming and outgoing connections.\", true);\nstatic core::BoolParameter UseIPv6(\"UseIPv6\", \"Use IPv6 for incoming and outgoing connections.\", true);\n\n/* Tunnelling support. */\nint network::findFreeTcpPort (void)\n{\n  int sock;\n  struct sockaddr_in addr;\n  memset(&addr, 0, sizeof(addr));\n  addr.sin_family = AF_INET;\n  addr.sin_addr.s_addr = INADDR_ANY;\n\n  if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0)\n    throw core::socket_error(\"Unable to create socket\", errorNumber);\n\n  addr.sin_port = 0;\n  if (bind (sock, (struct sockaddr *)&addr, sizeof (addr)) < 0)\n    throw core::socket_error(\"Unable to find free port\", errorNumber);\n\n  socklen_t n = sizeof(addr);\n  if (getsockname (sock, (struct sockaddr *)&addr, &n) < 0)\n    throw core::socket_error(\"Unable to get port number\", errorNumber);\n\n  closesocket (sock);\n  return ntohs(addr.sin_port);\n}\n\nstatic bool isAllSpace(const char *string) {\n  if (string == nullptr)\n    return false;\n  while(*string != '\\0') {\n    if (! isspace(*string))\n      return false;\n    string++;\n  }\n  return true;\n}\n\nvoid network::getHostAndPort(const char* hi, std::string* host,\n                             int* port, int basePort)\n{\n  const char* hostStart;\n  const char* hostEnd;\n  const char* portStart;\n\n  if (hi == nullptr)\n    throw std::invalid_argument(\"NULL host specified\");\n\n  // Trim leading whitespace\n  while(isspace(*hi))\n    hi++;\n\n  assert(host);\n  assert(port);\n\n  if (hi[0] == '[') {\n    hostStart = &hi[1];\n    hostEnd = strchr(hostStart, ']');\n    if (hostEnd == nullptr)\n      throw std::invalid_argument(\"Unmatched [ in host\");\n\n    portStart = hostEnd + 1;\n    if (isAllSpace(portStart))\n      portStart = nullptr;\n  } else {\n    hostStart = &hi[0];\n    hostEnd = strrchr(hostStart, ':');\n\n    if (hostEnd == nullptr) {\n      hostEnd = hostStart + strlen(hostStart);\n      portStart = nullptr;\n    } else {\n      if ((hostEnd > hostStart) && (hostEnd[-1] == ':'))\n        hostEnd--;\n      portStart = strchr(hostStart, ':');\n      if (portStart != hostEnd) {\n        // We found more : in the host. This is probably an IPv6 address\n        hostEnd = hostStart + strlen(hostStart);\n        portStart = nullptr;\n      }\n    }\n  }\n\n  // Back up past trailing space\n  while(isspace(*(hostEnd - 1)) && hostEnd > hostStart)\n    hostEnd--;\n\n  if (hostStart == hostEnd)\n    *host = \"localhost\";\n  else\n    *host = std::string(hostStart, hostEnd - hostStart);\n\n  if (portStart == nullptr)\n    *port = basePort;\n  else {\n    char* end;\n\n    if (portStart[0] != ':')\n      throw std::invalid_argument(\"Invalid port specified\");\n\n    if (portStart[1] != ':')\n      *port = strtol(portStart + 1, &end, 10);\n    else\n      *port = strtol(portStart + 2, &end, 10);\n    if (*end != '\\0' && ! isAllSpace(end))\n      throw std::invalid_argument(\"Invalid port specified\");\n\n    if ((portStart[1] != ':') && (*port < 100))\n      *port += basePort;\n  }\n}\n\nint network::getSockPort(int sock)\n{\n  vnc_sockaddr_t sa;\n  socklen_t sa_size = sizeof(sa);\n  if (getsockname(sock, &sa.u.sa, &sa_size) < 0)\n    return 0;\n\n  switch (sa.u.sa.sa_family) {\n  case AF_INET6:\n    return ntohs(sa.u.sin6.sin6_port);\n  default:\n    return ntohs(sa.u.sin.sin_port);\n  }\n}\n\n// -=- TcpSocket\n\nTcpSocket::TcpSocket(int sock) : Socket(sock)\n{\n  // Disable Nagle's algorithm, to reduce latency\n  enableNagles(false);\n}\n\nTcpSocket::TcpSocket(const char *host, int port)\n{\n  int sock, err, result;\n  struct addrinfo *ai, *current, hints;\n\n  // - Create a socket\n\n  memset(&hints, 0, sizeof(struct addrinfo));\n  hints.ai_family = AF_UNSPEC;\n  hints.ai_socktype = SOCK_STREAM;\n  hints.ai_canonname = nullptr;\n  hints.ai_addr = nullptr;\n  hints.ai_next = nullptr;\n\n  if ((result = getaddrinfo(host, nullptr, &hints, &ai)) != 0) {\n    throw core::getaddrinfo_error(\"Unable to resolve host by name\", result);\n  }\n\n  sock = -1;\n  err = 0;\n  for (current = ai; current != nullptr; current = current->ai_next) {\n    int family;\n    vnc_sockaddr_t sa;\n    socklen_t salen;\n    char ntop[NI_MAXHOST];\n\n    family = current->ai_family;\n\n    switch (family) {\n    case AF_INET:\n      if (!UseIPv4)\n        continue;\n      break;\n    case AF_INET6:\n      if (!UseIPv6)\n        continue;\n      break;\n    default:\n      continue;\n    }\n\n    salen = current->ai_addrlen;\n    memcpy(&sa, current->ai_addr, salen);\n\n    if (family == AF_INET)\n      sa.u.sin.sin_port = htons(port);\n    else\n      sa.u.sin6.sin6_port = htons(port);\n\n    getnameinfo(&sa.u.sa, salen, ntop, sizeof(ntop), nullptr, 0, NI_NUMERICHOST);\n    vlog.debug(\"Connecting to %s [%s] port %d\", host, ntop, port);\n\n    sock = socket (family, SOCK_STREAM, 0);\n    if (sock == -1) {\n      err = errorNumber;\n      freeaddrinfo(ai);\n      throw core::socket_error(\"Unable to create socket\", err);\n    }\n\n  /* Attempt to connect to the remote host */\n    while ((result = connect(sock, &sa.u.sa, salen)) == -1) {\n      err = errorNumber;\n#ifndef WIN32\n      if (err == EINTR)\n        continue;\n#endif\n      vlog.debug(\"Failed to connect to address %s port %d: %d\",\n                 ntop, port, err);\n      closesocket(sock);\n      sock = -1;\n      break;\n    }\n\n    if (result == 0)\n      break;\n  }\n\n  freeaddrinfo(ai);\n\n  if (sock == -1) {\n    if (err == 0)\n      throw std::runtime_error(\"No useful address for host\");\n    else\n      throw core::socket_error(\"Unable to connect to socket\", err);\n  }\n\n  // Take proper ownership of the socket\n  setFd(sock);\n\n  // Disable Nagle's algorithm, to reduce latency\n  enableNagles(false);\n}\n\nconst char* TcpSocket::getPeerAddress() {\n  vnc_sockaddr_t sa;\n  socklen_t sa_size = sizeof(sa);\n\n  if (getpeername(getFd(), &sa.u.sa, &sa_size) != 0) {\n    vlog.error(\"Unable to get peer name for socket\");\n    return \"(N/A)\";\n  }\n\n  if (sa.u.sa.sa_family == AF_INET6) {\n    static char buffer[INET6_ADDRSTRLEN + 2];\n    int ret;\n\n    buffer[0] = '[';\n\n    ret = getnameinfo(&sa.u.sa, sizeof(sa.u.sin6),\n                      buffer + 1, sizeof(buffer) - 2, nullptr, 0,\n                      NI_NUMERICHOST);\n    if (ret != 0) {\n      vlog.error(\"Unable to convert peer name to a string\");\n      return \"(N/A)\";\n    }\n\n    strcat(buffer, \"]\");\n\n    return buffer;\n  }\n\n  if (sa.u.sa.sa_family == AF_INET) {\n    char *name;\n\n    name = inet_ntoa(sa.u.sin.sin_addr);\n    if (name == nullptr) {\n      vlog.error(\"Unable to convert peer name to a string\");\n      return \"(N/A)\";\n    }\n\n    return name;\n  }\n\n  vlog.error(\"Unknown address family for socket\");\n  return \"\";\n}\n\nconst char* TcpSocket::getPeerEndpoint() {\n  static char buffer[INET6_ADDRSTRLEN + 2 + 32];\n  vnc_sockaddr_t sa;\n  socklen_t sa_size = sizeof(sa);\n  int port;\n\n  getpeername(getFd(), &sa.u.sa, &sa_size);\n\n  if (sa.u.sa.sa_family == AF_INET6)\n    port = ntohs(sa.u.sin6.sin6_port);\n  else if (sa.u.sa.sa_family == AF_INET)\n    port = ntohs(sa.u.sin.sin_port);\n  else\n    port = 0;\n\n  sprintf(buffer, \"%s::%d\", getPeerAddress(), port);\n\n  return buffer;\n}\n\nbool TcpSocket::enableNagles(bool enable) {\n  int one = enable ? 0 : 1;\n  if (setsockopt(getFd(), IPPROTO_TCP, TCP_NODELAY,\n                 (char *)&one, sizeof(one)) < 0) {\n    int e = errorNumber;\n    vlog.error(\"Unable to setsockopt TCP_NODELAY: %d\", e);\n    return false;\n  }\n  return true;\n}\n\nTcpListener::TcpListener(int sock) : SocketListener(sock)\n{\n}\n\nTcpListener::TcpListener(const struct sockaddr *listenaddr,\n                         socklen_t listenaddrlen)\n{\n  int one = 1;\n  vnc_sockaddr_t sa;\n  int sock;\n\n  if ((sock = socket (listenaddr->sa_family, SOCK_STREAM, 0)) < 0)\n    throw core::socket_error(\"Unable to create listening socket\", errorNumber);\n\n  memcpy (&sa, listenaddr, listenaddrlen);\n#ifdef IPV6_V6ONLY\n  if (listenaddr->sa_family == AF_INET6) {\n    if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&one, sizeof(one))) {\n      int e = errorNumber;\n      closesocket(sock);\n      throw core::socket_error(\"Unable to set IPV6_V6ONLY\", e);\n    }\n  }\n#endif /* defined(IPV6_V6ONLY) */\n\n#ifdef FD_CLOEXEC\n  // - By default, close the socket on exec()\n  fcntl(sock, F_SETFD, FD_CLOEXEC);\n#endif\n\n  // SO_REUSEADDR is broken on Windows. It allows binding to a port\n  // that already has a listening socket on it. SO_EXCLUSIVEADDRUSE\n  // might do what we want, but requires investigation.\n#ifndef WIN32\n  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,\n                 (char *)&one, sizeof(one)) < 0) {\n    int e = errorNumber;\n    closesocket(sock);\n    throw core::socket_error(\"Unable to create listening socket\", e);\n  }\n#endif\n\n  if (bind(sock, &sa.u.sa, listenaddrlen) == -1) {\n    int e = errorNumber;\n    closesocket(sock);\n    throw core::socket_error(\"Failed to bind socket\", e);\n  }\n\n  listen(sock);\n}\n\nSocket* TcpListener::createSocket(int fd_) {\n  return new TcpSocket(fd_);\n}\n\nstd::list<std::string> TcpListener::getMyAddresses() {\n  struct addrinfo *ai, *current, hints;\n  std::list<std::string> result;\n\n  initSockets();\n\n  memset(&hints, 0, sizeof(struct addrinfo));\n  hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;\n  hints.ai_family = AF_UNSPEC;\n  hints.ai_socktype = SOCK_STREAM;\n  hints.ai_canonname = nullptr;\n  hints.ai_addr = nullptr;\n  hints.ai_next = nullptr;\n\n  // Windows doesn't like NULL for service, so specify something\n  if ((getaddrinfo(nullptr, \"1\", &hints, &ai)) != 0)\n    return result;\n\n  for (current= ai; current != nullptr; current = current->ai_next) {\n    char addr[INET6_ADDRSTRLEN];\n\n    switch (current->ai_family) {\n    case AF_INET:\n      if (!UseIPv4)\n        continue;\n      break;\n    case AF_INET6:\n      if (!UseIPv6)\n        continue;\n      break;\n    default:\n      continue;\n    }\n\n    getnameinfo(current->ai_addr, current->ai_addrlen, addr, INET6_ADDRSTRLEN,\n                nullptr, 0, NI_NUMERICHOST);\n\n    result.push_back(addr);\n  }\n\n  freeaddrinfo(ai);\n\n  return result;\n}\n\nint TcpListener::getMyPort() {\n  return getSockPort(getFd());\n}\n\n\nvoid network::createLocalTcpListeners(std::list<SocketListener*> *listeners,\n                                      int port)\n{\n  struct addrinfo ai[2];\n  vnc_sockaddr_t sa[2];\n\n  memset(ai, 0, sizeof(ai));\n  memset(sa, 0, sizeof(sa));\n\n  sa[0].u.sin.sin_family = AF_INET;\n  sa[0].u.sin.sin_port = htons (port);\n  sa[0].u.sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);\n\n  ai[0].ai_family = sa[0].u.sin.sin_family;\n  ai[0].ai_addr = &sa[0].u.sa;\n  ai[0].ai_addrlen = sizeof(sa[0].u.sin);\n  ai[0].ai_next = &ai[1];\n\n  sa[1].u.sin6.sin6_family = AF_INET6;\n  sa[1].u.sin6.sin6_port = htons (port);\n  sa[1].u.sin6.sin6_addr = in6addr_loopback;\n\n  ai[1].ai_family = sa[1].u.sin6.sin6_family;\n  ai[1].ai_addr = &sa[1].u.sa;\n  ai[1].ai_addrlen = sizeof(sa[1].u.sin6);\n  ai[1].ai_next = nullptr;\n\n  createTcpListeners(listeners, ai);\n}\n\nvoid network::createTcpListeners(std::list<SocketListener*> *listeners,\n                                 const char *addr,\n                                 int port)\n{\n  struct addrinfo *ai, hints;\n  char service[16];\n  int result;\n\n  initSockets();\n\n  memset(&hints, 0, sizeof(struct addrinfo));\n  hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;\n  hints.ai_family = AF_UNSPEC;\n  hints.ai_socktype = SOCK_STREAM;\n  hints.ai_canonname = nullptr;\n  hints.ai_addr = nullptr;\n  hints.ai_next = nullptr;\n\n  snprintf (service, sizeof (service) - 1, \"%d\", port);\n  service[sizeof (service) - 1] = '\\0';\n  if ((result = getaddrinfo(addr, service, &hints, &ai)) != 0)\n    throw core::getaddrinfo_error(\"Unable to resolve listening address\", result);\n\n  try {\n    createTcpListeners(listeners, ai);\n  } catch(...) {\n    freeaddrinfo(ai);\n    throw;\n  }\n\n  freeaddrinfo(ai);\n}\n\nvoid network::createTcpListeners(std::list<SocketListener*> *listeners,\n                                 const struct addrinfo *ai)\n{\n  const struct addrinfo *current;\n  std::list<SocketListener*> new_listeners;\n\n  initSockets();\n\n  for (current = ai; current != nullptr; current = current->ai_next) {\n    switch (current->ai_family) {\n    case AF_INET:\n      if (!UseIPv4)\n        continue;\n      break;\n\n    case AF_INET6:\n      if (!UseIPv6)\n        continue;\n      break;\n\n    default:\n      continue;\n    }\n\n    try {\n      new_listeners.push_back(new TcpListener(current->ai_addr,\n                                              current->ai_addrlen));\n    } catch (core::socket_error& e) {\n      // Ignore this if it is due to lack of address family support on\n      // the interface or on the system\n      if (e.err != EADDRNOTAVAIL && e.err != EAFNOSUPPORT) {\n        // Otherwise, report the error\n        while (!new_listeners.empty()) {\n          delete new_listeners.back();\n          new_listeners.pop_back();\n        }\n        throw;\n      }\n    }\n  }\n\n  listeners->splice (listeners->end(), new_listeners);\n}\n\n\nTcpFilter::TcpFilter(const char* spec) {\n  std::vector<std::string> patterns;\n\n  patterns = core::split(spec, ',');\n\n  for (size_t i = 0; i < patterns.size(); i++) {\n    if (!patterns[i].empty())\n      filter.push_back(parsePattern(patterns[i].c_str()));\n  }\n}\n\nTcpFilter::~TcpFilter() {\n}\n\n\nstatic bool\npatternMatchIP(const TcpFilter::Pattern& pattern, vnc_sockaddr_t *sa) {\n  switch (pattern.address.u.sa.sa_family) {\n    unsigned long address;\n\n  case AF_INET:\n    if (sa->u.sa.sa_family != AF_INET)\n      return false;\n\n    address = sa->u.sin.sin_addr.s_addr;\n    if (address == htonl (INADDR_NONE)) return false;\n    return ((pattern.address.u.sin.sin_addr.s_addr &\n             pattern.mask.u.sin.sin_addr.s_addr) ==\n            (address & pattern.mask.u.sin.sin_addr.s_addr));\n\n  case AF_INET6:\n    if (sa->u.sa.sa_family != AF_INET6)\n      return false;\n\n    for (unsigned int n = 0; n < 16; n++) {\n      unsigned int bits = (n + 1) * 8;\n      unsigned int mask;\n      if (pattern.prefixlen > bits)\n        mask = 0xff;\n      else {\n        unsigned int lastbits = 0xff;\n        lastbits <<= bits - pattern.prefixlen;\n        mask = lastbits & 0xff;\n      }\n\n      if ((pattern.address.u.sin6.sin6_addr.s6_addr[n] & mask) !=\n          (sa->u.sin6.sin6_addr.s6_addr[n] & mask))\n        return false;\n\n      if (mask < 0xff)\n        break;\n    }\n\n    return true;\n\n  case AF_UNSPEC:\n    // Any address matches\n    return true;\n\n  default:\n    break;\n  }\n\n  return false;\n}\n\nbool\nTcpFilter::verifyConnection(Socket* s) {\n  vnc_sockaddr_t sa;\n  socklen_t sa_size = sizeof(sa);\n\n  if (getpeername(s->getFd(), &sa.u.sa, &sa_size) != 0)\n    return false;\n\n  std::list<TcpFilter::Pattern>::iterator i;\n  for (i=filter.begin(); i!=filter.end(); i++) {\n    if (patternMatchIP(*i, &sa)) {\n      switch ((*i).action) {\n      case Accept:\n        vlog.debug(\"ACCEPT %s\", s->getPeerAddress());\n        return true;\n      case Query:\n        vlog.debug(\"QUERY %s\", s->getPeerAddress());\n        s->setRequiresQuery();\n        return true;\n      case Reject:\n        vlog.debug(\"REJECT %s\", s->getPeerAddress());\n        return false;\n      }\n    }\n  }\n\n  vlog.debug(\"[REJECT] %s\", s->getPeerAddress());\n  return false;\n}\n\n\nTcpFilter::Pattern TcpFilter::parsePattern(const char* p) {\n  TcpFilter::Pattern pattern;\n\n  std::vector<std::string> parts;\n  int family;\n\n  initSockets();\n\n  parts = core::split(&p[1], '/');\n  if (parts.size() > 2)\n    throw std::invalid_argument(\"Invalid filter specified\");\n\n  if (parts.empty() || parts[0].empty()) {\n    // Match any address\n    memset (&pattern.address, 0, sizeof (pattern.address));\n    pattern.address.u.sa.sa_family = AF_UNSPEC;\n    pattern.prefixlen = 0;\n  } else {\n    struct addrinfo hints;\n    struct addrinfo *ai;\n    int result;\n    memset (&hints, 0, sizeof (hints));\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_flags = AI_NUMERICHOST;\n\n    // Take out brackets, if present\n    if (parts[0][0] == '[') {\n      parts[0].erase(0, 1);\n      if (!parts[0].empty() && parts[0][parts.size()-1] == ']')\n        parts[0].erase(parts.size()-1, 1);\n    }\n\n    if ((result = getaddrinfo (parts[0].c_str(), nullptr, &hints, &ai)) != 0) {\n      throw core::getaddrinfo_error(\"Unable to resolve host by name\", result);\n    }\n\n    memcpy (&pattern.address.u.sa, ai->ai_addr, ai->ai_addrlen);\n    freeaddrinfo (ai);\n\n    family = pattern.address.u.sa.sa_family;\n\n    if (parts.size() > 1) {\n      if (family == AF_INET &&\n          (parts[1].find('.') != std::string::npos)) {\n        throw std::invalid_argument(\"Mask no longer supported for \"\n                                    \"filter, use prefix instead\");\n      }\n\n      pattern.prefixlen = (unsigned int) atoi(parts[1].c_str());\n    } else {\n      switch (family) {\n      case AF_INET:\n        pattern.prefixlen = 32;\n        break;\n      case AF_INET6:\n        pattern.prefixlen = 128;\n        break;\n      default:\n        throw std::runtime_error(\"Unknown address family\");\n      }\n    }\n  }\n\n  family = pattern.address.u.sa.sa_family;\n\n  if (pattern.prefixlen > (family == AF_INET ? 32: 128))\n    throw std::invalid_argument(\n      core::format(\"Invalid prefix length for filter address: %u\",\n                   pattern.prefixlen));\n\n  // Compute mask from address and prefix length\n  memset (&pattern.mask, 0, sizeof (pattern.mask));\n  switch (family) {\n    unsigned long mask;\n  case AF_INET:\n    mask = 0;\n    for (unsigned int i=0; i<pattern.prefixlen; i++)\n      mask |= 1<<(31-i);\n    pattern.mask.u.sin.sin_addr.s_addr = htonl(mask);\n    break;\n\n  case AF_INET6:\n    for (unsigned int n = 0; n < 16; n++) {\n      unsigned int bits = (n + 1) * 8;\n      if (pattern.prefixlen > bits)\n        pattern.mask.u.sin6.sin6_addr.s6_addr[n] = 0xff;\n      else {\n        unsigned int lastbits = 0xff;\n        lastbits <<= bits - pattern.prefixlen;\n        pattern.mask.u.sin6.sin6_addr.s6_addr[n] = lastbits & 0xff;\n        break;\n      }\n    }\n    break;\n  case AF_UNSPEC:\n    // No mask to compute\n    break;\n  default:\n    ; /* not reached */\n  }\n\n  switch(p[0]) {\n  case '+': pattern.action = TcpFilter::Accept; break;\n  case '-': pattern.action = TcpFilter::Reject; break;\n  case '?': pattern.action = TcpFilter::Query; break;\n  };\n\n  return pattern;\n}\n\nstd::string TcpFilter::patternToStr(const TcpFilter::Pattern& p) {\n  char addr[INET6_ADDRSTRLEN + 2];\n\n  if (p.address.u.sa.sa_family == AF_INET) {\n    getnameinfo(&p.address.u.sa, sizeof(p.address.u.sin),\n                addr, sizeof(addr), nullptr, 0, NI_NUMERICHOST);\n  } else if (p.address.u.sa.sa_family == AF_INET6) {\n    addr[0] = '[';\n    getnameinfo(&p.address.u.sa, sizeof(p.address.u.sin6),\n                addr + 1, sizeof(addr) - 2, nullptr, 0, NI_NUMERICHOST);\n    strcat(addr, \"]\");\n  } else\n    addr[0] = '\\0';\n\n  char action;\n  switch (p.action) {\n  case Accept: action = '+'; break;\n  case Reject: action = '-'; break;\n  default:\n  case Query: action = '?'; break;\n  };\n  size_t resultlen = (1                   // action\n                      + strlen (addr)     // address\n                      + 1                 // slash\n                      + 3                 // prefix length, max 128\n                      + 1);               // terminating nul\n  char* result = new char[resultlen];\n  if (addr[0] == '\\0')\n    snprintf(result, resultlen, \"%c\", action);\n  else\n    snprintf(result, resultlen, \"%c%s/%u\", action, addr, p.prefixlen);\n\n  std::string out = result;\n\n  delete [] result;\n\n  return out;\n}\n"
  },
  {
    "path": "common/network/TcpSocket.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- TcpSocket.h - base-class for TCP stream sockets.\n//     This header also defines the TcpListener class, used\n//     to listen for incoming socket connections over TCP\n//\n//     NB: Any file descriptors created by the TcpSocket or\n//     TcpListener classes are close-on-exec if the OS supports\n//     it.  TcpSockets initialised with a caller-supplied fd\n//     are NOT set to close-on-exec.\n\n#ifndef __NETWORK_TCP_SOCKET_H__\n#define __NETWORK_TCP_SOCKET_H__\n\n#include <network/Socket.h>\n\n#ifdef WIN32\n#include <winsock2.h>\n#include <ws2tcpip.h>\n#else\n#include <sys/socket.h> /* for socklen_t */\n#include <netinet/in.h> /* for struct sockaddr_in */\n#endif\n\n#include <list>\n#include <string>\n\n/* Tunnelling support. */\n#define TUNNEL_PORT_OFFSET 5500\n\nnamespace network {\n\n  /* Tunnelling support. */\n  int findFreeTcpPort (void);\n\n  void getHostAndPort(const char* hi, std::string* host,\n                      int* port, int basePort=5900);\n\n  int getSockPort(int sock);\n\n  class TcpSocket : public Socket {\n  public:\n    TcpSocket(int sock);\n    TcpSocket(const char *name, int port);\n\n    const char* getPeerAddress() override;\n    const char* getPeerEndpoint() override;\n\n  protected:\n    bool enableNagles(bool enable);\n  };\n\n  class TcpListener : public SocketListener {\n  public:\n    TcpListener(const struct sockaddr *listenaddr, socklen_t listenaddrlen);\n    TcpListener(int sock);\n\n    int getMyPort() override;\n\n    static std::list<std::string> getMyAddresses();\n\n  protected:\n    Socket* createSocket(int fd) override;\n  };\n\n  void createLocalTcpListeners(std::list<SocketListener*> *listeners,\n                               int port);\n  void createTcpListeners(std::list<SocketListener*> *listeners,\n                          const char *addr,\n                          int port);\n  void createTcpListeners(std::list<SocketListener*> *listeners,\n                          const struct addrinfo *ai);\n\n  typedef struct vnc_sockaddr {\n    union {\n      sockaddr     sa;\n      sockaddr_in  sin;\n      sockaddr_in6 sin6;\n    } u;\n  } vnc_sockaddr_t;\n\n  class TcpFilter : public ConnectionFilter {\n  public:\n    TcpFilter(const char* filter);\n    virtual ~TcpFilter();\n\n    bool verifyConnection(Socket* s) override;\n\n    typedef enum {Accept, Reject, Query} Action;\n    struct Pattern {\n      Action action;\n      vnc_sockaddr_t address;\n      unsigned int prefixlen;\n\n      vnc_sockaddr_t mask; // computed from address and prefix\n    };\n    static Pattern parsePattern(const char* s);\n    static std::string patternToStr(const Pattern& p);\n  protected:\n    std::list<Pattern> filter;\n  };\n\n}\n\n#endif // __NETWORK_TCP_SOCKET_H__\n"
  },
  {
    "path": "common/network/UnixSocket.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (c) 2012 University of Oslo.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <sys/stat.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n#include <unistd.h>\n#include <errno.h>\n#include <stdlib.h>\n#include <stddef.h>\n#include <string.h>\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <network/UnixSocket.h>\n\nusing namespace network;\n\nstatic core::LogWriter vlog(\"UnixSocket\");\n\n// -=- UnixSocket\n\nUnixSocket::UnixSocket(int sock) : Socket(sock)\n{\n}\n\nUnixSocket::UnixSocket(const char *path)\n{\n  int sock, err, result;\n  sockaddr_un addr;\n  socklen_t salen;\n\n  if (strlen(path) >= sizeof(addr.sun_path))\n    throw core::socket_error(\"Socket path is too long\", ENAMETOOLONG);\n\n  // - Create a socket\n  sock = socket(AF_UNIX, SOCK_STREAM, 0);\n  if (sock == -1)\n    throw core::socket_error(\"Unable to create socket\", errno);\n\n  // - Attempt to connect\n  memset(&addr, 0, sizeof(addr));\n  addr.sun_family = AF_UNIX;\n  strcpy(addr.sun_path, path);\n  salen = sizeof(addr);\n  while ((result = connect(sock, (sockaddr *)&addr, salen)) == -1) {\n    err = errno;\n    close(sock);\n    break;\n  }\n\n  if (result == -1)\n    throw core::socket_error(\"Unable to connect to socket\", err);\n\n  setFd(sock);\n}\n\nconst char* UnixSocket::getPeerAddress() {\n  static struct sockaddr_un addr;\n  socklen_t salen;\n\n  // AF_UNIX only has a single address (the server side).\n  // Unfortunately we don't know which end we are, so we'll have to\n  // test a bit.\n\n  salen = sizeof(addr);\n  if (getpeername(getFd(), (struct sockaddr *)&addr, &salen) != 0) {\n    vlog.error(\"Unable to get peer name for socket\");\n    return \"\";\n  }\n\n  if (salen > offsetof(struct sockaddr_un, sun_path))\n    return addr.sun_path;\n\n  salen = sizeof(addr);\n  if (getsockname(getFd(), (struct sockaddr *)&addr, &salen) != 0) {\n    vlog.error(\"Unable to get local name for socket\");\n    return \"\";\n  }\n\n  if (salen > offsetof(struct sockaddr_un, sun_path))\n    return addr.sun_path;\n\n  // socketpair() will create unnamed sockets\n\n  return \"(unnamed UNIX socket)\";\n}\n\nconst char* UnixSocket::getPeerEndpoint() {\n  return getPeerAddress();\n}\n\nUnixListener::UnixListener(const char *path, int mode)\n{\n  struct sockaddr_un addr;\n  mode_t saved_umask;\n  int err, result;\n\n  if (strlen(path) >= sizeof(addr.sun_path))\n    throw core::socket_error(\"Socket path is too long\", ENAMETOOLONG);\n\n  // - Create a socket\n  if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)\n    throw core::socket_error(\"Unable to create listening socket\", errno);\n\n  // - Delete existing socket (ignore result)\n  unlink(path);\n\n  // - Attempt to bind to the requested path\n  memset(&addr, 0, sizeof(addr));\n  addr.sun_family = AF_UNIX;\n  strcpy(addr.sun_path, path);\n  saved_umask = umask(0777);\n  result = bind(fd, (struct sockaddr *)&addr, sizeof(addr));\n  err = errno;\n  umask(saved_umask);\n  if (result < 0) {\n    close(fd);\n    throw core::socket_error(\"Unable to bind listening socket\", err);\n  }\n\n  // - Set socket mode\n  if (chmod(path, mode) < 0) {\n    err = errno;\n    close(fd);\n    throw core::socket_error(\"Unable to set socket mode\", err);\n  }\n\n  listen(fd);\n}\n\nUnixListener::~UnixListener()\n{\n  struct sockaddr_un addr;\n  socklen_t salen = sizeof(addr);\n\n  if (getsockname(getFd(), (struct sockaddr *)&addr, &salen) == 0)\n    unlink(addr.sun_path);\n}\n\nSocket* UnixListener::createSocket(int fd_) {\n  return new UnixSocket(fd_);\n}\n\nint UnixListener::getMyPort() {\n  return 0;\n}\n"
  },
  {
    "path": "common/network/UnixSocket.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (c) 2012 University of Oslo.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- UnixSocket.h - base-class for UNIX stream sockets.\n//     This header also defines the UnixListener class, used\n//     to listen for incoming socket connections over UNIX\n//\n//     NB: Any file descriptors created by the UnixSocket or\n//     UnixListener classes are close-on-exec if the OS supports\n//     it.  UnixSockets initialised with a caller-supplied fd\n//     are NOT set to close-on-exec.\n\n#ifndef __NETWORK_UNIX_SOCKET_H__\n#define __NETWORK_UNIX_SOCKET_H__\n\n#include <network/Socket.h>\n\nnamespace network {\n\n  class UnixSocket : public Socket {\n  public:\n    UnixSocket(int sock);\n    UnixSocket(const char *name);\n\n    const char* getPeerAddress() override;\n    const char* getPeerEndpoint() override;\n  };\n\n  class UnixListener : public SocketListener {\n  public:\n    UnixListener(const char *listenaddr, int mode);\n    virtual ~UnixListener();\n\n    int getMyPort() override;\n\n  protected:\n    Socket* createSocket(int fd) override;\n  };\n\n}\n\n#endif // __NETWORK_UNIX_SOCKET_H__\n"
  },
  {
    "path": "common/rdr/AESInStream.cxx",
    "content": "/* Copyright (C) 2022 Dinglan Peng\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <stdexcept>\n\n#include <rdr/AESInStream.h>\n\n#ifdef HAVE_NETTLE\nusing namespace rdr;\n\nAESInStream::AESInStream(InStream* _in, const uint8_t* key,\n                         int _keySize)\n  : keySize(_keySize), in(_in), counter()\n{\n  if (keySize == 128)\n    EAX_SET_KEY(&eaxCtx128, aes128_set_encrypt_key, aes128_encrypt, key);\n  else if (keySize == 256)\n    EAX_SET_KEY(&eaxCtx256, aes256_set_encrypt_key, aes256_encrypt, key);\n  else\n    throw std::out_of_range(\"Incorrect key size\");\n}\n\nAESInStream::~AESInStream() {}\n\nbool AESInStream::fillBuffer()\n{\n  if (!in->hasData(2))\n    return false;\n  const uint8_t* buf = in->getptr(2);\n  size_t length = ((int)buf[0] << 8) | (int)buf[1];\n  if (!in->hasData(2 + length + 16))\n    return false;\n  ensureSpace(length);\n  buf = in->getptr(2 + length + 16);\n  const uint8_t* ad = buf;\n  const uint8_t* data = buf + 2;\n  const uint8_t* mac = buf + 2 + length;\n  uint8_t macComputed[16];\n\n  if (keySize == 128) {\n    EAX_SET_NONCE(&eaxCtx128, aes128_encrypt, 16, counter);\n    EAX_UPDATE(&eaxCtx128, aes128_encrypt, 2, ad);\n    EAX_DECRYPT(&eaxCtx128, aes128_encrypt, length, (uint8_t*)end, data);\n    EAX_DIGEST(&eaxCtx128, aes128_encrypt, 16, macComputed);\n  } else {\n    EAX_SET_NONCE(&eaxCtx256, aes256_encrypt, 16, counter);\n    EAX_UPDATE(&eaxCtx256, aes256_encrypt, 2, ad);\n    EAX_DECRYPT(&eaxCtx256, aes256_encrypt, length, (uint8_t*)end, data);\n    EAX_DIGEST(&eaxCtx256, aes256_encrypt, 16, macComputed);\n  }\n  if (memcmp(mac, macComputed, 16) != 0)\n    throw std::runtime_error(\"AESInStream: Failed to authenticate message\");\n  in->setptr(2 + length + 16);\n  end += length;\n\n  // Update nonce by incrementing the counter as a\n  // 128bit little endian unsigned integer\n  for (int i = 0; i < 16; ++i) {\n    // increment until there is no carry\n    if (++counter[i] != 0) {\n      break;\n    }\n  }\n  return true;\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/AESInStream.h",
    "content": "/* Copyright (C) 2022 Dinglan Peng\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RDR_AESINSTREAM_H__\n#define __RDR_AESINSTREAM_H__\n\n#ifdef HAVE_NETTLE\n\n#include <nettle/eax.h>\n#include <nettle/aes.h>\n#include <rdr/BufferedInStream.h>\n\nnamespace rdr {\n\n  class AESInStream : public BufferedInStream {\n  public:\n    AESInStream(InStream* in, const uint8_t* key, int keySize);\n    virtual ~AESInStream();\n\n  private:\n    bool fillBuffer() override;\n\n    int keySize;\n    InStream* in;\n    union {\n      struct EAX_CTX(aes128_ctx) eaxCtx128;\n      struct EAX_CTX(aes256_ctx) eaxCtx256;\n    };\n    uint8_t counter[16];\n  };\n}\n\n#endif\n#endif\n"
  },
  {
    "path": "common/rdr/AESOutStream.cxx",
    "content": "/* Copyright (C) 2022 Dinglan Peng\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <stdexcept>\n\n#include <rdr/AESOutStream.h>\n\n#ifdef HAVE_NETTLE\nusing namespace rdr;\n\nconst int MaxMessageSize = 8192;\n\nAESOutStream::AESOutStream(OutStream* _out, const uint8_t* key,\n                           int _keySize)\n  : keySize(_keySize), out(_out), counter()\n{\n  msg = new uint8_t[MaxMessageSize + 16 + 2];\n  if (keySize == 128)\n    EAX_SET_KEY(&eaxCtx128, aes128_set_encrypt_key, aes128_encrypt, key);\n  else if (keySize == 256)\n    EAX_SET_KEY(&eaxCtx256, aes256_set_encrypt_key, aes256_encrypt, key);\n  else\n    throw std::out_of_range(\"Incorrect key size\");\n}\n\nAESOutStream::~AESOutStream()\n{\n    delete[] msg;\n}\n\nvoid AESOutStream::flush()\n{\n  BufferedOutStream::flush();\n  out->flush();\n}\n\nvoid AESOutStream::cork(bool enable)\n{\n  BufferedOutStream::cork(enable);\n  out->cork(enable);\n}\n\nbool AESOutStream::flushBuffer()\n{\n  while (sentUpTo < ptr) {\n    size_t n = ptr - sentUpTo;\n    if (n > MaxMessageSize)\n      n = MaxMessageSize;\n    writeMessage(sentUpTo, n);\n    sentUpTo += n;\n  }\n  return true;\n}\n\n\nvoid AESOutStream::writeMessage(const uint8_t* data, size_t length)\n{\n  msg[0] = (length & 0xff00) >> 8;\n  msg[1] = length & 0xff;\n\n  if (keySize == 128) {\n    EAX_SET_NONCE(&eaxCtx128, aes128_encrypt, 16, counter);\n    EAX_UPDATE(&eaxCtx128, aes128_encrypt, 2, msg);\n    EAX_ENCRYPT(&eaxCtx128, aes128_encrypt, length, msg + 2, data);\n    EAX_DIGEST(&eaxCtx128, aes128_encrypt, 16, msg + 2 + length);\n  } else {\n    EAX_SET_NONCE(&eaxCtx256, aes256_encrypt, 16, counter);\n    EAX_UPDATE(&eaxCtx256, aes256_encrypt, 2, msg);\n    EAX_ENCRYPT(&eaxCtx256, aes256_encrypt, length, msg + 2, data);\n    EAX_DIGEST(&eaxCtx256, aes256_encrypt, 16, msg + 2 + length);\n  }\n  out->writeBytes(msg, 2 + length + 16);\n  out->flush();\n\n  // Update nonce by incrementing the counter as a\n  // 128bit little endian unsigned integer\n  for (int i = 0; i < 16; ++i) {\n    // increment until there is no carry\n    if (++counter[i] != 0) {\n      break;\n    }\n  }\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/AESOutStream.h",
    "content": "/* Copyright (C) 2022 Dinglan Peng\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RDR_AESOUTSTREAM_H__\n#define __RDR_AESOUTSTREAM_H__\n\n#ifdef HAVE_NETTLE\n#include <nettle/eax.h>\n#include <nettle/aes.h>\n#include <rdr/BufferedOutStream.h>\n\nnamespace rdr {\n\n  class AESOutStream : public BufferedOutStream {\n  public:\n    AESOutStream(OutStream* out, const uint8_t* key, int keySize);\n    virtual ~AESOutStream();\n\n    void flush() override;\n    void cork(bool enable) override;\n\n  private:\n    bool flushBuffer() override;\n    void writeMessage(const uint8_t* data, size_t length);\n\n    int keySize;\n    OutStream* out;\n    uint8_t* msg;\n    union {\n      struct EAX_CTX(aes128_ctx) eaxCtx128;\n      struct EAX_CTX(aes256_ctx) eaxCtx256;\n    };\n    uint8_t counter[16];\n  };\n};\n\n#endif\n#endif\n"
  },
  {
    "path": "common/rdr/BufferedInStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2020 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <core/string.h>\n\n#include <rdr/BufferedInStream.h>\n\nusing namespace rdr;\n\nstatic const size_t DEFAULT_BUF_SIZE = 8192;\nstatic const size_t MAX_BUF_SIZE = 32 * 1024 * 1024;\n\nBufferedInStream::BufferedInStream()\n  : bufSize(DEFAULT_BUF_SIZE), offset(0)\n{\n  ptr = end = start = new uint8_t[bufSize];\n  gettimeofday(&lastSizeCheck, nullptr);\n  peakUsage = 0;\n}\n\nBufferedInStream::~BufferedInStream()\n{\n  delete [] start;\n}\n\nsize_t BufferedInStream::pos()\n{\n  return offset + ptr - start;\n}\n\nvoid BufferedInStream::ensureSpace(size_t needed)\n{\n  struct timeval now;\n\n  // Given argument is how much free space is needed, but for allocation\n  // purposes we need to now how much space everything needs, including\n  // any existing data already in the buffer\n  needed += avail();\n\n  if (needed > bufSize) {\n    size_t newSize;\n    uint8_t* newBuffer;\n\n    if (needed > MAX_BUF_SIZE)\n      throw std::out_of_range(core::format(\n        \"BufferedInStream overrun: requested size of %lu bytes exceeds \"\n        \"maximum of %lu bytes\",\n        (long unsigned)needed, (long unsigned)MAX_BUF_SIZE));\n\n    newSize = DEFAULT_BUF_SIZE;\n    while (newSize < needed)\n      newSize *= 2;\n\n    newBuffer = new uint8_t[newSize];\n    memcpy(newBuffer, ptr, end - ptr);\n    delete [] start;\n    bufSize = newSize;\n\n    offset += ptr - start;\n    end = newBuffer + (end - ptr);\n    ptr = start = newBuffer;\n\n    gettimeofday(&lastSizeCheck, nullptr);\n    peakUsage = needed;\n  }\n\n  if (needed > peakUsage)\n    peakUsage = needed;\n\n  // Time to shrink an excessive buffer?\n  gettimeofday(&now, nullptr);\n  if ((avail() == 0) && (bufSize > DEFAULT_BUF_SIZE) &&\n      ((now.tv_sec < lastSizeCheck.tv_sec) ||\n       (now.tv_sec > (lastSizeCheck.tv_sec + 5)))) {\n    if (peakUsage < (bufSize / 2)) {\n      size_t newSize;\n\n      newSize = DEFAULT_BUF_SIZE;\n      while (newSize < peakUsage)\n        newSize *= 2;\n\n      // We know the buffer is empty, so just reset everything\n      delete [] start;\n      ptr = end = start = new uint8_t[newSize];\n      bufSize = newSize;\n    }\n\n    gettimeofday(&lastSizeCheck, nullptr);\n    peakUsage = needed;\n  }\n\n  // Do we need to shuffle things around?\n  if ((bufSize - (ptr - start)) < needed) {\n    memmove(start, ptr, end - ptr);\n\n    offset += ptr - start;\n    end -= ptr - start;\n    ptr = start;\n  }\n}\n\nbool BufferedInStream::overrun(size_t needed)\n{\n  // Make sure fillBuffer() has room for all the requested data\n  assert(needed > avail());\n  ensureSpace(needed - avail());\n\n  while (avail() < needed) {\n    if (!fillBuffer())\n      return false;\n  }\n\n  return true;\n}\n"
  },
  {
    "path": "common/rdr/BufferedInStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2020 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// Base class for input streams with a buffer\n//\n\n#ifndef __RDR_BUFFEREDINSTREAM_H__\n#define __RDR_BUFFEREDINSTREAM_H__\n\n#include <sys/time.h>\n\n#include <rdr/InStream.h>\n\nnamespace rdr {\n\n  class BufferedInStream : public InStream {\n\n  public:\n    virtual ~BufferedInStream();\n\n    size_t pos() override;\n\n  protected:\n    size_t availSpace() { return start + bufSize - end; }\n\n    void ensureSpace(size_t needed);\n\n  private:\n    virtual bool fillBuffer() = 0;\n\n    bool overrun(size_t needed) override;\n\n  private:\n    size_t bufSize;\n    size_t offset;\n    uint8_t* start;\n\n    struct timeval lastSizeCheck;\n    size_t peakUsage;\n\n  protected:\n    BufferedInStream();\n  };\n\n} // end of namespace rdr\n\n#endif\n"
  },
  {
    "path": "common/rdr/BufferedOutStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2020 Pierre Ossman for Cendio AB\n * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/string.h>\n\n#include <rdr/BufferedOutStream.h>\n\nusing namespace rdr;\n\nstatic const size_t DEFAULT_BUF_SIZE = 16384;\nstatic const size_t MAX_BUF_SIZE = 32 * 1024 * 1024;\n\nBufferedOutStream::BufferedOutStream(bool emulateCork_)\n  : bufSize(DEFAULT_BUF_SIZE), offset(0), emulateCork(emulateCork_)\n{\n  ptr = start = sentUpTo = new uint8_t[bufSize];\n  end = start + bufSize;\n  gettimeofday(&lastSizeCheck, nullptr);\n  peakUsage = 0;\n}\n\nBufferedOutStream::~BufferedOutStream()\n{\n  // FIXME: Complain about non-flushed buffer?\n  delete [] start;\n}\n\nsize_t BufferedOutStream::length()\n{\n  return offset + ptr - sentUpTo;\n}\n\nvoid BufferedOutStream::flush()\n{\n  struct timeval now;\n\n  // Only give larger chunks if corked to minimize overhead\n  if (corked && emulateCork && ((ptr - sentUpTo) < 1024))\n    return;\n\n  while (sentUpTo < ptr) {\n    size_t len;\n\n    len = (ptr - sentUpTo);\n\n    if (!flushBuffer())\n      break;\n\n    offset += len - (ptr - sentUpTo);\n  }\n\n  // Managed to flush everything?\n  if (sentUpTo == ptr)\n    ptr = sentUpTo = start;\n\n  // Time to shrink an excessive buffer?\n  gettimeofday(&now, nullptr);\n  if ((sentUpTo == ptr) && (bufSize > DEFAULT_BUF_SIZE) &&\n      ((now.tv_sec < lastSizeCheck.tv_sec) ||\n       (now.tv_sec > (lastSizeCheck.tv_sec + 5)))) {\n    if (peakUsage < (bufSize / 2)) {\n      size_t newSize;\n\n      newSize = DEFAULT_BUF_SIZE;\n      while (newSize < peakUsage)\n        newSize *= 2;\n\n      // We know the buffer is empty, so just reset everything\n      delete [] start;\n      ptr = start = sentUpTo = new uint8_t[newSize];\n      end = start + newSize;\n      bufSize = newSize;\n    }\n\n    gettimeofday(&lastSizeCheck, nullptr);\n    peakUsage = 0;\n  }\n}\n\nbool BufferedOutStream::hasBufferedData()\n{\n  return sentUpTo != ptr;\n}\n\nvoid BufferedOutStream::overrun(size_t needed)\n{\n  bool oldCorked;\n  size_t totalNeeded, newSize;\n  uint8_t* newBuffer;\n\n  // First try to get rid of the data we have\n  // (use corked to make things a bit more efficient since we're not\n  // trying to flush out everything, just make some room)\n  oldCorked = corked;\n  cork(true);\n  flush();\n  cork(oldCorked);\n\n  // Make note of the total needed space\n  totalNeeded = needed + (ptr - sentUpTo);\n\n  if (totalNeeded > peakUsage)\n    peakUsage = totalNeeded;\n\n  // Enough free space now?\n  if (avail() > needed)\n    return;\n\n  // Can we shuffle things around?\n  if (needed < bufSize - (ptr - sentUpTo)) {\n    memmove(start, sentUpTo, ptr - sentUpTo);\n    ptr = start + (ptr - sentUpTo);\n    sentUpTo = start;\n    return;\n  }\n\n  // We'll need to allocate more buffer space...\n\n  if (totalNeeded > MAX_BUF_SIZE)\n    throw std::out_of_range(core::format(\n      \"BufferedOutStream overrun: requested size of %lu bytes exceeds \"\n      \"maximum of %lu bytes\",\n      (long unsigned)totalNeeded, (long unsigned)MAX_BUF_SIZE));\n\n  newSize = DEFAULT_BUF_SIZE;\n  while (newSize < totalNeeded)\n    newSize *= 2;\n\n  newBuffer = new uint8_t[newSize];\n  memcpy(newBuffer, sentUpTo, ptr - sentUpTo);\n  delete [] start;\n  bufSize = newSize;\n\n  ptr = newBuffer + (ptr - sentUpTo);\n  sentUpTo = start = newBuffer;\n  end = newBuffer + newSize;\n\n  gettimeofday(&lastSizeCheck, nullptr);\n  peakUsage = totalNeeded;\n\n  return;\n}\n"
  },
  {
    "path": "common/rdr/BufferedOutStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2020 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// Base class for output streams with a buffer\n//\n\n#ifndef __RDR_BUFFEREDOUTSTREAM_H__\n#define __RDR_BUFFEREDOUTSTREAM_H__\n\n#include <sys/time.h>\n\n#include <rdr/OutStream.h>\n\nnamespace rdr {\n\n  class BufferedOutStream : public OutStream {\n\n  public:\n    virtual ~BufferedOutStream();\n\n    size_t length() override;\n    void flush() override;\n\n    // hasBufferedData() checks if there is any data yet to be flushed\n\n    bool hasBufferedData();\n\n  private:\n    // flushBuffer() requests that the stream be flushed. Returns true if it is\n    // able to progress the output (which might still not mean any bytes\n    // actually moved) and can be called again.\n\n    virtual bool flushBuffer() = 0;\n\n    void overrun(size_t needed) override;\n\n  private:\n    size_t bufSize;\n    size_t offset;\n    uint8_t* start;\n\n    struct timeval lastSizeCheck;\n    size_t peakUsage;\n\n    bool emulateCork;\n\n  protected:\n    uint8_t* sentUpTo;\n\n  protected:\n    BufferedOutStream(bool emulateCork=true);\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/CMakeLists.txt",
    "content": "add_library(rdr STATIC\n  AESInStream.cxx\n  AESOutStream.cxx\n  BufferedInStream.cxx\n  BufferedOutStream.cxx\n  FdInStream.cxx\n  FdOutStream.cxx\n  FileInStream.cxx\n  HexInStream.cxx\n  HexOutStream.cxx\n  RandomStream.cxx\n  TLSException.cxx\n  TLSInStream.cxx\n  TLSOutStream.cxx\n  TLSSocket.cxx\n  ZlibInStream.cxx\n  ZlibOutStream.cxx)\n\ntarget_include_directories(rdr PUBLIC ${CMAKE_SOURCE_DIR}/common)\ntarget_include_directories(rdr SYSTEM PUBLIC ${ZLIB_INCLUDE_DIRS})\ntarget_link_libraries(rdr core)\ntarget_link_libraries(rdr ${ZLIB_LIBRARIES})\n\nif(GNUTLS_FOUND)\n  target_include_directories(rdr SYSTEM PUBLIC ${GNUTLS_INCLUDE_DIR})\n  target_link_libraries(rdr ${GNUTLS_LIBRARIES})\nendif()\nif (NETTLE_FOUND)\n  target_include_directories(rdr SYSTEM PUBLIC ${NETTLE_INCLUDE_DIRS})\n  target_link_libraries(rdr ${NETTLE_LIBRARIES})\nendif()\nif(WIN32)\n\ttarget_link_libraries(rdr ws2_32)\nendif()\n\nif(UNIX)\n  libtool_create_control_file(rdr)\nendif()\n"
  },
  {
    "path": "common/rdr/FdInStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <string.h>\n#include <errno.h>\n#include <sys/time.h>\n#ifdef _WIN32\n#include <winsock2.h>\n#define errorNumber WSAGetLastError()\n#define close closesocket\n#include <core/winerrno.h>\n#else\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <unistd.h>\n#define errorNumber errno\n#endif\n\n/* Old systems have select() in sys/time.h */\n#ifdef HAVE_SYS_SELECT_H\n#include <sys/select.h>\n#endif\n\n#include <core/Exception.h>\n\n#include <rdr/FdInStream.h>\n\nusing namespace rdr;\n\nFdInStream::FdInStream(int fd_, bool closeWhenDone_)\n  : fd(fd_), closeWhenDone(closeWhenDone_)\n{\n}\n\nFdInStream::~FdInStream()\n{\n  if (closeWhenDone) close(fd);\n}\n\n\nbool FdInStream::fillBuffer()\n{\n  size_t n = readFd((uint8_t*)end, availSpace());\n  if (n == 0)\n    return false;\n  end += n;\n\n  return true;\n}\n\n//\n// readFd() reads up to the given length in bytes from the\n// file descriptor into a buffer. Zero is\n// returned if no bytes can be read. Otherwise it returns the number of bytes read.  It\n// never attempts to recv() unless select() indicates that the fd is readable -\n// this means it can be used on an fd which has been set non-blocking.  It also\n// has to cope with the annoying possibility of both select() and recv()\n// returning EINTR.\n//\n\nsize_t FdInStream::readFd(uint8_t* buf, size_t len)\n{\n  int n;\n  do {\n    fd_set fds;\n    struct timeval tv;\n\n    tv.tv_sec = tv.tv_usec = 0;\n\n    FD_ZERO(&fds);\n    FD_SET(fd, &fds);\n    n = select(fd+1, &fds, nullptr, nullptr, &tv);\n  } while (n < 0 && errorNumber == EINTR);\n\n  if (n < 0)\n    throw core::socket_error(\"select\", errorNumber);\n\n  if (n == 0)\n    return 0;\n\n  do {\n    n = ::recv(fd, (char*)buf, len, 0);\n  } while (n < 0 && errorNumber == EINTR);\n\n  if (n < 0)\n    throw core::socket_error(\"read\", errorNumber);\n  if (n == 0)\n    throw end_of_stream();\n\n  return n;\n}\n"
  },
  {
    "path": "common/rdr/FdInStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// FdInStream streams from a file descriptor.\n//\n\n#ifndef __RDR_FDINSTREAM_H__\n#define __RDR_FDINSTREAM_H__\n\n#include <rdr/BufferedInStream.h>\n\nnamespace rdr {\n\n  class FdInStream : public BufferedInStream {\n\n  public:\n\n    FdInStream(int fd, bool closeWhenDone_=false);\n    virtual ~FdInStream();\n\n    int getFd() { return fd; }\n\n  private:\n    bool fillBuffer() override;\n\n    size_t readFd(uint8_t* buf, size_t len);\n\n    int fd;\n    bool closeWhenDone;\n  };\n\n} // end of namespace rdr\n\n#endif\n"
  },
  {
    "path": "common/rdr/FdOutStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011 Pierre Ossman for Cendio AB\n * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <string.h>\n#include <errno.h>\n#ifdef _WIN32\n#include <winsock2.h>\n#define errorNumber WSAGetLastError()\n#include <core/winerrno.h>\n#else\n#include <sys/types.h>\n#include <unistd.h>\n#include <sys/time.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#define errorNumber errno\n#endif\n\n/* Old systems have select() in sys/time.h */\n#ifdef HAVE_SYS_SELECT_H\n#include <sys/select.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/time.h>\n\n#include <rdr/FdOutStream.h>\n\nusing namespace rdr;\n\nFdOutStream::FdOutStream(int fd_)\n#ifdef TCP_CORK\n  : BufferedOutStream(false),\n#else\n  : BufferedOutStream(true),\n#endif\n  fd(fd_)\n{\n  gettimeofday(&lastWrite, nullptr);\n}\n\nFdOutStream::~FdOutStream()\n{\n}\n\nunsigned FdOutStream::getIdleTime()\n{\n  return core::msSince(&lastWrite);\n}\n\nvoid FdOutStream::cork(bool enable)\n{\n  BufferedOutStream::cork(enable);\n\n#ifdef TCP_CORK\n  int one = enable ? 1 : 0;\n  setsockopt(fd, IPPROTO_TCP, TCP_CORK, (char *)&one, sizeof(one));\n#endif\n}\n\nbool FdOutStream::flushBuffer()\n{\n  size_t n = writeFd(sentUpTo, ptr - sentUpTo);\n  if (n == 0)\n    return false;\n\n  sentUpTo += n;\n\n  return true;\n}\n\n//\n// writeFd() writes up to the given length in bytes from the given\n// buffer to the file descriptor. It returns the number of bytes written.  It\n// never attempts to send() unless select() indicates that the fd is writable\n// - this means it can be used on an fd which has been set non-blocking.  It\n// also has to cope with the annoying possibility of both select() and send()\n// returning EINTR.\n//\n\nsize_t FdOutStream::writeFd(const uint8_t* data, size_t length)\n{\n  int n;\n\n  do {\n    fd_set fds;\n    struct timeval tv;\n\n    tv.tv_sec = tv.tv_usec = 0;\n\n    FD_ZERO(&fds);\n    FD_SET(fd, &fds);\n    n = select(fd+1, nullptr, &fds, nullptr, &tv);\n  } while (n < 0 && errorNumber == EINTR);\n\n  if (n < 0)\n    throw core::socket_error(\"select\", errorNumber);\n\n  if (n == 0)\n    return 0;\n\n  do {\n    // select only guarantees that you can write SO_SNDLOWAT without\n    // blocking, which is normally 1. Use MSG_DONTWAIT to avoid\n    // blocking, when possible.\n#ifndef MSG_DONTWAIT\n    n = ::send(fd, (const char*)data, length, 0);\n#else\n    n = ::send(fd, (const char*)data, length, MSG_DONTWAIT);\n#endif\n  } while (n < 0 && (errorNumber == EINTR));\n\n  if (n < 0)\n    throw core::socket_error(\"write\", errorNumber);\n\n  gettimeofday(&lastWrite, nullptr);\n\n  return n;\n}\n"
  },
  {
    "path": "common/rdr/FdOutStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// FdOutStream streams to a file descriptor.\n//\n\n#ifndef __RDR_FDOUTSTREAM_H__\n#define __RDR_FDOUTSTREAM_H__\n\n#include <sys/time.h>\n\n#include <rdr/BufferedOutStream.h>\n\nnamespace rdr {\n\n  class FdOutStream : public BufferedOutStream {\n\n  public:\n\n    FdOutStream(int fd);\n    virtual ~FdOutStream();\n\n    int getFd() { return fd; }\n\n    unsigned getIdleTime();\n\n    void cork(bool enable) override;\n\n  private:\n    bool flushBuffer() override;\n    size_t writeFd(const uint8_t* data, size_t length);\n    int fd;\n    struct timeval lastWrite;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/FileInStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2013 D. R. Commander.  All Rights Reserved.\n * Copyright 2015 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <errno.h>\n\n#include <core/Exception.h>\n\n#include <rdr/FileInStream.h>\n\nusing namespace rdr;\n\nFileInStream::FileInStream(const char *fileName)\n{\n  file = fopen(fileName, \"rb\");\n  if (!file)\n    throw core::posix_error(\"fopen\", errno);\n}\n\nFileInStream::~FileInStream(void) {\n  if (file) {\n    fclose(file);\n    file = nullptr;\n  }\n}\n\nbool FileInStream::fillBuffer()\n{\n  size_t n = fread((uint8_t*)end, 1, availSpace(), file);\n  if (n == 0) {\n    if (ferror(file))\n      throw core::posix_error(\"fread\", errno);\n    if (feof(file))\n      throw end_of_stream();\n    return false;\n  }\n  end += n;\n\n  return true;\n}\n"
  },
  {
    "path": "common/rdr/FileInStream.h",
    "content": "/* Copyright (C) 2013 D. R. Commander.  All Rights Reserved.\n * Copyright 2015 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RDR_FILEINSTREAM_H__\n#define __RDR_FILEINSTREAM_H__\n\n#include <stdio.h>\n\n#include <rdr/BufferedInStream.h>\n\nnamespace rdr {\n\n  class FileInStream : public BufferedInStream {\n\n  public:\n\n    FileInStream(const char *fileName);\n    ~FileInStream(void);\n\n  private:\n    bool fillBuffer() override;\n\n  private:\n    FILE *file;\n  };\n\n} // end of namespace rdr\n\n#endif\n"
  },
  {
    "path": "common/rdr/HexInStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2019-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <algorithm>\n\n#include <core/string.h>\n\n#include <rdr/HexInStream.h>\n\nusing namespace rdr;\n\nHexInStream::HexInStream(InStream& is)\n: in_stream(is)\n{\n}\n\nHexInStream::~HexInStream() {\n}\n\nbool HexInStream::fillBuffer() {\n  if (!in_stream.hasData(2))\n    return false;\n\n  size_t length = std::min(in_stream.avail()/2, availSpace());\n  const uint8_t* iptr = in_stream.getptr(length*2);\n\n  uint8_t* optr = (uint8_t*) end;\n  for (size_t i=0; i<length; i++) {\n    if (!core::hexToBin((const char*)&iptr[i*2], 2, &optr[i], 1))\n      throw std::runtime_error(\"HexInStream: Invalid input data\");\n  }\n\n  in_stream.setptr(length*2);\n  end += length;\n\n  return true;\n}\n"
  },
  {
    "path": "common/rdr/HexInStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RDR_HEX_INSTREAM_H__\n#define __RDR_HEX_INSTREAM_H__\n\n#include <rdr/BufferedInStream.h>\n\nnamespace rdr {\n\n  class HexInStream : public BufferedInStream {\n  public:\n\n    HexInStream(InStream& is);\n    virtual ~HexInStream();\n\n  private:\n    bool fillBuffer() override;\n\n  private:\n    InStream& in_stream;\n  };\n\n} // end of namespace rdr\n\n#endif\n"
  },
  {
    "path": "common/rdr/HexOutStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2019-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <algorithm>\n\n#include <core/string.h>\n\n#include <rdr/HexOutStream.h>\n\nusing namespace rdr;\n\nHexOutStream::HexOutStream(OutStream& os)\n  : out_stream(os)\n{\n}\n\nHexOutStream::~HexOutStream()\n{\n}\n\nbool HexOutStream::flushBuffer()\n{\n  while (sentUpTo != ptr) {\n    uint8_t* optr = out_stream.getptr(2);\n    size_t length = std::min((size_t)(ptr-sentUpTo), out_stream.avail()/2);\n\n    for (size_t i=0; i<length; i++)\n      core::binToHex(&sentUpTo[i], 1, (char*)&optr[i*2], 2);\n\n    out_stream.setptr(length*2);\n    sentUpTo += length;\n  }\n\n  return true;\n}\n\nvoid\nHexOutStream::flush() {\n  BufferedOutStream::flush();\n  out_stream.flush();\n}\n\nvoid HexOutStream::cork(bool enable)\n{\n  BufferedOutStream::cork(enable);\n  out_stream.cork(enable);\n}\n"
  },
  {
    "path": "common/rdr/HexOutStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RDR_HEX_OUTSTREAM_H__\n#define __RDR_HEX_OUTSTREAM_H__\n\n#include <rdr/BufferedOutStream.h>\n\nnamespace rdr {\n\n  class HexOutStream : public BufferedOutStream {\n  public:\n\n    HexOutStream(OutStream& os);\n    virtual ~HexOutStream();\n\n    void flush() override;\n    void cork(bool enable) override;\n\n  private:\n    bool flushBuffer() override;\n    void writeBuffer();\n\n    OutStream& out_stream;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/InStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2020 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// rdr::InStream marshalls data from a buffer stored in RDR (RFB Data\n// Representation).\n//\n\n#ifndef __RDR_INSTREAM_H__\n#define __RDR_INSTREAM_H__\n\n#include <stdint.h>\n#include <string.h> // for memcpy\n\n#include <stdexcept>\n\n// Check that callers are using InStream properly,\n// useful when writing new protocol handling\n#ifdef _DEBUG\n#define RFB_INSTREAM_CHECK\n#endif\n\nnamespace rdr {\n\n  class end_of_stream : public std::runtime_error {\n  public:\n    end_of_stream() noexcept : std::runtime_error(\"End of stream\") {}\n  };\n\n  class InStream {\n\n  public:\n\n    virtual ~InStream() {}\n\n    // avail() returns the number of bytes that are currenctly directly\n    // available from the stream.\n\n    inline size_t avail() {\n#ifdef RFB_INSTREAM_CHECK\n      checkedBytes = end - ptr;\n#endif\n\n      return end - ptr;\n    }\n\n    // hasData() ensures there is at least \"length\" bytes of buffer data,\n    // possibly trying to fetch more data if there isn't enough right away\n\n    inline bool hasData(size_t length) {\n#ifdef RFB_INSTREAM_CHECK\n      checkedBytes = 0;\n#endif\n\n      if (length > (size_t)(end - ptr)) {\n        if (restorePoint != nullptr) {\n          bool ret;\n          size_t restoreDiff;\n\n          restoreDiff = ptr - restorePoint;\n          ptr = restorePoint;\n\n          ret = overrun(length + restoreDiff);\n\n          restorePoint = ptr;\n          ptr += restoreDiff;\n\n          if (!ret)\n            return false;\n        } else {\n          if (!overrun(length))\n            return false;\n        }\n      }\n\n#ifdef RFB_INSTREAM_CHECK\n      checkedBytes = length;\n#endif\n\n      return true;\n    }\n\n    inline bool hasDataOrRestore(size_t length) {\n      if (hasData(length))\n        return true;\n      gotoRestorePoint();\n      return false;\n    }\n\n    inline void setRestorePoint() {\n#ifdef RFB_INSTREAM_CHECK\n      if (restorePoint != nullptr)\n        throw std::logic_error(\"Nested use of input stream restore point\");\n#endif\n      restorePoint = ptr;\n    }\n    inline void clearRestorePoint() {\n#ifdef RFB_INSTREAM_CHECK\n      if (restorePoint == nullptr)\n        throw std::logic_error(\"Incorrect clearing of input stream restore point\");\n#endif\n      restorePoint = nullptr;\n    }\n    inline void gotoRestorePoint() {\n#ifdef RFB_INSTREAM_CHECK\n      if (restorePoint == nullptr)\n        throw std::logic_error(\"Incorrect activation of input stream restore point\");\n#endif\n      ptr = restorePoint;\n      clearRestorePoint();\n    }\n\n    // readU/SN() methods read unsigned and signed N-bit integers.\n\n    inline uint8_t  readU8()  { check(1); return *ptr++; }\n    inline uint16_t readU16() { check(2);\n                                int b0 = *ptr++; int b1 = *ptr++;\n                                return b0 << 8 | b1; }\n    inline uint32_t readU32() { check(4);\n                                int b0 = *ptr++; int b1 = *ptr++;\n                                int b2 = *ptr++; int b3 = *ptr++;\n                                return b0 << 24 | b1 << 16 | b2 << 8 | b3; }\n\n    inline int8_t  readS8()  { return (int8_t) readU8();  }\n    inline int16_t readS16() { return (int16_t)readU16(); }\n    inline int32_t readS32() { return (int32_t)readU32(); }\n\n    // skip() ignores a number of bytes on the stream\n\n    inline void skip(size_t bytes) {\n      check(bytes);\n      ptr += bytes;\n    }\n\n    // readBytes() reads an exact number of bytes.\n\n    void readBytes(uint8_t* data, size_t length) {\n      check(length);\n      memcpy(data, ptr, length);\n      ptr += length;\n    }\n\n    // readOpaqueN() reads a quantity without byte-swapping.\n\n    inline uint8_t  readOpaque8()  { return readU8(); }\n    inline uint16_t readOpaque16() { check(2); uint16_t r;\n                                     ((uint8_t*)&r)[0] = *ptr++;\n                                     ((uint8_t*)&r)[1] = *ptr++;\n                                     return r; }\n    inline uint32_t readOpaque32() { check(4); uint32_t r;\n                                     ((uint8_t*)&r)[0] = *ptr++;\n                                     ((uint8_t*)&r)[1] = *ptr++;\n                                     ((uint8_t*)&r)[2] = *ptr++;\n                                     ((uint8_t*)&r)[3] = *ptr++;\n                                     return r; }\n\n    // pos() returns the position in the stream.\n\n    virtual size_t pos() = 0;\n\n    // getptr() and setptr() are \"dirty\" methods which allow you direct access\n    // to the buffer. This is useful for a stream which is a wrapper around an\n    // some other stream API.\n\n    inline const uint8_t* getptr(size_t length) { check(length);\n                                                  return ptr; }\n    inline void setptr(size_t length) { if (length > avail())\n                                          throw std::out_of_range(\"Input stream overflow\");\n                                        skip(length); }\n\n  private:\n\n    const uint8_t* restorePoint;\n    size_t checkedBytes;\n\n    inline void check(size_t bytes) {\n#ifdef RFB_INSTREAM_CHECK\n      if (bytes > checkedBytes)\n        throw std::logic_error(\"Input stream used without underrun check\");\n      checkedBytes -= bytes;\n#endif\n      if (bytes > (size_t)(end - ptr))\n        throw std::out_of_range(\"InStream buffer underrun\");\n    }\n\n    // overrun() is implemented by a derived class to cope with buffer overrun.\n    // It tries to ensure there are at least needed bytes of buffer data.\n    // Returns true if it managed to satisfy the request, or false otherwise.\n\n    virtual bool overrun(size_t needed) = 0;\n\n  protected:\n\n    InStream() : restorePoint(nullptr), checkedBytes(0)\n    {\n      (void)checkedBytes;\n    }\n    const uint8_t* ptr;\n    const uint8_t* end;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/MemInStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// rdr::MemInStream is an InStream which streams from a given memory buffer.\n// If the deleteWhenDone parameter is true then the buffer will be delete[]d in\n// the destructor.  Note that it is delete[]d as a uint8_t* - strictly speaking this\n// means it ought to be new[]ed as a uint8_t* as well, but on most platforms this\n// doesn't matter.\n//\n\n#ifndef __RDR_MEMINSTREAM_H__\n#define __RDR_MEMINSTREAM_H__\n\n#include <rdr/InStream.h>\n\nnamespace rdr {\n\n  class MemInStream : public InStream {\n\n  public:\n\n    MemInStream(const uint8_t* data, size_t len, bool deleteWhenDone_=false)\n      : start(data), deleteWhenDone(deleteWhenDone_)\n    {\n      ptr = start;\n      end = start + len;\n\n#ifdef RFB_INSTREAM_CHECK\n      // MemInStream cannot add more data, so callers are assumed to already\n      // new the total size\n      avail();\n#endif\n    }\n\n    virtual ~MemInStream() {\n      if (deleteWhenDone)\n        delete [] start;\n    }\n\n    size_t pos() override { return ptr - start; }\n    void reposition(size_t pos) { ptr = start + pos; }\n\n  private:\n\n    bool overrun(size_t /*needed*/) override { throw end_of_stream(); }\n    const uint8_t* start;\n    bool deleteWhenDone;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/MemOutStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// A MemOutStream grows as needed when data is written to it.\n//\n\n#ifndef __RDR_MEMOUTSTREAM_H__\n#define __RDR_MEMOUTSTREAM_H__\n\n#include <rdr/OutStream.h>\n\nnamespace rdr {\n\n  class MemOutStream : public OutStream {\n\n  public:\n\n    MemOutStream(int len=1024) {\n      start = ptr = new uint8_t[len];\n      end = start + len;\n    }\n\n    virtual ~MemOutStream() {\n      delete [] start;\n    }\n\n    size_t length() override { return ptr - start; }\n    void clear() { ptr = start; };\n    void clearAndZero() { memset(start, 0, ptr-start); clear(); }\n    void reposition(size_t pos) { ptr = start + pos; }\n\n    // data() returns a pointer to the buffer.\n\n    const uint8_t* data() { return start; }\n\n  protected:\n\n    // overrun() either doubles the buffer or adds enough space for\n    // needed bytes.\n\n    void overrun(size_t needed) override {\n      size_t len = ptr - start + needed;\n      if (len < (size_t)(end - start) * 2)\n        len = (end - start) * 2;\n\n      if (len < (size_t)(end - start))\n        throw std::out_of_range(\"Overflow in MemOutStream::overrun()\");\n\n      uint8_t* newStart = new uint8_t[len];\n      memcpy(newStart, start, ptr - start);\n      ptr = newStart + (ptr - start);\n      delete [] start;\n      start = newStart;\n      end = newStart + len;\n    }\n\n    uint8_t* start;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/OutStream.h",
    "content": "/* Copyright (C) 2002-2003 RealVNC Ltd.  All Rights Reserved.\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// rdr::OutStream marshalls data into a buffer stored in RDR (RFB Data\n// Representation).\n//\n\n#ifndef __RDR_OUTSTREAM_H__\n#define __RDR_OUTSTREAM_H__\n\n#include <stdint.h>\n#include <string.h> // for memcpy\n\n#include <stdexcept>\n\n#include <rdr/InStream.h>\n\nnamespace rdr {\n\n  class OutStream {\n\n  protected:\n\n    OutStream() : ptr(nullptr), end(nullptr), corked(false) {}\n\n  public:\n\n    virtual ~OutStream() {}\n\n    // avail() returns the number of bytes that currently be written to the\n    // stream without any risk of blocking.\n\n    inline size_t avail()\n    {\n      return end - ptr;\n    }\n\n    // writeU/SN() methods write unsigned and signed N-bit integers.\n\n    inline void writeU8( uint8_t  u) { check(1); *ptr++ = u; }\n    inline void writeU16(uint16_t u) { check(2); *ptr++ = u >> 8;\n                                       *ptr++ = (uint8_t)u; }\n    inline void writeU32(uint32_t u) { check(4); *ptr++ = u >> 24;\n                                       *ptr++ = u >> 16;\n                                       *ptr++ = u >> 8;\n                                       *ptr++ = u; }\n\n    inline void writeS8( int8_t  s) { writeU8((uint8_t)s); }\n    inline void writeS16(int16_t s) { writeU16((uint16_t)s); }\n    inline void writeS32(int32_t s) { writeU32((uint32_t)s); }\n\n    inline void pad(size_t bytes) {\n      while (bytes-- > 0) writeU8(0);\n    }\n\n    // writeBytes() writes an exact number of bytes.\n\n    void writeBytes(const uint8_t* data, size_t length) {\n      while (length > 0) {\n        check(1);\n        size_t n = length;\n        if (length > avail())\n          n = avail();\n        memcpy(ptr, data, n);\n        ptr += n;\n        data = (uint8_t*)data + n;\n        length -= n;\n      }\n    }\n\n    // copyBytes() efficiently transfers data between streams\n\n    void copyBytes(InStream* is, size_t length) {\n      while (length > 0) {\n        check(1);\n        size_t n = length;\n        if (length > avail())\n          n = avail();\n        is->readBytes(ptr, n);\n        ptr += n;\n        length -= n;\n      }\n    }\n\n    // writeOpaqueN() writes a quantity without byte-swapping.\n\n    inline void writeOpaque8( uint8_t  u) { writeU8(u); }\n    inline void writeOpaque16(uint16_t u) { check(2);\n                                            *ptr++ = ((uint8_t*)&u)[0];\n                                            *ptr++ = ((uint8_t*)&u)[1]; }\n    inline void writeOpaque32(uint32_t u) { check(4);\n                                            *ptr++ = ((uint8_t*)&u)[0];\n                                            *ptr++ = ((uint8_t*)&u)[1];\n                                            *ptr++ = ((uint8_t*)&u)[2];\n                                            *ptr++ = ((uint8_t*)&u)[3]; }\n\n    // length() returns the length of the stream.\n\n    virtual size_t length() = 0;\n\n    // flush() requests that the stream be flushed.\n\n    virtual void flush() {}\n\n    // cork() requests that the stream coalesces flushes in an efficient way\n\n    virtual void cork(bool enable) { corked = enable; if (!enable) flush(); }\n\n    // getptr() and setptr() are \"dirty\" methods which allow you direct access\n    // to the buffer. This is useful for a stream which is a wrapper around an\n    // some other stream API. Note that setptr() should not called with a value\n    // larger than the bytes actually written as doing so can result in\n    // security issues. Use pad() in such cases instead.\n\n    inline uint8_t* getptr(size_t length) { check(length); return ptr; }\n    inline void setptr(size_t length) { if (length > avail())\n                                          throw std::out_of_range(\"Output stream overflow\");\n                                        ptr += length; }\n\n  private:\n\n    inline void check(size_t length)\n    {\n      if (length > avail())\n        overrun(length);\n    }\n\n    // overrun() is implemented by a derived class to cope with buffer overrun.\n    // It ensures there are at least needed bytes of buffer space.\n\n    virtual void overrun(size_t needed) = 0;\n\n  protected:\n\n    uint8_t* ptr;\n    uint8_t* end;\n\n    bool corked;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/RandomStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rdr/RandomStream.h>\n\n#include <time.h>\n#include <stdlib.h>\n#ifndef WIN32\n#include <unistd.h>\n#include <errno.h>\n#else\n#define getpid() GetCurrentProcessId()\n#ifndef RFB_HAVE_WINCRYPT\n#pragma message(\"  NOTE: Not building WinCrypt-based RandomStream\")\n#endif\n#endif\n\nstatic core::LogWriter vlog(\"RandomStream\");\n\nusing namespace rdr;\n\nunsigned int RandomStream::seed;\n\nRandomStream::RandomStream()\n{\n#ifdef RFB_HAVE_WINCRYPT\n  provider = 0;\n  if (!CryptAcquireContext(&provider, nullptr, nullptr,\n                           PROV_RSA_FULL, 0)) {\n    if (GetLastError() == (DWORD)NTE_BAD_KEYSET) {\n      if (!CryptAcquireContext(&provider, nullptr, nullptr,\n                               PROV_RSA_FULL, CRYPT_NEWKEYSET)) {\n        vlog.error(\"Unable to create keyset\");\n        provider = 0;\n      }\n    } else {\n      vlog.error(\"Unable to acquire context\");\n      provider = 0;\n    }\n  }\n  if (!provider) {\n#else\n#ifndef WIN32\n  fp = fopen(\"/dev/urandom\", \"r\");\n  if (!fp)\n    fp = fopen(\"/dev/random\", \"r\");\n  if (!fp) {\n#else\n  {\n#endif\n#endif\n    vlog.error(\"No OS supplied random source, using rand()\");\n    seed += (unsigned int) time(nullptr) + getpid() + getpid() * 987654 + rand();\n    srand(seed);\n  }\n}\n\nRandomStream::~RandomStream() {\n#ifdef RFB_HAVE_WINCRYPT\n  if (provider)\n    CryptReleaseContext(provider, 0);\n#endif\n#ifndef WIN32\n  if (fp) fclose(fp);\n#endif\n}\n\nbool RandomStream::fillBuffer() {\n#ifdef RFB_HAVE_WINCRYPT\n  if (provider) {\n    if (!CryptGenRandom(provider, availSpace(), (uint8_t*)end))\n      throw core::win32_error(\"Unable to CryptGenRandom\", GetLastError());\n    end += availSpace();\n  } else {\n#else\n#ifndef WIN32\n  if (fp) {\n    size_t n = fread((uint8_t*)end, 1, availSpace(), fp);\n    if (n <= 0)\n      throw core::posix_error(\n        \"Reading /dev/urandom or /dev/random failed\", errno);\n    end += n;\n  } else {\n#else\n  {\n#endif\n#endif\n    for (size_t i=availSpace(); i>0; i--)\n      *(uint8_t*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0));\n  }\n\n  return true;\n}\n"
  },
  {
    "path": "common/rdr/RandomStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RDR_RANDOMSTREAM_H__\n#define __RDR_RANDOMSTREAM_H__\n\n#include <stdio.h>\n#include <rdr/BufferedInStream.h>\n\n#ifdef WIN32\n#include <windows.h>\n#include <wincrypt.h>\n#ifdef WINCRYPT32API\n#define RFB_HAVE_WINCRYPT\n#endif\n#endif\n\nnamespace rdr {\n\n  class RandomStream : public BufferedInStream {\n\n  public:\n\n    RandomStream();\n    virtual ~RandomStream();\n\n  private:\n    bool fillBuffer() override;\n\n  private:\n    static unsigned int seed;\n#ifdef RFB_HAVE_WINCRYPT\n    HCRYPTPROV provider;\n#endif\n#ifndef WIN32\n    FILE* fp;\n#endif\n\n  };\n\n} // end of namespace rdr\n\n#endif\n"
  },
  {
    "path": "common/rdr/TLSException.cxx",
    "content": "/*\n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/string.h>\n\n#include <rdr/TLSException.h>\n\n#include <string.h>\n#include <stdio.h>\n#ifdef HAVE_GNUTLS\n#include <gnutls/gnutls.h>\n#endif\n\nusing namespace rdr;\n\n#ifdef HAVE_GNUTLS\ntls_error::tls_error(const char* s, int err_, int alert_) noexcept\n  : std::runtime_error(core::format(\"%s: %s (%d)\", s,\n                                    strerror(err_, alert_), err_)),\n    err(err_), alert(alert_)\n{\n}\n\nconst char* tls_error::strerror(int err_, int alert_) const noexcept\n{\n  const char* msg;\n\n  msg = nullptr;\n\n  if ((alert_ != -1) &&\n      ((err_ == GNUTLS_E_WARNING_ALERT_RECEIVED) ||\n       (err_ == GNUTLS_E_FATAL_ALERT_RECEIVED)))\n    msg = gnutls_alert_get_name((gnutls_alert_description_t)alert_);\n\n  if (msg == nullptr)\n    msg = gnutls_strerror(err_);\n\n  return msg;\n}\n#endif /* HAVE_GNUTLS */\n\n"
  },
  {
    "path": "common/rdr/TLSException.h",
    "content": "/* \n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RDR_TLSEXCEPTION_H__\n#define __RDR_TLSEXCEPTION_H__\n\n#include <stdexcept>\n\nnamespace rdr {\n\n  class tls_error : public std::runtime_error {\n  public:\n    int err, alert;\n    tls_error(const char* s, int err_, int alert_=-1) noexcept;\n  private:\n    const char* strerror(int err_, int alert_) const noexcept;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/TLSInStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright 2012-2025 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rdr/TLSInStream.h>\n#include <rdr/TLSSocket.h>\n\n#ifdef HAVE_GNUTLS\n\nusing namespace rdr;\n\nTLSInStream::TLSInStream(TLSSocket* sock_)\n  : sock(sock_)\n{\n}\n\nTLSInStream::~TLSInStream()\n{\n}\n\nbool TLSInStream::fillBuffer()\n{\n  size_t n = sock->readTLS((uint8_t*) end, availSpace());\n  if (n == 0)\n    return false;\n  end += n;\n\n  return true;\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/TLSInStream.h",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright 2012-2025 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RDR_TLSINSTREAM_H__\n#define __RDR_TLSINSTREAM_H__\n\n#ifdef HAVE_GNUTLS\n\n#include <rdr/BufferedInStream.h>\n\nnamespace rdr {\n\n  class TLSSocket;\n\n  class TLSInStream : public BufferedInStream {\n  public:\n    TLSInStream(TLSSocket* sock);\n    virtual ~TLSInStream();\n\n  private:\n    bool fillBuffer() override;\n\n    TLSSocket* sock;\n  };\n\n}\n\n#endif\n\n#endif\n"
  },
  {
    "path": "common/rdr/TLSOutStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright 2012-2025 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rdr/TLSOutStream.h>\n#include <rdr/TLSSocket.h>\n\n#ifdef HAVE_GNUTLS\n\nusing namespace rdr;\n\nTLSOutStream::TLSOutStream(TLSSocket* sock_)\n  : sock(sock_)\n{\n}\n\nTLSOutStream::~TLSOutStream()\n{\n}\n\nvoid TLSOutStream::flush()\n{\n  BufferedOutStream::flush();\n  sock->out->flush();\n}\n\nvoid TLSOutStream::cork(bool enable)\n{\n  BufferedOutStream::cork(enable);\n  sock->out->cork(enable);\n}\n\nbool TLSOutStream::flushBuffer()\n{\n  while (sentUpTo < ptr) {\n    size_t n = sock->writeTLS(sentUpTo, ptr - sentUpTo);\n    sentUpTo += n;\n  }\n\n  return true;\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/TLSOutStream.h",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RDR_TLSOUTSTREAM_H__\n#define __RDR_TLSOUTSTREAM_H__\n\n#ifdef HAVE_GNUTLS\n\n#include <rdr/BufferedOutStream.h>\n\nnamespace rdr {\n\n  class TLSSocket;\n\n  class TLSOutStream : public BufferedOutStream {\n  public:\n    TLSOutStream(TLSSocket* out);\n    virtual ~TLSOutStream();\n\n    void flush() override;\n    void cork(bool enable) override;\n\n  private:\n    bool flushBuffer() override;\n\n    TLSSocket* sock;\n  };\n\n}\n\n#endif\n\n#endif\n"
  },
  {
    "path": "common/rdr/TLSSocket.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2012-2025 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rdr/InStream.h>\n#include <rdr/OutStream.h>\n#include <rdr/TLSException.h>\n#include <rdr/TLSSocket.h>\n\n#include <errno.h>\n\n#ifdef HAVE_GNUTLS\n\nusing namespace rdr;\n\nstatic core::LogWriter vlog(\"TLSSocket\");\n\nTLSSocket::TLSSocket(InStream* in_, OutStream* out_,\n                     gnutls_session_t session_)\n  : session(session_), in(in_), out(out_), tlsin(this), tlsout(this)\n{\n  gnutls_transport_set_pull_function(\n    session, [](gnutls_transport_ptr_t sock, void* data, size_t size) {\n      return ((TLSSocket*)sock)->pull(data, size);\n    });\n  gnutls_transport_set_push_function(\n    session, [](gnutls_transport_ptr_t sock, const void* data, size_t size) {\n      return ((TLSSocket*)sock)->push(data, size);\n    });\n  gnutls_transport_set_ptr(session, this);\n}\n\nTLSSocket::~TLSSocket()\n{\n  gnutls_transport_set_pull_function(session, nullptr);\n  gnutls_transport_set_push_function(session, nullptr);\n  gnutls_transport_set_ptr(session, nullptr);\n}\n\nbool TLSSocket::handshake()\n{\n  int err;\n\n  err = gnutls_handshake(session);\n  if (err != GNUTLS_E_SUCCESS) {\n    gnutls_alert_description_t alert;\n    const char* msg;\n\n    if ((err == GNUTLS_E_PULL_ERROR) || (err == GNUTLS_E_PUSH_ERROR))\n      std::rethrow_exception(saved_exception);\n\n    alert = gnutls_alert_get(session);\n    msg = nullptr;\n\n    if ((err == GNUTLS_E_WARNING_ALERT_RECEIVED) ||\n        (err == GNUTLS_E_FATAL_ALERT_RECEIVED))\n      msg = gnutls_alert_get_name(alert);\n\n    if (msg == nullptr)\n      msg = gnutls_strerror(err);\n\n    if (!gnutls_error_is_fatal(err)) {\n      vlog.debug(\"Deferring completion of TLS handshake: %s\", msg);\n      return false;\n    }\n\n    vlog.error(\"TLS Handshake failed: %s\\n\", msg);\n    gnutls_alert_send_appropriate(session, err);\n    throw rdr::tls_error(\"TLS Handshake failed\", err, alert);\n  }\n\n  return true;\n}\n\nvoid TLSSocket::shutdown()\n{\n  int ret;\n\n  try {\n    if (tlsout.hasBufferedData()) {\n      tlsout.cork(false);\n      tlsout.flush();\n      if (tlsout.hasBufferedData())\n        vlog.error(\"Failed to flush remaining socket data on close\");\n    }\n  } catch (std::exception& e) {\n    vlog.error(\"Failed to flush remaining socket data on close: %s\", e.what());\n  }\n\n  // FIXME: We can't currently wait for the response, so we only send\n  //        our close and hope for the best\n  ret = gnutls_bye(session, GNUTLS_SHUT_WR);\n  if ((ret != GNUTLS_E_SUCCESS) && (ret != GNUTLS_E_INVALID_SESSION)) {\n    if ((ret == GNUTLS_E_PULL_ERROR) || (ret == GNUTLS_E_PUSH_ERROR)) {\n      try {\n        std::rethrow_exception(saved_exception);\n      } catch (std::exception& e) {\n        vlog.error(\"TLS shutdown failed: %s\", e.what());\n      }\n    } else {\n      vlog.error(\"TLS shutdown failed: %s\", gnutls_strerror(ret));\n    }\n  }\n}\n\nsize_t TLSSocket::readTLS(uint8_t* buf, size_t len)\n{\n  int n;\n\n  while (true) {\n    streamEmpty = false;\n    n = gnutls_record_recv(session, (void *) buf, len);\n    if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN) {\n      // GnuTLS returns GNUTLS_E_AGAIN for a bunch of other scenarios\n      // other than the pull function returning EAGAIN, so we have to\n      // double check that the underlying stream really is empty\n      if (!streamEmpty)\n        continue;\n      else\n        return 0;\n    }\n    break;\n  };\n\n  if (n == GNUTLS_E_PULL_ERROR)\n    std::rethrow_exception(saved_exception);\n\n  if (n < 0) {\n    gnutls_alert_send_appropriate(session, n);\n    throw tls_error(\"readTLS\", n, gnutls_alert_get(session));\n  }\n\n  if (n == 0)\n    throw end_of_stream();\n\n  return n;\n}\n\nsize_t TLSSocket::writeTLS(const uint8_t* data, size_t length)\n{\n  int n;\n\n  n = gnutls_record_send(session, data, length);\n  if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN)\n    return 0;\n\n  if (n == GNUTLS_E_PUSH_ERROR)\n    std::rethrow_exception(saved_exception);\n\n  if (n < 0) {\n    gnutls_alert_send_appropriate(session, n);\n    throw tls_error(\"writeTLS\", n, gnutls_alert_get(session));\n  }\n\n  return n;\n}\n\nssize_t TLSSocket::pull(void* data, size_t size)\n{\n  streamEmpty = false;\n  saved_exception = nullptr;\n\n  try {\n    if (!in->hasData(1)) {\n      streamEmpty = true;\n      gnutls_transport_set_errno(session, EAGAIN);\n      return -1;\n    }\n\n    if (in->avail() < size)\n      size = in->avail();\n\n    in->readBytes((uint8_t*)data, size);\n  } catch (end_of_stream&) {\n    return 0;\n  } catch (std::exception& e) {\n    core::socket_error* se;\n    se = dynamic_cast<core::socket_error*>(&e);\n    if (se)\n      gnutls_transport_set_errno(session, se->err);\n    else\n      gnutls_transport_set_errno(session, EINVAL);\n    saved_exception = std::current_exception();\n    return -1;\n  }\n\n  return size;\n}\n\nssize_t TLSSocket::push(const void* data, size_t size)\n{\n  saved_exception = nullptr;\n\n  try {\n    out->writeBytes((const uint8_t*)data, size);\n    out->flush();\n  } catch (std::exception& e) {\n    core::socket_error* se;\n    se = dynamic_cast<core::socket_error*>(&e);\n    if (se)\n      gnutls_transport_set_errno(session, se->err);\n    else\n      gnutls_transport_set_errno(session, EINVAL);\n    saved_exception = std::current_exception();\n    return -1;\n  }\n\n  return size;\n}\n\n#endif\n"
  },
  {
    "path": "common/rdr/TLSSocket.h",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright 2012-2025 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,\n * USA.\n */\n\n#ifndef __RDR_TLSSOCKET_H__\n#define __RDR_TLSSOCKET_H__\n\n#ifdef HAVE_GNUTLS\n\n#include <exception>\n\n#include <gnutls/gnutls.h>\n\n#include <rdr/TLSInStream.h>\n#include <rdr/TLSOutStream.h>\n\nnamespace rdr {\n\n  class InStream;\n  class OutStream;\n\n  class TLSInStream;\n  class TLSOutStream;\n\n  class TLSSocket {\n  public:\n    TLSSocket(InStream* in, OutStream* out, gnutls_session_t session);\n    virtual ~TLSSocket();\n\n    TLSInStream& inStream() { return tlsin; }\n    TLSOutStream& outStream() { return tlsout; }\n\n    bool handshake();\n    void shutdown();\n\n  protected:\n    /* Used by the stream classes */\n    size_t readTLS(uint8_t* buf, size_t len);\n    size_t writeTLS(const uint8_t* data, size_t length);\n\n    friend TLSInStream;\n    friend TLSOutStream;\n\n  private:\n    ssize_t pull(void* data, size_t size);\n    ssize_t push(const void* data, size_t size);\n\n    gnutls_session_t session;\n\n    InStream* in;\n    OutStream* out;\n\n    TLSInStream tlsin;\n    TLSOutStream tlsout;\n\n    bool streamEmpty;\n\n    std::exception_ptr saved_exception;\n  };\n\n}\n\n#endif\n\n#endif\n"
  },
  {
    "path": "common/rdr/ZlibInStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <rdr/ZlibInStream.h>\n#include <zlib.h>\n\nusing namespace rdr;\n\nZlibInStream::ZlibInStream()\n  : underlying(nullptr), zs(nullptr), bytesIn(0)\n{\n  init();\n}\n\nZlibInStream::~ZlibInStream()\n{\n  deinit();\n}\n\nvoid ZlibInStream::setUnderlying(InStream* is, size_t bytesIn_)\n{\n  underlying = is;\n  bytesIn = bytesIn_;\n  skip(avail());\n}\n\nvoid ZlibInStream::flushUnderlying()\n{\n  while (bytesIn > 0) {\n    if (!hasData(1))\n      throw std::runtime_error(\"ZlibInStream: Failed to flush remaining stream data\");\n    skip(avail());\n  }\n\n  setUnderlying(nullptr, 0);\n}\n\nvoid ZlibInStream::reset()\n{\n  deinit();\n  init();\n}\n\nvoid ZlibInStream::init()\n{\n  assert(zs == nullptr);\n\n  zs = new z_stream;\n  zs->zalloc    = nullptr;\n  zs->zfree     = nullptr;\n  zs->opaque    = nullptr;\n  zs->next_in   = nullptr;\n  zs->avail_in  = 0;\n  if (inflateInit(zs) != Z_OK) {\n    delete zs;\n    zs = nullptr;\n    throw std::runtime_error(\"ZlibInStream: inflateInit failed\");\n  }\n}\n\nvoid ZlibInStream::deinit()\n{\n  assert(zs != nullptr);\n  setUnderlying(nullptr, 0);\n  inflateEnd(zs);\n  delete zs;\n  zs = nullptr;\n}\n\nbool ZlibInStream::fillBuffer()\n{\n  if (!underlying)\n    throw std::runtime_error(\"ZlibInStream overrun: No underlying stream\");\n\n  zs->next_out = (uint8_t*)end;\n  zs->avail_out = availSpace();\n\n  if (!underlying->hasData(1))\n    return false;\n  size_t length = underlying->avail();\n  if (length > bytesIn)\n    length = bytesIn;\n  zs->next_in = (uint8_t*)underlying->getptr(length);\n  zs->avail_in = length;\n\n  int rc = inflate(zs, Z_SYNC_FLUSH);\n  if (rc < 0) {\n    throw std::runtime_error(\"ZlibInStream: inflate failed\");\n  }\n\n  bytesIn -= length - zs->avail_in;\n  end = zs->next_out;\n  underlying->setptr(length - zs->avail_in);\n  return true;\n}\n"
  },
  {
    "path": "common/rdr/ZlibInStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// ZlibInStream streams from a compressed data stream (\"underlying\"),\n// decompressing with zlib on the fly.\n//\n\n#ifndef __RDR_ZLIBINSTREAM_H__\n#define __RDR_ZLIBINSTREAM_H__\n\n#include <rdr/BufferedInStream.h>\n\nstruct z_stream_s;\n\nnamespace rdr {\n\n  class ZlibInStream : public BufferedInStream {\n\n  public:\n    ZlibInStream();\n    virtual ~ZlibInStream();\n\n    void setUnderlying(InStream* is, size_t bytesIn);\n    void flushUnderlying();\n    void reset();\n\n  private:\n    void init();\n    void deinit();\n\n    bool fillBuffer() override;\n\n  private:\n    InStream* underlying;\n    z_stream_s* zs;\n    size_t bytesIn;\n  };\n\n} // end of namespace rdr\n\n#endif\n"
  },
  {
    "path": "common/rdr/ZlibOutStream.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n\n#include <core/LogWriter.h>\n\n#include <rdr/ZlibOutStream.h>\n\n#include <zlib.h>\n\n#undef ZLIBOUT_DEBUG\n\nstatic core::LogWriter vlog(\"ZlibOutStream\");\n\nusing namespace rdr;\n\nZlibOutStream::ZlibOutStream(OutStream* os, int compressLevel)\n  : underlying(os), compressionLevel(compressLevel), newLevel(compressLevel)\n{\n  zs = new z_stream;\n  zs->zalloc    = nullptr;\n  zs->zfree     = nullptr;\n  zs->opaque    = nullptr;\n  zs->next_in   = nullptr;\n  zs->avail_in  = 0;\n  if (deflateInit(zs, compressLevel) != Z_OK) {\n    delete zs;\n    throw std::runtime_error(\"ZlibOutStream: deflateInit failed\");\n  }\n}\n\nZlibOutStream::~ZlibOutStream()\n{\n  try {\n    flush();\n  } catch (std::exception&) {\n  }\n  deflateEnd(zs);\n  delete zs;\n}\n\nvoid ZlibOutStream::setUnderlying(OutStream* os)\n{\n  underlying = os;\n  if (underlying)\n    underlying->cork(corked);\n}\n\nvoid ZlibOutStream::setCompressionLevel(int level)\n{\n  if (level < -1 || level > 9)\n    level = -1;                 // Z_DEFAULT_COMPRESSION\n\n  newLevel = level;\n}\n\nvoid ZlibOutStream::flush()\n{\n  BufferedOutStream::flush();\n  if (underlying != nullptr)\n    underlying->flush();\n}\n\nvoid ZlibOutStream::cork(bool enable)\n{\n  BufferedOutStream::cork(enable);\n  if (underlying != nullptr)\n    underlying->cork(enable);\n}\n\nbool ZlibOutStream::flushBuffer()\n{\n  checkCompressionLevel();\n\n  zs->next_in = sentUpTo;\n  zs->avail_in = ptr - sentUpTo;\n\n#ifdef ZLIBOUT_DEBUG\n  vlog.debug(\"Flush: avail_in %d\",zs->avail_in);\n#endif\n\n  // Force out everything from the zlib encoder\n  deflate(corked ? Z_NO_FLUSH : Z_SYNC_FLUSH);\n\n  sentUpTo = zs->next_in;\n\n  return true;\n}\n\nvoid ZlibOutStream::deflate(int flush)\n{\n  int rc;\n\n  if (!underlying)\n    throw std::runtime_error(\"ZlibOutStream: Underlying OutStream has not been set\");\n\n  if ((flush == Z_NO_FLUSH) && (zs->avail_in == 0))\n    return;\n\n  do {\n    size_t chunk;\n    zs->next_out = underlying->getptr(1);\n    zs->avail_out = chunk = underlying->avail();\n\n#ifdef ZLIBOUT_DEBUG\n    vlog.debug(\"Calling deflate, avail_in %d, avail_out %d\",\n               zs->avail_in,zs->avail_out);\n#endif\n\n    rc = ::deflate(zs, flush);\n    if (rc < 0) {\n      // Silly zlib returns an error if you try to flush something twice\n      if ((rc == Z_BUF_ERROR) && (flush != Z_NO_FLUSH))\n        break;\n\n      throw std::runtime_error(\"ZlibOutStream: deflate failed\");\n    }\n\n#ifdef ZLIBOUT_DEBUG\n    vlog.debug(\"After deflate: %d bytes\",\n               zs->next_out-underlying->getptr());\n#endif\n\n    underlying->setptr(chunk - zs->avail_out);\n  } while (zs->avail_out == 0);\n}\n\nvoid ZlibOutStream::checkCompressionLevel()\n{\n  int rc;\n\n  if (newLevel != compressionLevel) {\n#ifdef ZLIBOUT_DEBUG\n    vlog.debug(\"Change: avail_in %d\",zs->avail_in);\n#endif\n\n    // zlib is just horribly stupid. It does an implicit flush on\n    // parameter changes, but the flush it does is not one that forces\n    // out all the data. And since you cannot flush things again, we\n    // cannot force out our data after the parameter change. Hence we\n    // need to do a more proper flush here first.\n    deflate(Z_SYNC_FLUSH);\n\n    rc = deflateParams (zs, newLevel, Z_DEFAULT_STRATEGY);\n    if (rc < 0) {\n      // The implicit flush can result in this error, caused by the\n      // explicit flush we did above. It should be safe to ignore though\n      // as the first flush should have left things in a stable state...\n      if (rc != Z_BUF_ERROR)\n        throw std::runtime_error(\"ZlibOutStream: deflateParams failed\");\n    }\n\n    compressionLevel = newLevel;\n  }\n}\n"
  },
  {
    "path": "common/rdr/ZlibOutStream.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// ZlibOutStream streams to a compressed data stream (underlying), compressing\n// with zlib on the fly.\n//\n\n#ifndef __RDR_ZLIBOUTSTREAM_H__\n#define __RDR_ZLIBOUTSTREAM_H__\n\n#include <rdr/BufferedOutStream.h>\n\nstruct z_stream_s;\n\nnamespace rdr {\n\n  class ZlibOutStream : public BufferedOutStream {\n\n  public:\n\n    ZlibOutStream(OutStream* os=nullptr, int compressionLevel=-1);\n    virtual ~ZlibOutStream();\n\n    void setUnderlying(OutStream* os);\n    void setCompressionLevel(int level=-1);\n    void flush() override;\n    void cork(bool enable) override;\n\n  private:\n    bool flushBuffer() override;\n    void deflate(int flush);\n    void checkCompressionLevel();\n\n    OutStream* underlying;\n    int compressionLevel;\n    int newLevel;\n    z_stream_s* zs;\n  };\n\n} // end of namespace rdr\n\n#endif\n"
  },
  {
    "path": "common/rfb/AccessRights.cxx",
    "content": "/* Copyright 2024 TigerVNC Team\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include \"AccessRights.h\"\n\nnamespace rfb\n{\n\n  // AccessRights values\n  const AccessRights AccessNone           = 0x0000;\n  const AccessRights AccessView           = 0x0001;\n  const AccessRights AccessKeyEvents      = 0x0002;\n  const AccessRights AccessPtrEvents      = 0x0004;\n  const AccessRights AccessCutText        = 0x0008;\n  const AccessRights AccessSetDesktopSize = 0x0010;\n  const AccessRights AccessNonShared      = 0x0020;\n  const AccessRights AccessDefault        = 0x03ff;\n  const AccessRights AccessNoQuery        = 0x0400;\n  const AccessRights AccessFull           = 0xffff;\n\n} /* namespace rfb */\n"
  },
  {
    "path": "common/rfb/AccessRights.h",
    "content": "/* Copyright 2024 TigerVNC Team\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef COMMON_RFB_ACCESSRIGHTS_H_\n#define COMMON_RFB_ACCESSRIGHTS_H_\n\n#include <stdint.h>\n\nnamespace rfb\n{\n\n  typedef uint16_t AccessRights;\n  extern const AccessRights AccessNone;           // No rights at all\n  extern const AccessRights AccessView;           // View display contents\n  extern const AccessRights AccessKeyEvents;      // Send key events\n  extern const AccessRights AccessPtrEvents;      // Send pointer events\n  extern const AccessRights AccessCutText;        // Send/receive clipboard events\n  extern const AccessRights AccessSetDesktopSize; // Change desktop size\n  extern const AccessRights AccessNonShared;      // Exclusive access to the server\n  extern const AccessRights AccessDefault;        // The default rights, INCLUDING FUTURE ONES\n  extern const AccessRights AccessNoQuery;        // Connect without local user accepting\n  extern const AccessRights AccessFull;           // All of the available AND FUTURE rights\n\n} /* namespace rfb */\n\n#endif /* COMMON_RFB_ACCESSRIGHTS_H_ */\n"
  },
  {
    "path": "common/rfb/Blacklist.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rfb/Blacklist.h>\n#include <core/Configuration.h>\n\nusing namespace rfb;\n\ncore::BoolParameter enabled(\"UseBlacklist\",\n                            \"Temporarily reject connections from a \"\n                            \"host if it repeatedly fails to \"\n                            \"authenticate.\",\n                            true);\ncore::IntParameter threshold(\"BlacklistThreshold\",\n                             \"The number of unauthenticated connection \"\n                             \"attempts allowed from any individual \"\n                             \"host before that host is black-listed\",\n                             5, 0, INT_MAX);\ncore::IntParameter initialTimeout(\"BlacklistTimeout\",\n                                  \"The initial timeout applied when a \"\n                                  \"host is first black-listed. The \"\n                                  \"host cannot re-attempt a connection \"\n                                  \"until the timeout expires.\",\n                                  10, 0, INT_MAX);\n\n\nBlacklist::Blacklist() {\n}\n\nBlacklist::~Blacklist() {\n}\n\nbool Blacklist::isBlackmarked(const char* name) {\n  if (!enabled)\n    return false;\n\n  BlacklistMap::iterator i = blm.find(name);\n  if (i == blm.end()) {\n    // Entry is not already black-marked.\n    // Create the entry unmarked, unblocked,\n    // with suitable defaults set.\n    BlacklistInfo bi;\n    bi.marks = 1;\n    bi.blockUntil = 0;\n    bi.blockTimeout = initialTimeout;\n    blm[name] = bi;\n    i = blm.find(name);\n  }\n\n  // Entry exists - has it reached the threshold yet?\n  if ((*i).second.marks >= threshold) {\n    // Yes - entry is blocked - has the timeout expired?        \n    time_t now = time(nullptr);\n    if (now >= (*i).second.blockUntil) {\n      // Timeout has expired.  Reset timeout and allow\n      // a re-try.\n      (*i).second.blockUntil = now + (*i).second.blockTimeout;\n      (*i).second.blockTimeout = (*i).second.blockTimeout * 2;\n      return false;\n    }\n    // Blocked and timeout still in effect - reject!\n    return true;\n  }\n\n  // We haven't reached the threshold yet.\n  // Increment the black-mark counter but allow\n  // the entry to pass.\n  (*i).second.marks++;\n  return false;\n}\n\nvoid Blacklist::clearBlackmark(const char* name) {\n  blm.erase(name);\n}\n"
  },
  {
    "path": "common/rfb/Blacklist.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// Blacklist.h - Handling of black-listed entities.\n// Just keeps a table mapping strings to timing information, including\n// how many times the entry has been black-listed and when to next\n// put it on probation (e.g. allow a connection in from the host, and\n// re-blacklist it if that fails). \n//\n\n#ifndef __RFB_BLACKLIST_H__\n#define __RFB_BLACKLIST_H__\n\n#include <time.h>\n\n#include <map>\n#include <string>\n\nnamespace rfb {\n\n  //\n  // -=- Blacklist handler\n  //\n  // Parameters include a threshold after which to blacklist the named\n  // host, and a timeout after which to re-consider them.\n  //\n  // Threshold means that isBlackmarked can be called that number of times\n  // before it will return true.\n  //\n  // Timeout means that after that many seconds, the next call to isBlackmarked\n  // will return false.  At the same time, the timeout is doubled, so that the\n  // next calls will fail, until the timeout expires again or clearBlackmark is\n  // called.\n  //\n  // When clearBlackMark is called, the corresponding entry is completely\n  // removed, causing the next isBlackmarked call to return false.\n\n  // KNOWN BUG:  Client can keep making rejected requests, thus increasing\n  // their timeout.  If client does this for 30 years, timeout may wrap round\n  // to a very small value again.\n\n  // THIS CLASS IS NOT THREAD-SAFE!\n\n  class Blacklist {\n  public:\n    Blacklist();\n    ~Blacklist();\n\n    bool isBlackmarked(const char* name);\n    void clearBlackmark(const char* name);\n\n  protected:\n    struct BlacklistInfo {\n      int marks;\n      time_t blockUntil;\n      unsigned int blockTimeout;\n    };\n    typedef std::map<std::string,BlacklistInfo> BlacklistMap;\n    BlacklistMap blm;\n  };\n\n}\n\n#endif\n\n"
  },
  {
    "path": "common/rfb/CConnection.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <stdio.h>\n#include <string.h>\n\n#include <algorithm>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb/Exception.h>\n#include <rfb/clipboardTypes.h>\n#include <rfb/fenceTypes.h>\n#include <rfb/screenTypes.h>\n#include <rfb/CMsgReader.h>\n#include <rfb/CMsgWriter.h>\n#include <rfb/CSecurity.h>\n#include <rfb/Cursor.h>\n#include <rfb/Decoder.h>\n#include <rfb/KeysymStr.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/Security.h>\n#include <rfb/SecurityClient.h>\n#include <rfb/CConnection.h>\n\n#define XK_MISCELLANY\n#define XK_XKB_KEYS\n#include <rfb/keysymdef.h>\n\n#include <rdr/InStream.h>\n#include <rdr/OutStream.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"CConnection\");\n\ncore::BoolParameter\n  CConnection::noJpeg(\"NoJPEG\", \"Disable lossy JPEG compression.\",\n                      false);\n\nCConnection::CConnection()\n  : csecurity(nullptr),\n    supportsLocalCursor(false), supportsCursorPosition(false),\n    supportsDesktopResize(false), supportsLEDState(false),\n    is(nullptr), os(nullptr), reader_(nullptr), writer_(nullptr),\n    shared(false),\n    state_(RFBSTATE_UNINITIALISED),\n    pendingPFChange(false), preferredEncoding(encodingTight),\n    compressLevel(2), qualityLevel(-1),\n    formatChange(false), encodingChange(false),\n    firstUpdate(true), pendingUpdate(false), continuousUpdates(false),\n    forceNonincremental(true),\n    framebuffer(nullptr), decoder(this),\n    hasRemoteClipboard(false), hasLocalClipboard(false)\n{\n}\n\nCConnection::~CConnection()\n{\n  close();\n}\n\nvoid CConnection::setServerName(const char* name_)\n{\n  if (name_ == nullptr)\n    name_ = \"\";\n  serverName = name_;\n}\n\nvoid CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)\n{\n  is = is_;\n  os = os_;\n}\n\nvoid CConnection::setFramebuffer(ModifiablePixelBuffer* fb)\n{\n  decoder.flush();\n\n  if (fb) {\n    assert(fb->width() == server.width());\n    assert(fb->height() == server.height());\n  }\n\n  if ((framebuffer != nullptr) && (fb != nullptr)) {\n    core::Rect rect;\n\n    const uint8_t* data;\n    int stride;\n\n    const uint8_t black[4] = { 0, 0, 0, 0 };\n\n    // Copy still valid area\n\n    rect = fb->getRect();\n    rect = rect.intersect(framebuffer->getRect());\n    data = framebuffer->getBuffer(framebuffer->getRect(), &stride);\n    fb->imageRect(rect, data, stride);\n\n    // Black out any new areas\n\n    if (fb->width() > framebuffer->width()) {\n      rect.setXYWH(framebuffer->width(), 0,\n                   fb->width() - framebuffer->width(),\n                   fb->height());\n      fb->fillRect(rect, black);\n    }\n\n    if (fb->height() > framebuffer->height()) {\n      rect.setXYWH(0, framebuffer->height(),\n                   fb->width(),\n                   fb->height() - framebuffer->height());\n      fb->fillRect(rect, black);\n    }\n  }\n\n  delete framebuffer;\n  framebuffer = fb;\n}\n\nvoid CConnection::initialiseProtocol()\n{\n  state_ = RFBSTATE_PROTOCOL_VERSION;\n}\n\nbool CConnection::processMsg()\n{\n  switch (state_) {\n\n  case RFBSTATE_PROTOCOL_VERSION: return processVersionMsg();        break;\n  case RFBSTATE_SECURITY_TYPES:   return processSecurityTypesMsg();  break;\n  case RFBSTATE_SECURITY:         return processSecurityMsg();       break;\n  case RFBSTATE_SECURITY_RESULT:  return processSecurityResultMsg(); break;\n  case RFBSTATE_SECURITY_REASON:  return processSecurityReasonMsg(); break;\n  case RFBSTATE_INITIALISATION:   return processInitMsg();           break;\n  case RFBSTATE_NORMAL:           return reader_->readMsg();         break;\n  case RFBSTATE_CLOSING:\n    throw std::logic_error(\"CConnection::processMsg: Called while closing\");\n  case RFBSTATE_UNINITIALISED:\n    throw std::logic_error(\"CConnection::processMsg: Not initialised yet?\");\n  default:\n    throw std::logic_error(\"CConnection::processMsg: Invalid state\");\n  }\n}\n\nbool CConnection::processVersionMsg()\n{\n  char verStr[27]; // FIXME: gcc has some bug in format-overflow\n  int majorVersion;\n  int minorVersion;\n\n  vlog.debug(\"Reading protocol version\");\n\n  if (!is->hasData(12))\n    return false;\n\n  is->readBytes((uint8_t*)verStr, 12);\n  verStr[12] = '\\0';\n\n  if (sscanf(verStr, \"RFB %03d.%03d\\n\",\n             &majorVersion, &minorVersion) != 2) {\n    state_ = RFBSTATE_INVALID;\n    throw protocol_error(\"Reading version failed, not an RFB server?\");\n  }\n\n  server.setVersion(majorVersion, minorVersion);\n\n  vlog.info(\"Server supports RFB protocol version %d.%d\",\n            server.majorVersion, server.minorVersion);\n\n  // The only official RFB protocol versions are currently 3.3, 3.7 and 3.8\n  if (server.beforeVersion(3,3)) {\n    vlog.error(\"Server gave unsupported RFB protocol version %d.%d\",\n               server.majorVersion, server.minorVersion);\n    state_ = RFBSTATE_INVALID;\n    throw protocol_error(\n      core::format(\"Server gave unsupported RFB protocol version %d.%d\",\n                   server.majorVersion, server.minorVersion));\n  } else if (server.beforeVersion(3,7)) {\n    server.setVersion(3,3);\n  } else if (server.afterVersion(3,8)) {\n    server.setVersion(3,8);\n  }\n\n  sprintf(verStr, \"RFB %03d.%03d\\n\",\n          server.majorVersion, server.minorVersion);\n  os->writeBytes((const uint8_t*)verStr, 12);\n  os->flush();\n\n  state_ = RFBSTATE_SECURITY_TYPES;\n\n  vlog.info(\"Using RFB protocol version %d.%d\",\n            server.majorVersion, server.minorVersion);\n\n  return true;\n}\n\n\nbool CConnection::processSecurityTypesMsg()\n{\n  vlog.debug(\"Processing security types message\");\n\n  int secType = secTypeInvalid;\n\n  std::list<uint8_t> secTypes;\n  secTypes = security.GetEnabledSecTypes();\n\n  if (server.isVersion(3,3)) {\n\n    // legacy 3.3 server may only offer \"vnc authentication\" or \"none\"\n\n    if (!is->hasData(4))\n      return false;\n\n    secType = is->readU32();\n    if (secType == secTypeInvalid) {\n      state_ = RFBSTATE_SECURITY_REASON;\n      return true;\n    } else if (secType == secTypeNone || secType == secTypeVncAuth) {\n      if (std::find(secTypes.begin(), secTypes.end(),\n                    secType) == secTypes.end())\n        secType = secTypeInvalid;\n    } else {\n      vlog.error(\"Unknown 3.3 security type %d\", secType);\n      throw protocol_error(\"Unknown 3.3 security type\");\n    }\n\n  } else {\n\n    // >=3.7 server will offer us a list\n\n    if (!is->hasData(1))\n      return false;\n\n    is->setRestorePoint();\n\n    int nServerSecTypes = is->readU8();\n\n    if (!is->hasDataOrRestore(nServerSecTypes))\n      return false;\n    is->clearRestorePoint();\n\n    if (nServerSecTypes == 0) {\n      state_ = RFBSTATE_SECURITY_REASON;\n      return true;\n    }\n\n    for (int i = 0; i < nServerSecTypes; i++) {\n      uint8_t serverSecType = is->readU8();\n      vlog.debug(\"Server offers security type %s(%d)\",\n                 secTypeName(serverSecType), serverSecType);\n\n      /*\n       * Use the first type sent by server which matches client's type.\n       * It means server's order specifies priority.\n       */\n      if (secType == secTypeInvalid) {\n        if (std::find(secTypes.begin(), secTypes.end(),\n                      serverSecType) != secTypes.end())\n          secType = serverSecType;\n      }\n    }\n\n    // Inform the server of our decision\n    if (secType != secTypeInvalid) {\n      os->writeU8(secType);\n      os->flush();\n      vlog.info(\"Choosing security type %s(%d)\",secTypeName(secType),secType);\n    }\n  }\n\n  if (secType == secTypeInvalid) {\n    state_ = RFBSTATE_INVALID;\n    vlog.error(\"No matching security types\");\n    throw protocol_error(\"No matching security types\");\n  }\n\n  state_ = RFBSTATE_SECURITY;\n  csecurity = security.GetCSecurity(this, secType);\n\n  return true;\n}\n\nbool CConnection::processSecurityMsg()\n{\n  vlog.debug(\"Processing security message\");\n  if (!csecurity->processMsg())\n    return false;\n\n  state_ = RFBSTATE_SECURITY_RESULT;\n\n  return true;\n}\n\nbool CConnection::processSecurityResultMsg()\n{\n  vlog.debug(\"Processing security result message\");\n  int result;\n\n  if (server.beforeVersion(3,8) && csecurity->getType() == secTypeNone) {\n    result = secResultOK;\n  } else {\n    if (!is->hasData(4))\n      return false;\n    result = is->readU32();\n  }\n\n  switch (result) {\n  case secResultOK:\n    securityCompleted();\n    return true;\n  case secResultFailed:\n    vlog.debug(\"Auth failed\");\n    break;\n  case secResultTooMany:\n    vlog.debug(\"Auth failed: Too many tries\");\n    break;\n  default:\n    throw protocol_error(\"Unknown security result from server\");\n  }\n\n  if (server.beforeVersion(3,8)) {\n    state_ = RFBSTATE_INVALID;\n    throw auth_error(\"Authentication failed\");\n  }\n\n  state_ = RFBSTATE_SECURITY_REASON;\n  return true;\n}\n\nbool CConnection::processSecurityReasonMsg()\n{\n  vlog.debug(\"Processing security reason message\");\n\n  if (!is->hasData(4))\n    return false;\n\n  is->setRestorePoint();\n\n  uint32_t len = is->readU32();\n  if (!is->hasDataOrRestore(len))\n    return false;\n  is->clearRestorePoint();\n\n  std::vector<char> reason(len + 1);\n  is->readBytes((uint8_t*)reason.data(), len);\n  reason[len] = '\\0';\n\n  state_ = RFBSTATE_INVALID;\n  throw auth_error(reason.data());\n}\n\nbool CConnection::processInitMsg()\n{\n  vlog.debug(\"Reading server initialisation\");\n  return reader_->readServerInit();\n}\n\nvoid CConnection::securityCompleted()\n{\n  state_ = RFBSTATE_INITIALISATION;\n  reader_ = new CMsgReader(this, is);\n  writer_ = new CMsgWriter(&server, os);\n  vlog.debug(\"Authentication success!\");\n  writer_->writeClientInit(shared);\n}\n\nvoid CConnection::close()\n{\n  state_ = RFBSTATE_CLOSING;\n\n  /*\n   * We're already shutting down, so just log any pending decoder\n   * problems\n   */\n  try {\n    decoder.flush();\n  } catch (std::exception& e) {\n    vlog.error(\"%s\", e.what());\n  }\n\n  setFramebuffer(nullptr);\n  delete csecurity;\n  csecurity = nullptr;\n  delete reader_;\n  reader_ = nullptr;\n  delete writer_;\n  writer_ = nullptr;\n}\n\nvoid CConnection::setDesktopSize(int w, int h)\n{\n  decoder.flush();\n\n  server.setDimensions(w, h);\n\n  if (continuousUpdates)\n    writer()->writeEnableContinuousUpdates(true, 0, 0,\n                                           server.width(),\n                                           server.height());\n\n  resizeFramebuffer();\n  assert(framebuffer != nullptr);\n  assert(framebuffer->width() == server.width());\n  assert(framebuffer->height() == server.height());\n}\n\nvoid CConnection::setExtendedDesktopSize(unsigned reason,\n                                         unsigned result,\n                                         int w, int h,\n                                         const ScreenSet& layout)\n{\n  decoder.flush();\n\n  server.supportsSetDesktopSize = true;\n\n  if ((reason != reasonClient) || (result == resultSuccess))\n    server.setDimensions(w, h, layout);\n\n  if ((reason == reasonClient) && (result != resultSuccess)) {\n    vlog.error(\"SetDesktopSize failed: %d\", result);\n    return;\n  }\n\n  if (continuousUpdates)\n    writer()->writeEnableContinuousUpdates(true, 0, 0,\n                                           server.width(),\n                                           server.height());\n\n  resizeFramebuffer();\n  assert(framebuffer != nullptr);\n  assert(framebuffer->width() == server.width());\n  assert(framebuffer->height() == server.height());\n}\n\nvoid CConnection::setCursor(int width, int height,\n                            const core::Point& hotspot,\n                            const uint8_t* data)\n{\n  Cursor cursor(width, height, hotspot, data);\n  server.setCursor(cursor);\n}\n\nvoid CConnection::setCursorPos(const core::Point& /*pos*/)\n{\n}\n\nvoid CConnection::setName(const char* name)\n{\n  server.setName(name);\n}\n\nvoid CConnection::fence(uint32_t flags, unsigned len, const uint8_t data[])\n{\n  server.supportsFence = true;\n\n  if (flags & fenceFlagRequest) {\n    // FIXME: We handle everything synchronously, and we assume anything\n    //        using us also does so, which means we automatically handle\n    //        these flags\n    flags = flags & (fenceFlagBlockBefore | fenceFlagBlockAfter);\n\n    writer()->writeFence(flags, len, data);\n    return;\n  }\n}\n\nvoid CConnection::endOfContinuousUpdates()\n{\n  server.supportsContinuousUpdates = true;\n\n  // We've gotten the marker for a format change, so make the pending\n  // one active\n  if (pendingPFChange) {\n    server.setPF(pendingPF);\n    pendingPFChange = false;\n\n    // We might have another change pending\n    if (formatChange)\n      requestNewUpdate();\n  }\n}\n\nvoid CConnection::supportsQEMUKeyEvent()\n{\n  server.supportsQEMUKeyEvent = true;\n}\n\nvoid CConnection::supportsExtendedMouseButtons()\n{\n  server.supportsExtendedMouseButtons = true;\n}\n\nvoid CConnection::serverInit(int width, int height,\n                             const PixelFormat& pf,\n                             const char* name)\n{\n  server.setDimensions(width, height);\n  server.setPF(pf);\n  server.setName(name);\n\n  state_ = RFBSTATE_NORMAL;\n  vlog.debug(\"Initialisation done\");\n\n  initDone();\n  assert(framebuffer != nullptr);\n  assert(framebuffer->width() == server.width());\n  assert(framebuffer->height() == server.height());\n\n  // We want to make sure we call SetEncodings at least once\n  encodingChange = true;\n\n  requestNewUpdate();\n\n  // This initial update request is a bit of a corner case, so we need\n  // to help out setting the correct format here.\n  if (pendingPFChange) {\n    server.setPF(pendingPF);\n    pendingPFChange = false;\n  }\n}\n\nbool CConnection::readAndDecodeRect(const core::Rect& r, int encoding,\n                                    ModifiablePixelBuffer* pb)\n{\n  if (!decoder.decodeRect(r, encoding, pb))\n    return false;\n  decoder.flush();\n  return true;\n}\n\nvoid CConnection::framebufferUpdateStart()\n{\n  assert(framebuffer != nullptr);\n\n  // Note: This might not be true if continuous updates are supported\n  pendingUpdate = false;\n\n  requestNewUpdate();\n}\n\nvoid CConnection::framebufferUpdateEnd()\n{\n  decoder.flush();\n\n  // A format change has been scheduled and we are now past the update\n  // with the old format. Time to active the new one.\n  if (pendingPFChange && !continuousUpdates) {\n    server.setPF(pendingPF);\n    pendingPFChange = false;\n  }\n\n  if (firstUpdate) {\n    if (server.supportsContinuousUpdates) {\n      vlog.info(\"Enabling continuous updates\");\n      continuousUpdates = true;\n      writer()->writeEnableContinuousUpdates(true, 0, 0,\n                                             server.width(),\n                                             server.height());\n    }\n\n    firstUpdate = false;\n  }\n}\n\nbool CConnection::dataRect(const core::Rect& r, int encoding)\n{\n  return decoder.decodeRect(r, encoding, framebuffer);\n}\n\nvoid CConnection::setColourMapEntries(int /*firstColour*/,\n                                      int /*nColours*/,\n                                      uint16_t* /*rgbs*/)\n{\n  vlog.error(\"Invalid SetColourMapEntries from server!\");\n}\n\nvoid CConnection::serverCutText(const char* str)\n{\n  hasLocalClipboard = false;\n\n  serverClipboard = str;\n  hasRemoteClipboard = true;\n\n  handleClipboardAnnounce(true);\n}\n\nvoid CConnection::setLEDState(unsigned int state)\n{\n  server.setLEDState(state);\n}\n\nvoid CConnection::handleClipboardCaps(uint32_t flags,\n                                      const uint32_t* lengths)\n{\n  int i;\n  uint32_t sizes[] = { 0 };\n\n  vlog.debug(\"Got server clipboard capabilities:\");\n  for (i = 0;i < 16;i++) {\n    if (flags & (1 << i)) {\n      const char *type;\n\n      switch (1 << i) {\n        case clipboardUTF8:\n          type = \"Plain text\";\n          break;\n        case clipboardRTF:\n          type = \"Rich text\";\n          break;\n        case clipboardHTML:\n          type = \"HTML\";\n          break;\n        case clipboardDIB:\n          type = \"Images\";\n          break;\n        case clipboardFiles:\n          type = \"Files\";\n          break;\n        default:\n          vlog.debug(\"    Unknown format 0x%x\", 1 << i);\n          continue;\n      }\n\n      if (lengths[i] == 0)\n        vlog.debug(\"    %s (only notify)\", type);\n      else {\n        vlog.debug(\"    %s (automatically send up to %s)\",\n                   type, core::iecPrefix(lengths[i], \"B\").c_str());\n      }\n    }\n  }\n\n  server.setClipboardCaps(flags, lengths);\n\n  writer()->writeClipboardCaps(rfb::clipboardUTF8 |\n                               rfb::clipboardRequest |\n                               rfb::clipboardPeek |\n                               rfb::clipboardNotify |\n                               rfb::clipboardProvide,\n                               sizes);\n}\n\nvoid CConnection::handleClipboardRequest(uint32_t flags)\n{\n  if (!(flags & rfb::clipboardUTF8)) {\n    vlog.debug(\"Ignoring clipboard request for unsupported formats 0x%x\", flags);\n    return;\n  }\n  if (!hasLocalClipboard) {\n    vlog.debug(\"Ignoring unexpected clipboard request\");\n    return;\n  }\n  handleClipboardRequest();\n}\n\nvoid CConnection::handleClipboardPeek()\n{\n  if (server.clipboardFlags() & rfb::clipboardNotify)\n    writer()->writeClipboardNotify(hasLocalClipboard ? rfb::clipboardUTF8 : 0);\n}\n\nvoid CConnection::handleClipboardNotify(uint32_t flags)\n{\n  hasRemoteClipboard = false;\n\n  if (flags & rfb::clipboardUTF8) {\n    hasLocalClipboard = false;\n    handleClipboardAnnounce(true);\n  } else {\n    handleClipboardAnnounce(false);\n  }\n}\n\nvoid CConnection::handleClipboardProvide(uint32_t flags,\n                                         const size_t* lengths,\n                                         const uint8_t* const* data)\n{\n  if (!(flags & rfb::clipboardUTF8)) {\n    vlog.debug(\"Ignoring clipboard provide with unsupported formats 0x%x\", flags);\n    return;\n  }\n\n  // FIXME: This conversion magic should be in CMsgReader\n  if (!core::isValidUTF8((const char*)data[0], lengths[0])) {\n    vlog.error(\"Invalid UTF-8 sequence in clipboard - ignoring\");\n    return;\n  }\n  serverClipboard = core::convertLF((const char*)data[0], lengths[0]);\n  hasRemoteClipboard = true;\n\n  // FIXME: Should probably verify that this data was actually requested\n  handleClipboardData(serverClipboard.c_str());\n}\n\nvoid CConnection::initDone()\n{\n}\n\nvoid CConnection::resizeFramebuffer()\n{\n  assert(false);\n}\n\nvoid CConnection::handleClipboardRequest()\n{\n}\n\nvoid CConnection::handleClipboardAnnounce(bool /*available*/)\n{\n}\n\nvoid CConnection::handleClipboardData(const char* /*data*/)\n{\n}\n\nvoid CConnection::requestClipboard()\n{\n  if (hasRemoteClipboard) {\n    handleClipboardData(serverClipboard.c_str());\n    return;\n  }\n\n  if (server.clipboardFlags() & rfb::clipboardRequest)\n    writer()->writeClipboardRequest(rfb::clipboardUTF8);\n}\n\nvoid CConnection::announceClipboard(bool available)\n{\n  hasLocalClipboard = available;\n  unsolicitedClipboardAttempt = false;\n\n  // Attempt an unsolicited transfer?\n  if (available &&\n      (server.clipboardSize(rfb::clipboardUTF8) > 0) &&\n      (server.clipboardFlags() & rfb::clipboardProvide)) {\n    vlog.debug(\"Attempting unsolicited clipboard transfer...\");\n    unsolicitedClipboardAttempt = true;\n    handleClipboardRequest();\n    return;\n  }\n\n  if (server.clipboardFlags() & rfb::clipboardNotify) {\n    writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);\n    return;\n  }\n\n  if (available)\n    handleClipboardRequest();\n}\n\nvoid CConnection::sendClipboardData(const char* data)\n{\n  if (server.clipboardFlags() & rfb::clipboardProvide) {\n    // FIXME: This conversion magic should be in CMsgWriter\n    std::string filtered(core::convertCRLF(data));\n    size_t sizes[1] = { filtered.size() + 1 };\n    const uint8_t* datas[1] = { (const uint8_t*)filtered.c_str() };\n\n    if (unsolicitedClipboardAttempt) {\n      unsolicitedClipboardAttempt = false;\n      if (sizes[0] > server.clipboardSize(rfb::clipboardUTF8)) {\n        vlog.debug(\"Clipboard was too large for unsolicited clipboard transfer\");\n        if (server.clipboardFlags() & rfb::clipboardNotify)\n          writer()->writeClipboardNotify(rfb::clipboardUTF8);\n        return;\n      }\n    }\n\n    writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, datas);\n  } else {\n    writer()->writeClientCutText(data);\n  }\n}\n\nvoid CConnection::sendKeyPress(int systemKeyCode,\n                               uint32_t keyCode, uint32_t keySym)\n{\n  // For the first few years, there wasn't a good consensus on what the\n  // Windows keys should be mapped to for X11. So we need to help out a\n  // bit and map all variants to the same key...\n  switch (keySym) {\n  case XK_Hyper_L:\n    keySym = XK_Super_L;\n    break;\n  case XK_Hyper_R:\n    keySym = XK_Super_R;\n    break;\n  // There has been several variants for Shift-Tab over the years.\n  // RFB states that we should always send a normal tab.\n  case XK_ISO_Left_Tab:\n    keySym = XK_Tab;\n    break;\n  }\n\n#ifdef __APPLE__\n  // Alt on OS X behaves more like AltGr on other systems, and to get\n  // sane behaviour we should translate things in that manner for the\n  // remote VNC server. However that means we lose the ability to use\n  // Alt as a shortcut modifier. Do what RealVNC does and hijack the\n  // left command key as an Alt replacement.\n  switch (keySym) {\n  case XK_Super_L:\n    keySym = XK_Alt_L;\n    break;\n  case XK_Super_R:\n    keySym = XK_Super_L;\n    break;\n  case XK_Alt_L:\n    keySym = XK_Mode_switch;\n    break;\n  case XK_Alt_R:\n    keySym = XK_ISO_Level3_Shift;\n    break;\n  }\n#endif\n\n  // Because of the way keyboards work, we cannot expect to have the same\n  // symbol on release as when pressed. This breaks the VNC protocol however,\n  // so we need to keep track of what keysym a key _code_ generated on press\n  // and send the same on release.\n  downKeys[systemKeyCode].keyCode = keyCode;\n  downKeys[systemKeyCode].keySym = keySym;\n\n  vlog.debug(\"Key pressed: %d => 0x%02x / XK_%s (0x%04x)\",\n             systemKeyCode, keyCode, KeySymName(keySym), keySym);\n\n  writer()->writeKeyEvent(keySym, keyCode, true);\n}\n\nvoid CConnection::sendKeyRelease(int systemKeyCode)\n{\n  DownMap::iterator iter;\n\n  iter = downKeys.find(systemKeyCode);\n  if (iter == downKeys.end()) {\n    // These occur somewhat frequently so let's not spam them unless\n    // logging is turned up.\n    vlog.debug(\"Unexpected release of key code %d\", systemKeyCode);\n    return;\n  }\n\n  vlog.debug(\"Key released: %d => 0x%02x / XK_%s (0x%04x)\",\n             systemKeyCode, iter->second.keyCode,\n             KeySymName(iter->second.keySym), iter->second.keySym);\n\n  writer()->writeKeyEvent(iter->second.keySym,\n                          iter->second.keyCode, false);\n\n  downKeys.erase(iter);\n}\n\nvoid CConnection::releaseAllKeys()\n{\n  while (!downKeys.empty())\n    sendKeyRelease(downKeys.begin()->first);\n}\n\nvoid CConnection::refreshFramebuffer()\n{\n  forceNonincremental = true;\n\n  // Without continuous updates we have to make sure we only have a\n  // single update in flight, so we'll have to wait to do the refresh\n  if (continuousUpdates)\n    requestNewUpdate();\n}\n\nvoid CConnection::setPreferredEncoding(int encoding)\n{\n  if (preferredEncoding == encoding)\n    return;\n\n  preferredEncoding = encoding;\n  encodingChange = true;\n}\n\nint CConnection::getPreferredEncoding()\n{\n  return preferredEncoding;\n}\n\nvoid CConnection::setCompressLevel(int level)\n{\n  if (compressLevel == level)\n    return;\n\n  compressLevel = level;\n  encodingChange = true;\n}\n\nint CConnection::getCompressLevel()\n{\n  return compressLevel;\n}\n\nvoid CConnection::setQualityLevel(int level)\n{\n  if (qualityLevel == level)\n    return;\n\n  qualityLevel = level;\n  encodingChange = true;\n}\n\nint CConnection::getQualityLevel()\n{\n  return qualityLevel;\n}\n\nvoid CConnection::setPF(const PixelFormat& pf)\n{\n  if (server.pf() == pf && !formatChange)\n    return;\n\n  nextPF = pf;\n  formatChange = true;\n}\n\nbool CConnection::isSecure() const\n{\n  return csecurity ? csecurity->isSecure() : false;\n}\n\n// requestNewUpdate() requests an update from the server, having set the\n// format and encoding appropriately.\nvoid CConnection::requestNewUpdate()\n{\n  if (formatChange && !pendingPFChange) {\n    /* Catch incorrect requestNewUpdate calls */\n    assert(!pendingUpdate || continuousUpdates);\n\n    // We have to make sure we switch the internal format at a safe\n    // time. For continuous updates we temporarily disable updates and\n    // look for a EndOfContinuousUpdates message to see when to switch.\n    // For classical updates we just got a new update right before this\n    // function was called, so we need to make sure we finish that\n    // update before we can switch.\n\n    pendingPFChange = true;\n    pendingPF = nextPF;\n\n    if (continuousUpdates)\n      writer()->writeEnableContinuousUpdates(false, 0, 0, 0, 0);\n\n    writer()->writeSetPixelFormat(pendingPF);\n\n    if (continuousUpdates)\n      writer()->writeEnableContinuousUpdates(true, 0, 0,\n                                             server.width(),\n                                             server.height());\n\n    formatChange = false;\n  }\n\n  if (encodingChange) {\n    updateEncodings();\n    encodingChange = false;\n  }\n\n  if (forceNonincremental || !continuousUpdates) {\n    pendingUpdate = true;\n    writer()->writeFramebufferUpdateRequest({0, 0,\n                                             server.width(),\n                                             server.height()},\n                                            !forceNonincremental);\n  }\n\n  forceNonincremental = false;\n}\n\n// Ask for encodings based on which decoders are supported.  Assumes higher\n// encoding numbers are more desirable.\n\nvoid CConnection::updateEncodings()\n{\n  std::list<uint32_t> encodings;\n\n  if (supportsLocalCursor) {\n    encodings.push_back(pseudoEncodingCursorWithAlpha);\n    encodings.push_back(pseudoEncodingVMwareCursor);\n    encodings.push_back(pseudoEncodingCursor);\n    encodings.push_back(pseudoEncodingXCursor);\n  }\n  if (supportsCursorPosition) {\n    encodings.push_back(pseudoEncodingVMwareCursorPosition);\n  }\n  if (supportsDesktopResize) {\n    encodings.push_back(pseudoEncodingDesktopSize);\n    encodings.push_back(pseudoEncodingExtendedDesktopSize);\n  }\n  if (supportsLEDState) {\n    encodings.push_back(pseudoEncodingLEDState);\n    encodings.push_back(pseudoEncodingVMwareLEDState);\n  }\n\n  encodings.push_back(pseudoEncodingDesktopName);\n  encodings.push_back(pseudoEncodingLastRect);\n  encodings.push_back(pseudoEncodingExtendedClipboard);\n  encodings.push_back(pseudoEncodingContinuousUpdates);\n  encodings.push_back(pseudoEncodingFence);\n  encodings.push_back(pseudoEncodingQEMUKeyEvent);\n  encodings.push_back(pseudoEncodingExtendedMouseButtons);\n\n  if (Decoder::supported(preferredEncoding)) {\n    if (!noJpeg || preferredEncoding != encodingJPEG)\n      encodings.push_back(preferredEncoding);\n  }\n\n  encodings.push_back(encodingCopyRect);\n\n  for (int i = encodingMax; i >= 0; i--) {\n    if ((i != preferredEncoding) && Decoder::supported(i)) {\n      if (noJpeg && i == encodingJPEG)\n        continue;\n      encodings.push_back(i);\n    }\n  }\n\n  if (compressLevel >= 0 && compressLevel <= 9)\n      encodings.push_back(pseudoEncodingCompressLevel0 + compressLevel);\n  // Tight JPEG is enabled by setting a quality level\n  if (!noJpeg) {\n    if (qualityLevel >= 0 && qualityLevel <= 9)\n      encodings.push_back(pseudoEncodingQualityLevel0 + qualityLevel);\n  }\n\n  writer()->writeSetEncodings(encodings);\n}\n"
  },
  {
    "path": "common/rfb/CConnection.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// CConnection - class on the client side representing a connection to a\n// server.  A derived class should override methods appropriately.\n//\n\n#ifndef __RFB_CCONNECTION_H__\n#define __RFB_CCONNECTION_H__\n\n#include <map>\n#include <string>\n\n#include <core/Configuration.h>\n\n#include <rfb/CMsgHandler.h>\n#include <rfb/DecodeManager.h>\n#include <rfb/PixelFormat.h>\n#include <rfb/SecurityClient.h>\n\nnamespace rdr {\n  class InStream;\n  class OutStream;\n}\n\nnamespace rfb {\n\n  class CMsgReader;\n  class CMsgWriter;\n  class CSecurity;\n\n  enum MsgBoxFlags{\n      M_OK = 0,\n      M_OKCANCEL = 1,\n      M_YESNO = 4,\n      M_ICONERROR = 0x10,\n      M_ICONQUESTION = 0x20,\n      M_ICONWARNING = 0x30,\n      M_ICONINFORMATION = 0x40,\n      M_DEFBUTTON1 = 0,\n      M_DEFBUTTON2 = 0x100\n  };\n\n  class CConnection : public CMsgHandler {\n  public:\n\n    CConnection();\n    virtual ~CConnection();\n\n    // Settings that control the connection\n\n    static core::BoolParameter noJpeg;\n\n    // Methods to initialise the connection\n\n    // setServerName() is used to provide a unique(ish) name for the server to\n    // which we are connected.  This might be the result of getPeerEndpoint on\n    // a TcpSocket, for example, or a host specified by DNS name & port.\n    // The serverName is used when verifying the Identity of a host (see RA2).\n    void setServerName(const char* name_);\n\n    // setStreams() sets the streams to be used for the connection.  These must\n    // be set before initialiseProtocol() and processMsg() are called.  The\n    // CSecurity object may call setStreams() again to provide alternative\n    // streams over which the RFB protocol is sent (i.e. encrypting/decrypting\n    // streams).  Ownership of the streams remains with the caller\n    // (i.e. SConnection will not delete them).\n    void setStreams(rdr::InStream* is, rdr::OutStream* os);\n\n    // setShared sets the value of the shared flag which will be sent to the\n    // server upon initialisation.\n    void setShared(bool s) { shared = s; }\n\n    // setFramebuffer configures the PixelBuffer that the CConnection\n    // should render all pixel data in to. Note that the CConnection\n    // takes ownership of the PixelBuffer and it must not be deleted by\n    // anyone else. Call setFramebuffer again with NULL or a different\n    // PixelBuffer to delete the previous one.\n    void setFramebuffer(ModifiablePixelBuffer* fb);\n\n    // initialiseProtocol() should be called once the streams and security\n    // types are set.  Subsequently, processMsg() should be called whenever\n    // there is data to read on the InStream.\n    void initialiseProtocol();\n\n    // processMsg() should be called whenever there is data available on\n    // the CConnection's current InStream. It will process at most one\n    // RFB message before returning. If there was insufficient data,\n    // then it will return false and should be called again once more\n    // data is available.\n    bool processMsg();\n\n    // close() gracefully shuts down the connection to the server and\n    // should be called before terminating the underlying network\n    // connection\n    void close();\n\n    // requestClipboard() will result in a request to the server to\n    // transfer its clipboard data. A call to handleClipboardData()\n    // will be made once the data is available.\n    virtual void requestClipboard();\n\n    // announceClipboard() informs the server of changes to the\n    // clipboard on the client. The server may later request the\n    // clipboard data via handleClipboardRequest().\n    virtual void announceClipboard(bool available);\n\n    // sendClipboardData() transfers the clipboard data to the server\n    // and should be called whenever the server has requested the\n    // clipboard via handleClipboardRequest().\n    virtual void sendClipboardData(const char* data);\n\n    // sendKeyPress()/sendKeyRelease() send keyboard events to the\n    // server\n    void sendKeyPress(int systemKeyCode, uint32_t keyCode, uint32_t keySym);\n    void sendKeyRelease(int systemKeyCode);\n\n    // releaseAllKeys() sends keyboard release events to the server for\n    // all keys that are currently pressed down by this client,\n    // avoiding keys getting stuck. This can be useful if the client\n    // loses keyboard focus or otherwise no longer gets keyboard events\n    // from the system.\n    void releaseAllKeys();\n\n    // refreshFramebuffer() forces a complete refresh of the entire\n    // framebuffer\n    void refreshFramebuffer();\n\n    // setPreferredEncoding()/getPreferredEncoding() adjusts which\n    // encoding is listed first as a hint to the server that it is the\n    // preferred one\n    void setPreferredEncoding(int encoding);\n    int getPreferredEncoding();\n    // setCompressLevel()/setQualityLevel() controls the encoding hints\n    // sent to the server\n    void setCompressLevel(int level);\n    int getCompressLevel();\n    void setQualityLevel(int level);\n    int getQualityLevel();\n    // setPF() controls the pixel format requested from the server.\n    // server.pf() will automatically be adjusted once the new format\n    // is active.\n    void setPF(const PixelFormat& pf);\n\n    CMsgReader* reader() { return reader_; }\n    CMsgWriter* writer() { return writer_; }\n\n    rdr::InStream* getInStream() { return is; }\n    rdr::OutStream* getOutStream() { return os; }\n\n    // Access method used by SSecurity implementations that can verify servers'\n    // Identities, to determine the unique(ish) name of the server.\n    const char* getServerName() const { return serverName.c_str(); }\n\n    bool isSecure() const;\n\n    enum stateEnum {\n      RFBSTATE_UNINITIALISED,\n      RFBSTATE_PROTOCOL_VERSION,\n      RFBSTATE_SECURITY_TYPES,\n      RFBSTATE_SECURITY,\n      RFBSTATE_SECURITY_RESULT,\n      RFBSTATE_SECURITY_REASON,\n      RFBSTATE_INITIALISATION,\n      RFBSTATE_NORMAL,\n      RFBSTATE_CLOSING,\n      RFBSTATE_INVALID\n    };\n\n    stateEnum state() { return state_; }\n\n    // Methods used by SSecurity classes\n\n    // getUserPasswd() gets the username and password.  This might\n    // involve a dialog, getpass(), etc.  The user buffer pointer can be\n    // null, in which case no user name will be retrieved.\n    virtual void getUserPasswd(bool secure, std::string* user,\n                               std::string* password) = 0;\n\n    // showMsgBox() displays a message box with the specified style and\n    // contents.  The return value is true if the user clicked OK/Yes.\n    virtual bool showMsgBox(MsgBoxFlags flags, const char *title,\n                            const char *text) = 0;\n\n  protected:\n\n    // Methods overridden from CMsgHandler\n\n    // Note: These must be called by any deriving classes\n\n    void setDesktopSize(int w, int h) override;\n    void setExtendedDesktopSize(unsigned reason, unsigned result,\n                                int w, int h,\n                                const ScreenSet& layout) override;\n\n    void setCursor(int width, int height, const core::Point& hotspot,\n                   const uint8_t* data) override;\n    void setCursorPos(const core::Point& pos) override;\n\n    void setName(const char* name) override;\n\n    void fence(uint32_t flags, unsigned len, const uint8_t data[]) override;\n\n    void endOfContinuousUpdates() override;\n\n    void supportsQEMUKeyEvent() override;\n\n    void supportsExtendedMouseButtons() override;\n\n    void serverInit(int width, int height, const PixelFormat& pf,\n                    const char* name) override;\n\n    bool readAndDecodeRect(const core::Rect& r, int encoding,\n                           ModifiablePixelBuffer* pb) override;\n\n    void framebufferUpdateStart() override;\n    void framebufferUpdateEnd() override;\n    bool dataRect(const core::Rect& r, int encoding) override;\n\n    void setColourMapEntries(int firstColour, int nColours,\n                             uint16_t* rgbs) override;\n\n    void serverCutText(const char* str) override;\n\n    void setLEDState(unsigned int state) override;\n\n    void handleClipboardCaps(uint32_t flags,\n                             const uint32_t* lengths) override;\n    void handleClipboardRequest(uint32_t flags) override;\n    void handleClipboardPeek() override;\n    void handleClipboardNotify(uint32_t flags) override;\n    void handleClipboardProvide(uint32_t flags, const size_t* lengths,\n                                const uint8_t* const* data) override;\n\n\n    // Methods to be overridden in a derived class\n\n    // initDone() is called when the connection is fully established\n    // and standard messages can be sent. This is called before the\n    // initial FramebufferUpdateRequest giving a derived class the\n    // chance to modify pixel format and settings. The derived class\n    // must also make sure it has provided a valid framebuffer before\n    // returning.\n    virtual void initDone() = 0;\n\n    // resizeFramebuffer() is called whenever the framebuffer\n    // dimensions or the screen layout changes. A subclass must make\n    // sure the pixel buffer has been updated once this call returns.\n    virtual void resizeFramebuffer();\n\n    // handleClipboardRequest() is called whenever the server requests\n    // the client to send over its clipboard data. It will only be\n    // called after the client has first announced a clipboard change\n    // via announceClipboard().\n    virtual void handleClipboardRequest();\n\n    // handleClipboardAnnounce() is called to indicate a change in the\n    // clipboard on the server. Call requestClipboard() to access the\n    // actual data.\n    virtual void handleClipboardAnnounce(bool available);\n\n    // handleClipboardData() is called when the server has sent over\n    // the clipboard data as a result of a previous call to\n    // requestClipboard(). Note that this function might never be\n    // called if the clipboard data was no longer available when the\n    // server received the request.\n    virtual void handleClipboardData(const char* data);\n\n  protected:\n    CSecurity *csecurity;\n    SecurityClient security;\n\n  protected:\n    void setState(stateEnum s) { state_ = s; }\n\n    void setReader(CMsgReader *r) { reader_ = r; }\n    void setWriter(CMsgWriter *w) { writer_ = w; }\n\n    ModifiablePixelBuffer* getFramebuffer() { return framebuffer; }\n\n  protected:\n    // Optional capabilities that a subclass is expected to set to true\n    // if supported\n    bool supportsLocalCursor;\n    bool supportsCursorPosition;\n    bool supportsDesktopResize;\n    bool supportsLEDState;\n\n  private:\n    bool processVersionMsg();\n    bool processSecurityTypesMsg();\n    bool processSecurityMsg();\n    bool processSecurityResultMsg();\n    bool processSecurityReasonMsg();\n    bool processInitMsg();\n    void throwAuthError();\n    void securityCompleted();\n\n    void requestNewUpdate();\n    void updateEncodings();\n\n    rdr::InStream* is;\n    rdr::OutStream* os;\n    CMsgReader* reader_;\n    CMsgWriter* writer_;\n    bool deleteStreamsWhenDone;\n    bool shared;\n    stateEnum state_;\n\n    std::string serverName;\n\n    bool pendingPFChange;\n    rfb::PixelFormat pendingPF;\n\n    int preferredEncoding;\n    int compressLevel;\n    int qualityLevel;\n\n    bool formatChange;\n    rfb::PixelFormat nextPF;\n    bool encodingChange;\n\n    bool firstUpdate;\n    bool pendingUpdate;\n    bool continuousUpdates;\n\n    bool forceNonincremental;\n\n    ModifiablePixelBuffer* framebuffer;\n    DecodeManager decoder;\n\n    std::string serverClipboard;\n    bool hasRemoteClipboard;\n    bool hasLocalClipboard;\n    bool unsolicitedClipboardAttempt;\n\n    struct DownKey {\n        uint32_t keyCode;\n        uint32_t keySym;\n    };\n    typedef std::map<int, DownKey> DownMap;\n    DownMap downKeys;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/CMakeLists.txt",
    "content": "add_library(rfb STATIC\n  AccessRights.cxx\n  Blacklist.cxx\n  Congestion.cxx\n  CConnection.cxx\n  CMsgReader.cxx\n  CMsgWriter.cxx\n  CSecurityPlain.cxx\n  CSecurityStack.cxx\n  CSecurityVeNCrypt.cxx\n  CSecurityVncAuth.cxx\n  ClientParams.cxx\n  ComparingUpdateTracker.cxx\n  CopyRectDecoder.cxx\n  Cursor.cxx\n  DecodeManager.cxx\n  Decoder.cxx\n  d3des.c\n  EncodeManager.cxx\n  Encoder.cxx\n  HextileDecoder.cxx\n  HextileEncoder.cxx\n  JpegCompressor.cxx\n  JpegDecompressor.cxx\n  JPEGDecoder.cxx\n  JPEGEncoder.cxx\n  KeyRemapper.cxx\n  KeysymStr.c\n  PixelBuffer.cxx\n  PixelFormat.cxx\n  RREEncoder.cxx\n  RREDecoder.cxx\n  RawDecoder.cxx\n  RawEncoder.cxx\n  SConnection.cxx\n  SMsgReader.cxx\n  SMsgWriter.cxx\n  ServerCore.cxx\n  ServerParams.cxx\n  Security.cxx\n  SecurityServer.cxx\n  SecurityClient.cxx\n  SSecurityPlain.cxx\n  SSecurityStack.cxx\n  SSecurityVncAuth.cxx\n  SSecurityVeNCrypt.cxx\n  TightDecoder.cxx\n  TightEncoder.cxx\n  TightJPEGEncoder.cxx\n  UpdateTracker.cxx\n  VNCSConnectionST.cxx\n  VNCServerST.cxx\n  ZRLEEncoder.cxx\n  ZRLEDecoder.cxx\n  encodings.cxx\n  obfuscate.cxx)\n\ntarget_include_directories(rfb PUBLIC ${CMAKE_SOURCE_DIR}/common)\ntarget_include_directories(rfb SYSTEM PUBLIC ${JPEG_INCLUDE_DIR})\ntarget_link_libraries(rfb core rdr network)\ntarget_link_libraries(rfb ${JPEG_LIBRARIES} ${PIXMAN_LIBRARIES})\n\nif(ENABLE_H264 AND NOT H264_LIBS STREQUAL \"NONE\")\n  target_sources(rfb PRIVATE H264Decoder.cxx H264DecoderContext.cxx)\n  if(H264_LIBS STREQUAL \"LIBAV\")\n    target_sources(rfb PRIVATE H264LibavDecoderContext.cxx)\n  elseif(H264_LIBS STREQUAL \"WIN\")\n    target_sources(rfb PRIVATE H264WinDecoderContext.cxx)\n  endif()\n  target_include_directories(rfb SYSTEM PUBLIC ${H264_INCLUDE_DIRS})\n  target_link_libraries(rfb ${H264_LIBRARIES})\nendif()\n\nif(WIN32)\n  target_include_directories(rfb PUBLIC ${CMAKE_SOURCE_DIR}/win)\n  target_sources(rfb PRIVATE WinPasswdValidator.cxx)\nendif(WIN32)\n\nif(UNIX AND NOT APPLE)\n  target_sources(rfb PRIVATE UnixPasswordValidator.cxx)\n  target_include_directories(rfb SYSTEM PRIVATE ${PAM_INCLUDE_DIRS})\n  target_link_libraries(rfb ${PAM_LIBRARIES})\nendif()\n\nif(GNUTLS_FOUND)\n  target_sources(rfb PRIVATE CSecurityTLS.cxx SSecurityTLS.cxx)\n  target_include_directories(rfb SYSTEM PUBLIC ${GNUTLS_INCLUDE_DIR})\n  target_link_libraries(rfb ${GNUTLS_LIBRARIES})\n  # FIXME: Hack to block it marking gnutls_free() as dllimport\n  if(WIN32 AND BUILD_STATIC)\n    target_compile_definitions(rfb PRIVATE GNUTLS_INTERNAL_BUILD)\n  endif()\nendif()\n\nif (NETTLE_FOUND)\n  target_sources(rfb PRIVATE CSecurityDH.cxx CSecurityMSLogonII.cxx\n                 CSecurityRSAAES.cxx SSecurityRSAAES.cxx)\n  target_include_directories(rfb SYSTEM PUBLIC ${NETTLE_INCLUDE_DIRS})\n  target_link_libraries(rfb ${HOGWEED_LIBRARIES} ${NETTLE_LIBRARIES})\nendif()\n\nif(UNIX)\n  libtool_create_control_file(rfb)\nendif()\n"
  },
  {
    "path": "common/rfb/CMsgHandler.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// CMsgHandler - class to handle incoming messages on the client side.\n//\n\n#ifndef __RFB_CMSGHANDLER_H__\n#define __RFB_CMSGHANDLER_H__\n\n#include <stdint.h>\n\n#include <rfb/ServerParams.h>\n\nnamespace core {\n  struct Point;\n  struct Rect;\n}\n\nnamespace rfb {\n\n  class ModifiablePixelBuffer;\n  struct ScreenSet;\n\n  class CMsgHandler {\n  public:\n    // The following methods are called as corresponding messages are\n    // read. A derived class must override these methods.\n\n    virtual void setDesktopSize(int w, int h) = 0;\n    virtual void setExtendedDesktopSize(unsigned reason, unsigned result,\n                                        int w, int h,\n                                        const ScreenSet& layout) = 0;\n    virtual void setCursor(int width, int height, const\n                           core::Point& hotspot,\n                           const uint8_t* data) = 0;\n    virtual void setCursorPos(const core::Point& pos) = 0;\n    virtual void setName(const char* name) = 0;\n    virtual void fence(uint32_t flags, unsigned len,\n                       const uint8_t data[]) = 0;\n    virtual void endOfContinuousUpdates() = 0;\n    virtual void supportsQEMUKeyEvent() = 0;\n    virtual void supportsExtendedMouseButtons() = 0;\n    virtual void serverInit(int width, int height,\n                            const PixelFormat& pf,\n                            const char* name) = 0;\n\n    virtual bool readAndDecodeRect(const core::Rect& r, int encoding,\n                                   ModifiablePixelBuffer* pb) = 0;\n\n    virtual void framebufferUpdateStart() = 0;\n    virtual void framebufferUpdateEnd() = 0;\n    virtual bool dataRect(const core::Rect& r, int encoding) = 0;\n\n    virtual void setColourMapEntries(int firstColour, int nColours,\n\t\t\t\t     uint16_t* rgbs) = 0;\n    virtual void bell() = 0;\n    virtual void serverCutText(const char* str) = 0;\n\n    virtual void setLEDState(unsigned int state) = 0;\n\n    virtual void handleClipboardCaps(uint32_t flags,\n                                     const uint32_t* lengths) = 0;\n    virtual void handleClipboardRequest(uint32_t flags) = 0;\n    virtual void handleClipboardPeek() = 0;\n    virtual void handleClipboardNotify(uint32_t flags) = 0;\n    virtual void handleClipboardProvide(uint32_t flags,\n                                        const size_t* lengths,\n                                        const uint8_t* const* data) = 0;\n\n    ServerParams server;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/CMsgReader.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <stdio.h>\n\n#include <vector>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rdr/InStream.h>\n#include <rdr/ZlibInStream.h>\n\n#include <rfb/msgTypes.h>\n#include <rfb/clipboardTypes.h>\n#include <rfb/Exception.h>\n#include <rfb/CMsgHandler.h>\n#include <rfb/CMsgReader.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/ScreenSet.h>\n#include <rfb/encodings.h>\n\nstatic core::LogWriter vlog(\"CMsgReader\");\n\nstatic core::IntParameter maxCutText(\"MaxCutText\",\n                                     \"Maximum permitted length of an \"\n                                     \"incoming clipboard update\",\n                                     256*1024, 0, INT_MAX);\n\nusing namespace rfb;\n\nCMsgReader::CMsgReader(CMsgHandler* handler_, rdr::InStream* is_)\n  : imageBufIdealSize(0), handler(handler_), is(is_),\n    state(MSGSTATE_IDLE), cursorEncoding(-1)\n{\n}\n\nCMsgReader::~CMsgReader()\n{\n}\n\nbool CMsgReader::readServerInit()\n{\n  int width, height;\n  uint32_t len;\n\n  if (!is->hasData(2 + 2 + 16 + 4))\n    return false;\n\n  is->setRestorePoint();\n\n  width = is->readU16();\n  height = is->readU16();\n\n  PixelFormat pf;\n  pf.read(is);\n\n  len = is->readU32();\n  if (!is->hasDataOrRestore(len))\n    return false;\n  is->clearRestorePoint();\n  std::vector<char> name(len + 1);\n  is->readBytes((uint8_t*)name.data(), len);\n  name[len] = '\\0';\n\n  if (core::isValidUTF8(name.data()))\n    handler->serverInit(width, height, pf, name.data());\n  else\n    handler->serverInit(width, height, pf,\n                        core::latin1ToUTF8(name.data()).c_str());\n\n  return true;\n}\n\nbool CMsgReader::readMsg()\n{\n  if (state == MSGSTATE_IDLE) {\n    if (!is->hasData(1))\n      return false;\n\n    currentMsgType = is->readU8();\n    state = MSGSTATE_MESSAGE;\n  }\n\n  if (currentMsgType != msgTypeFramebufferUpdate) {\n    bool ret;\n\n    switch (currentMsgType) {\n    case msgTypeSetColourMapEntries:\n      ret = readSetColourMapEntries();\n      break;\n    case msgTypeBell:\n      ret = readBell();\n      break;\n    case msgTypeServerCutText:\n      ret = readServerCutText();\n      break;\n    case msgTypeFramebufferUpdate:\n      ret = readFramebufferUpdate();\n      break;\n    case msgTypeServerFence:\n      ret = readFence();\n      break;\n    case msgTypeEndOfContinuousUpdates:\n      ret = readEndOfContinuousUpdates();\n      break;\n    default:\n      throw protocol_error(core::format(\"Unknown message type %d\", currentMsgType));\n    }\n\n    if (ret)\n      state = MSGSTATE_IDLE;\n\n    return ret;\n  } else {\n    if (state == MSGSTATE_MESSAGE) {\n      if (!readFramebufferUpdate())\n        return false;\n\n      // Empty update?\n      if (nUpdateRectsLeft == 0) {\n        state = MSGSTATE_IDLE;\n        handler->framebufferUpdateEnd();\n        return true;\n      }\n\n      state = MSGSTATE_RECT_HEADER;\n    }\n\n    if (state == MSGSTATE_RECT_HEADER) {\n      if (!is->hasData(2 + 2 + 2 + 2 + 4))\n        return false;\n\n      int x = is->readU16();\n      int y = is->readU16();\n      int w = is->readU16();\n      int h = is->readU16();\n\n      dataRect.setXYWH(x, y, w, h);\n\n      rectEncoding = is->readS32();\n\n      state = MSGSTATE_RECT_DATA;\n    }\n\n    bool ret;\n\n    switch (rectEncoding) {\n    case pseudoEncodingLastRect:\n      nUpdateRectsLeft = 1;     // this rectangle is the last one\n      ret = true;\n      break;\n    case pseudoEncodingXCursor:\n      ret = readSetXCursor(dataRect.width(), dataRect.height(), dataRect.tl);\n      break;\n    case pseudoEncodingCursor:\n      ret = readSetCursor(dataRect.width(), dataRect.height(), dataRect.tl);\n      break;\n    case pseudoEncodingCursorWithAlpha:\n      ret = readSetCursorWithAlpha(dataRect.width(), dataRect.height(), dataRect.tl);\n      break;\n    case pseudoEncodingVMwareCursor:\n      ret = readSetVMwareCursor(dataRect.width(), dataRect.height(), dataRect.tl);\n      break;\n    case pseudoEncodingVMwareCursorPosition:\n      handler->setCursorPos(dataRect.tl);\n      ret = true;\n      break;\n    case pseudoEncodingDesktopName:\n      ret = readSetDesktopName(dataRect.tl.x, dataRect.tl.y,\n                               dataRect.width(), dataRect.height());\n      break;\n    case pseudoEncodingDesktopSize:\n      handler->setDesktopSize(dataRect.width(), dataRect.height());\n      ret = true;\n      break;\n    case pseudoEncodingExtendedDesktopSize:\n      ret = readExtendedDesktopSize(dataRect.tl.x, dataRect.tl.y,\n                                    dataRect.width(), dataRect.height());\n      break;\n    case pseudoEncodingLEDState:\n      ret = readLEDState();\n      break;\n    case pseudoEncodingVMwareLEDState:\n      ret = readVMwareLEDState();\n      break;\n    case pseudoEncodingQEMUKeyEvent:\n      handler->supportsQEMUKeyEvent();\n      ret = true;\n      break;\n    case pseudoEncodingExtendedMouseButtons:\n      handler->supportsExtendedMouseButtons();\n      ret = true;\n      break;\n    default:\n      ret = readRect(dataRect, rectEncoding);\n      break;\n    };\n\n    if (ret) {\n      state = MSGSTATE_RECT_HEADER;\n      nUpdateRectsLeft--;\n      if (nUpdateRectsLeft == 0) {\n        state = MSGSTATE_IDLE;\n        handler->framebufferUpdateEnd();\n      }\n    }\n\n    return ret;\n  }\n}\n\nbool CMsgReader::readSetColourMapEntries()\n{\n  if (!is->hasData(1 + 2 + 2))\n    return false;\n\n  is->setRestorePoint();\n\n  is->skip(1);\n  int firstColour = is->readU16();\n  int nColours = is->readU16();\n\n  if (!is->hasDataOrRestore(nColours * 3 * 2))\n    return false;\n  is->clearRestorePoint();\n\n  std::vector<uint16_t> rgbs(nColours * 3);\n  for (size_t i = 0; i < rgbs.size(); i++)\n    rgbs[i] = is->readU16();\n  handler->setColourMapEntries(firstColour, nColours, rgbs.data());\n\n  return true;\n}\n\nbool CMsgReader::readBell()\n{\n  handler->bell();\n  return true;\n}\n\nbool CMsgReader::readServerCutText()\n{\n  if (!is->hasData(3 + 4))\n    return false;\n\n  is->setRestorePoint();\n\n  is->skip(3);\n  uint32_t len = is->readU32();\n\n  if (len & 0x80000000) {\n    int32_t slen = len;\n    slen = -slen;\n    if (readExtendedClipboard(slen)) {\n      is->clearRestorePoint();\n      return true;\n    } else {\n      is->gotoRestorePoint();\n      return false;\n    }\n  }\n\n  if (!is->hasDataOrRestore(len))\n    return false;\n  is->clearRestorePoint();\n\n  if (len > (size_t)maxCutText) {\n    is->skip(len);\n    vlog.error(\"Cut text too long (%d bytes) - ignoring\",len);\n    return true;\n  }\n\n  std::vector<char> ca(len);\n  is->readBytes((uint8_t*)ca.data(), len);\n\n  std::string utf8(core::latin1ToUTF8(ca.data(), ca.size()));\n  std::string filtered(core::convertLF(utf8.data(), utf8.size()));\n\n  handler->serverCutText(filtered.c_str());\n\n  return true;\n}\n\nbool CMsgReader::readExtendedClipboard(int32_t len)\n{\n  uint32_t flags;\n  uint32_t action;\n\n  if (!is->hasData(len))\n    return false;\n\n  if (len < 4)\n    throw protocol_error(\"Invalid extended clipboard message\");\n  if (len > maxCutText) {\n    vlog.error(\"Extended clipboard message too long (%d bytes) - ignoring\", len);\n    is->skip(len);\n    return true;\n  }\n\n  flags = is->readU32();\n  action = flags & clipboardActionMask;\n\n  if (action & clipboardCaps) {\n    int i;\n    size_t num;\n    uint32_t lengths[16];\n\n    num = 0;\n    for (i = 0;i < 16;i++) {\n      if (flags & (1 << i))\n        num++;\n    }\n\n    if (len < (int32_t)(4 + 4*num))\n      throw protocol_error(\"Invalid extended clipboard message\");\n\n    num = 0;\n    for (i = 0;i < 16;i++) {\n      if (flags & (1 << i))\n        lengths[num++] = is->readU32();\n    }\n\n    handler->handleClipboardCaps(flags, lengths);\n  } else if (action == clipboardProvide) {\n    rdr::ZlibInStream zis;\n\n    int i;\n    size_t num;\n    size_t lengths[16];\n    uint8_t* buffers[16];\n\n    zis.setUnderlying(is, len - 4);\n\n    num = 0;\n    for (i = 0;i < 16;i++) {\n      if (!(flags & 1 << i))\n        continue;\n\n      if (!zis.hasData(4))\n        throw protocol_error(\"Extended clipboard decode error\");\n\n      lengths[num] = zis.readU32();\n\n      if (lengths[num] > (size_t)maxCutText) {\n        vlog.error(\"Extended clipboard data too long (%d bytes) - ignoring\",\n                   (unsigned)lengths[num]);\n\n        // Slowly (safely) drain away the data\n        while (lengths[num] > 0) {\n          size_t chunk;\n\n          if (!zis.hasData(1))\n            throw protocol_error(\"Extended clipboard decode error\");\n\n          chunk = zis.avail();\n          if (chunk > lengths[num])\n            chunk = lengths[num];\n\n          zis.skip(chunk);\n          lengths[num] -= chunk;\n        }\n\n        flags &= ~(1 << i);\n\n        continue;\n      }\n\n      if (!zis.hasData(lengths[num]))\n        throw protocol_error(\"Extended clipboard decode error\");\n\n      buffers[num] = new uint8_t[lengths[num]];\n      zis.readBytes(buffers[num], lengths[num]);\n      num++;\n    }\n\n    zis.flushUnderlying();\n    zis.setUnderlying(nullptr, 0);\n\n    handler->handleClipboardProvide(flags, lengths, buffers);\n\n    num = 0;\n    for (i = 0;i < 16;i++) {\n      if (!(flags & 1 << i))\n        continue;\n      delete [] buffers[num++];\n    }\n  } else {\n    switch (action) {\n    case clipboardRequest:\n      handler->handleClipboardRequest(flags);\n      break;\n    case clipboardPeek:\n      handler->handleClipboardPeek();\n      break;\n    case clipboardNotify:\n      handler->handleClipboardNotify(flags);\n      break;\n    default:\n      throw protocol_error(\"Invalid extended clipboard action\");\n    }\n  }\n\n  return true;\n}\n\nbool CMsgReader::readFence()\n{\n  uint32_t flags;\n  uint8_t len;\n  uint8_t data[64];\n\n  if (!is->hasData(3 + 4 + 1))\n    return false;\n\n  is->setRestorePoint();\n\n  is->skip(3);\n\n  flags = is->readU32();\n\n  len = is->readU8();\n\n  if (!is->hasDataOrRestore(len))\n    return false;\n  is->clearRestorePoint();\n\n  if (len > sizeof(data)) {\n    vlog.error(\"Ignoring fence with too large payload\");\n    is->skip(len);\n    return true;\n  }\n\n  is->readBytes(data, len);\n\n  handler->fence(flags, len, data);\n\n  return true;\n}\n\nbool CMsgReader::readEndOfContinuousUpdates()\n{\n  handler->endOfContinuousUpdates();\n  return true;\n}\n\nbool CMsgReader::readFramebufferUpdate()\n{\n  if (!is->hasData(1 + 2))\n    return false;\n\n  is->skip(1);\n  nUpdateRectsLeft = is->readU16();\n  handler->framebufferUpdateStart();\n\n  return true;\n}\n\nbool CMsgReader::readRect(const core::Rect& r, int encoding)\n{\n  if ((r.br.x > handler->server.width()) ||\n      (r.br.y > handler->server.height())) {\n    vlog.error(\"Rect too big: %dx%d at %d,%d exceeds %dx%d\",\n\t    r.width(), r.height(), r.tl.x, r.tl.y,\n            handler->server.width(), handler->server.height());\n    throw protocol_error(\"Rect too big\");\n  }\n\n  if (r.is_empty())\n    vlog.error(\"Zero size rect\");\n\n  return handler->dataRect(r, encoding);\n}\n\nbool CMsgReader::readSetXCursor(int width, int height,\n                                const core::Point& hotspot)\n{\n  if (width > maxCursorSize || height > maxCursorSize)\n    throw protocol_error(\"Too big cursor\");\n\n  std::vector<uint8_t> rgba(width*height*4);\n\n  if (width * height > 0) {\n    uint8_t pr, pg, pb;\n    uint8_t sr, sg, sb;\n    int data_len = ((width+7)/8) * height;\n    int mask_len = ((width+7)/8) * height;\n    std::vector<uint8_t> data(data_len);\n    std::vector<uint8_t> mask(mask_len);\n\n    int x, y;\n    uint8_t* out;\n\n    if (!is->hasData(3 + 3 + data_len + mask_len))\n      return false;\n\n    pr = is->readU8();\n    pg = is->readU8();\n    pb = is->readU8();\n\n    sr = is->readU8();\n    sg = is->readU8();\n    sb = is->readU8();\n\n    is->readBytes(data.data(), data.size());\n    is->readBytes(mask.data(), mask.size());\n\n    int maskBytesPerRow = (width+7)/8;\n    out = rgba.data();\n    for (y = 0;y < height;y++) {\n      for (x = 0;x < width;x++) {\n        int byte = y * maskBytesPerRow + x / 8;\n        int bit = 7 - x % 8;\n\n        if (data[byte] & (1 << bit)) {\n          out[0] = pr;\n          out[1] = pg;\n          out[2] = pb;\n        } else {\n          out[0] = sr;\n          out[1] = sg;\n          out[2] = sb;\n        }\n\n        if (mask[byte] & (1 << bit))\n          out[3] = 255;\n        else\n          out[3] = 0;\n\n        out += 4;\n      }\n    }\n  }\n\n  handler->setCursor(width, height, hotspot, rgba.data());\n\n  return true;\n}\n\nbool CMsgReader::readSetCursor(int width, int height,\n                               const core::Point& hotspot)\n{\n  if (width > maxCursorSize || height > maxCursorSize)\n    throw protocol_error(\"Too big cursor\");\n\n  int data_len = width * height * (handler->server.pf().bpp/8);\n  int mask_len = ((width+7)/8) * height;\n  std::vector<uint8_t> data(data_len);\n  std::vector<uint8_t> mask(mask_len);\n\n  int x, y;\n  std::vector<uint8_t> rgba(width*height*4);\n  uint8_t* in;\n  uint8_t* out;\n\n  if (!is->hasData(data_len + mask_len))\n    return false;\n\n  is->readBytes(data.data(), data.size());\n  is->readBytes(mask.data(), mask.size());\n\n  int maskBytesPerRow = (width+7)/8;\n  in = data.data();\n  out = rgba.data();\n  for (y = 0;y < height;y++) {\n    for (x = 0;x < width;x++) {\n      int byte = y * maskBytesPerRow + x / 8;\n      int bit = 7 - x % 8;\n\n      handler->server.pf().rgbFromBuffer(out, in, 1);\n\n      if (mask[byte] & (1 << bit))\n        out[3] = 255;\n      else\n        out[3] = 0;\n\n      in += handler->server.pf().bpp/8;\n      out += 4;\n    }\n  }\n\n  handler->setCursor(width, height, hotspot, rgba.data());\n\n  return true;\n}\n\nbool CMsgReader::readSetCursorWithAlpha(int width, int height,\n                                        const core::Point& hotspot)\n{\n  if (width > maxCursorSize || height > maxCursorSize)\n    throw protocol_error(\"Too big cursor\");\n\n  const PixelFormat rgbaPF(32, 32, false, true, 255, 255, 255, 16, 8, 0);\n  ManagedPixelBuffer pb(rgbaPF, width, height);\n  PixelFormat origPF;\n\n  bool ret;\n\n  uint8_t* buf;\n  int stride;\n\n  // We can't use restore points as the decoder likely wants to as well, so\n  // we need to keep track of the read encoding\n\n  if (cursorEncoding == -1) {\n    if (!is->hasData(4))\n      return false;\n\n    cursorEncoding = is->readS32();\n  }\n\n  origPF = handler->server.pf();\n  handler->server.setPF(rgbaPF);\n  ret = handler->readAndDecodeRect(pb.getRect(), cursorEncoding, &pb);\n  handler->server.setPF(origPF);\n\n  if (!ret)\n    return false;\n\n  cursorEncoding = -1;\n\n  // On-wire data has pre-multiplied alpha, but we store it\n  // non-pre-multiplied\n  buf = pb.getBufferRW(pb.getRect(), &stride);\n  assert(stride == width);\n\n  for (int i = 0;i < pb.area();i++) {\n    uint8_t alpha;\n\n    alpha = buf[3];\n    if (alpha == 0)\n      alpha = 1; // Avoid division by zero\n\n    buf[0] = (unsigned)buf[0] * 255/alpha;\n    buf[1] = (unsigned)buf[1] * 255/alpha;\n    buf[2] = (unsigned)buf[2] * 255/alpha;\n\n    buf += 4;\n  }\n\n  pb.commitBufferRW(pb.getRect());\n\n  handler->setCursor(width, height, hotspot,\n                     pb.getBuffer(pb.getRect(), &stride));\n\n  return true;\n}\n\nbool CMsgReader::readSetVMwareCursor(int width, int height,\n                                     const core::Point& hotspot)\n{\n  if (width > maxCursorSize || height > maxCursorSize)\n    throw protocol_error(\"Too big cursor\");\n\n  uint8_t type;\n\n  if (!is->hasData(1 + 1))\n    return false;\n\n  is->setRestorePoint();\n\n  type = is->readU8();\n  is->skip(1);\n\n  if (type == 0) {\n    int len = width * height * (handler->server.pf().bpp/8);\n    std::vector<uint8_t> andMask(len);\n    std::vector<uint8_t> xorMask(len);\n\n    std::vector<uint8_t> data(width*height*4);\n\n    uint8_t* andIn;\n    uint8_t* xorIn;\n    uint8_t* out;\n    int Bpp;\n\n    if (!is->hasDataOrRestore(len + len))\n      return false;\n    is->clearRestorePoint();\n\n    is->readBytes(andMask.data(), andMask.size());\n    is->readBytes(xorMask.data(), xorMask.size());\n\n    andIn = andMask.data();\n    xorIn = xorMask.data();\n    out = data.data();\n    Bpp = handler->server.pf().bpp/8;\n    for (int y = 0;y < height;y++) {\n      for (int x = 0;x < width;x++) {\n        Pixel andPixel, xorPixel;\n\n        andPixel = handler->server.pf().pixelFromBuffer(andIn);\n        xorPixel = handler->server.pf().pixelFromBuffer(xorIn);\n        andIn += Bpp;\n        xorIn += Bpp;\n\n        if (andPixel == 0) {\n          uint8_t r, g, b;\n\n          // Opaque pixel\n\n          handler->server.pf().rgbFromPixel(xorPixel, &r, &g, &b);\n          *out++ = r;\n          *out++ = g;\n          *out++ = b;\n          *out++ = 0xff;\n        } else if (xorPixel == 0) {\n          // Fully transparent pixel\n          *out++ = 0;\n          *out++ = 0;\n          *out++ = 0;\n          *out++ = 0;\n        } else if (andPixel == xorPixel) {\n          // Inverted pixel\n\n          // We don't really support this, so just turn the pixel black\n          // FIXME: Do an outline like WinVNC does?\n          *out++ = 0;\n          *out++ = 0;\n          *out++ = 0;\n          *out++ = 0xff;\n        } else {\n          // Partially transparent/inverted pixel\n\n          // We _really_ can't handle this, just make it black\n          *out++ = 0;\n          *out++ = 0;\n          *out++ = 0;\n          *out++ = 0xff;\n        }\n      }\n    }\n\n    handler->setCursor(width, height, hotspot, data.data());\n  } else if (type == 1) {\n    std::vector<uint8_t> data(width*height*4);\n\n    if (!is->hasDataOrRestore(width*height*4))\n      return false;\n    is->clearRestorePoint();\n\n    // FIXME: Is alpha premultiplied?\n    is->readBytes(data.data(), data.size());\n\n    handler->setCursor(width, height, hotspot, data.data());\n  } else {\n    throw protocol_error(\"Unknown cursor type\");\n  }\n\n  return true;\n}\n\nbool CMsgReader::readSetDesktopName(int x, int y, int w, int h)\n{\n  uint32_t len;\n\n  if (!is->hasData(4))\n    return false;\n\n  is->setRestorePoint();\n\n  len = is->readU32();\n\n  if (!is->hasDataOrRestore(len))\n    return false;\n  is->clearRestorePoint();\n\n  std::vector<char> name(len + 1);\n  is->readBytes((uint8_t*)name.data(), len);\n  name[len] = '\\0';\n\n  if (x || y || w || h) {\n    vlog.error(\"Ignoring DesktopName rect with non-zero position/size\");\n    return true;\n  }\n\n  if (!core::isValidUTF8(name.data())) {\n    vlog.error(\"Ignoring DesktopName rect with invalid UTF-8 sequence\");\n    return true;\n  }\n\n  handler->setName(name.data());\n\n  return true;\n}\n\nbool CMsgReader::readExtendedDesktopSize(int x, int y, int w, int h)\n{\n  unsigned int screens, i;\n  uint32_t id, flags;\n  int sx, sy, sw, sh;\n  ScreenSet layout;\n\n  if (!is->hasData(1 + 3))\n    return false;\n\n  is->setRestorePoint();\n\n  screens = is->readU8();\n  is->skip(3);\n\n  if (!is->hasDataOrRestore(16 * screens))\n    return false;\n  is->clearRestorePoint();\n\n  for (i = 0;i < screens;i++) {\n    id = is->readU32();\n    sx = is->readU16();\n    sy = is->readU16();\n    sw = is->readU16();\n    sh = is->readU16();\n    flags = is->readU32();\n\n    layout.add_screen(Screen(id, sx, sy, sw, sh, flags));\n  }\n\n  handler->setExtendedDesktopSize(x, y, w, h, layout);\n\n  return true;\n}\n\nbool CMsgReader::readLEDState()\n{\n  uint8_t ledState;\n\n  if (!is->hasData(1))\n    return false;\n\n  ledState = is->readU8();\n\n  handler->setLEDState(ledState);\n\n  return true;\n}\n\nbool CMsgReader::readVMwareLEDState()\n{\n  uint32_t ledState;\n\n  if (!is->hasData(4))\n    return false;\n\n  ledState = is->readU32();\n\n  // As luck has it, this extension uses the same bit definitions,\n  // so no conversion required\n\n  handler->setLEDState(ledState);\n\n  return true;\n}\n"
  },
  {
    "path": "common/rfb/CMsgReader.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// CMsgReader - class for reading RFB messages on the server side\n// (i.e. messages from client to server).\n//\n\n#ifndef __RFB_CMSGREADER_H__\n#define __RFB_CMSGREADER_H__\n\n#include <stdint.h>\n\n#include <core/Rect.h>\n\nnamespace rdr { class InStream; }\n\nnamespace rfb {\n\n  class CMsgHandler;\n\n  class CMsgReader {\n  public:\n    CMsgReader(CMsgHandler* handler, rdr::InStream* is);\n    virtual ~CMsgReader();\n\n    bool readServerInit();\n\n    // readMsg() reads a message, calling the handler as appropriate.\n    bool readMsg();\n\n    rdr::InStream* getInStream() { return is; }\n\n    int imageBufIdealSize;\n\n  protected:\n    bool readSetColourMapEntries();\n    bool readBell();\n    bool readServerCutText();\n    bool readExtendedClipboard(int32_t len);\n    bool readFence();\n    bool readEndOfContinuousUpdates();\n\n    bool readFramebufferUpdate();\n\n    bool readRect(const core::Rect& r, int encoding);\n\n    bool readSetXCursor(int width, int height,\n                        const core::Point& hotspot);\n    bool readSetCursor(int width, int height,\n                       const core::Point& hotspot);\n    bool readSetCursorWithAlpha(int width, int height,\n                                const core::Point& hotspot);\n    bool readSetVMwareCursor(int width, int height,\n                             const core::Point& hotspot);\n    bool readSetDesktopName(int x, int y, int w, int h);\n    bool readExtendedDesktopSize(int x, int y, int w, int h);\n    bool readLEDState();\n    bool readVMwareLEDState();\n\n  private:\n    CMsgHandler* handler;\n    rdr::InStream* is;\n\n    enum stateEnum {\n      MSGSTATE_IDLE,\n      MSGSTATE_MESSAGE,\n      MSGSTATE_RECT_HEADER,\n      MSGSTATE_RECT_DATA,\n    };\n\n    stateEnum state;\n\n    uint8_t currentMsgType;\n    int nUpdateRectsLeft;\n    core::Rect dataRect;\n    int rectEncoding;\n\n    int cursorEncoding;\n\n    static const int maxCursorSize = 256;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/CMsgWriter.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <assert.h>\n\n#include <core/Rect.h>\n#include <core/string.h>\n\n#include <rdr/OutStream.h>\n#include <rdr/MemOutStream.h>\n#include <rdr/ZlibOutStream.h>\n\n#include <rfb/msgTypes.h>\n#include <rfb/fenceTypes.h>\n#include <rfb/qemuTypes.h>\n#include <rfb/clipboardTypes.h>\n#include <rfb/PixelFormat.h>\n#include <rfb/ScreenSet.h>\n#include <rfb/ServerParams.h>\n#include <rfb/CMsgWriter.h>\n\nusing namespace rfb;\n\nCMsgWriter::CMsgWriter(ServerParams* server_, rdr::OutStream* os_)\n  : server(server_), os(os_)\n{\n}\n\nCMsgWriter::~CMsgWriter()\n{\n}\n\nvoid CMsgWriter::writeClientInit(bool shared)\n{\n  os->writeU8(shared);\n  endMsg();\n}\n\nvoid CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)\n{\n  startMsg(msgTypeSetPixelFormat);                                 \n  os->pad(3);\n  pf.write(os);\n  endMsg();\n}\n\nvoid CMsgWriter::writeSetEncodings(const std::list<uint32_t> encodings)\n{\n  startMsg(msgTypeSetEncodings);\n  os->pad(1);\n  os->writeU16(encodings.size());\n  for (uint32_t encoding : encodings)\n    os->writeU32(encoding);\n  endMsg();\n}\n\nvoid CMsgWriter::writeSetDesktopSize(int width, int height,\n                                     const ScreenSet& layout)\n{\n  if (!server->supportsSetDesktopSize)\n    throw std::logic_error(\"Server does not support SetDesktopSize\");\n\n  startMsg(msgTypeSetDesktopSize);\n  os->pad(1);\n\n  os->writeU16(width);\n  os->writeU16(height);\n\n  os->writeU8(layout.num_screens());\n  os->pad(1);\n\n  ScreenSet::const_iterator iter;\n  for (iter = layout.begin();iter != layout.end();++iter) {\n    os->writeU32(iter->id);\n    os->writeU16(iter->dimensions.tl.x);\n    os->writeU16(iter->dimensions.tl.y);\n    os->writeU16(iter->dimensions.width());\n    os->writeU16(iter->dimensions.height());\n    os->writeU32(iter->flags);\n  }\n\n  endMsg();\n}\n\nvoid CMsgWriter::writeFramebufferUpdateRequest(const core::Rect& r,\n                                               bool incremental)\n{\n  startMsg(msgTypeFramebufferUpdateRequest);\n  os->writeU8(incremental);\n  os->writeU16(r.tl.x);\n  os->writeU16(r.tl.y);\n  os->writeU16(r.width());\n  os->writeU16(r.height());\n  endMsg();\n}\n\nvoid CMsgWriter::writeEnableContinuousUpdates(bool enable,\n                                              int x, int y, int w, int h)\n{\n  if (!server->supportsContinuousUpdates)\n    throw std::logic_error(\"Server does not support continuous updates\");\n\n  startMsg(msgTypeEnableContinuousUpdates);\n\n  os->writeU8(!!enable);\n\n  os->writeU16(x);\n  os->writeU16(y);\n  os->writeU16(w);\n  os->writeU16(h);\n\n  endMsg();\n}\n\nvoid CMsgWriter::writeFence(uint32_t flags, unsigned len, const uint8_t data[])\n{\n  if (!server->supportsFence)\n    throw std::logic_error(\"Server does not support fences\");\n  if (len > 64)\n    throw std::out_of_range(\"Too large fence payload\");\n  if ((flags & ~fenceFlagsSupported) != 0)\n    throw std::invalid_argument(\"Unknown fence flags\");\n\n  startMsg(msgTypeClientFence);\n  os->pad(3);\n\n  os->writeU32(flags);\n\n  os->writeU8(len);\n  os->writeBytes(data, len);\n\n  endMsg();\n}\n\nvoid CMsgWriter::writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down)\n{\n  if (!server->supportsQEMUKeyEvent || !keycode) {\n    /* This event isn't meaningful without a valid keysym */\n    if (!keysym)\n      return;\n\n    startMsg(msgTypeKeyEvent);\n    os->writeU8(down);\n    os->pad(2);\n    os->writeU32(keysym);\n    endMsg();\n  } else {\n    startMsg(msgTypeQEMUClientMessage);\n    os->writeU8(qemuExtendedKeyEvent);\n    os->writeU16(down);\n    os->writeU32(keysym);\n    os->writeU32(keycode);\n    endMsg();\n  }\n}\n\n\nvoid CMsgWriter::writePointerEvent(const core::Point& pos,\n                                   uint16_t buttonMask)\n{\n  core::Point p(pos);\n  bool extendedMouseButtons;\n\n  if (p.x < 0) p.x = 0;\n  if (p.y < 0) p.y = 0;\n  if (p.x >= server->width()) p.x = server->width() - 1;\n  if (p.y >= server->height()) p.y = server->height() - 1;\n\n  /* The highest bit in buttonMask is never sent to the server */\n  assert(!(buttonMask & 0x8000));\n\n  /* Only send extended pointerEvent message when needed */\n  extendedMouseButtons = buttonMask & 0x7f80;\n\n  startMsg(msgTypePointerEvent);\n  if (server->supportsExtendedMouseButtons && extendedMouseButtons) {\n    int higherBits;\n    int lowerBits;\n\n    higherBits = (buttonMask  >> 7) & 0xff;\n    assert(!(higherBits & 0xfc)); /* Bits 2-7 are reserved */\n\n    lowerBits = buttonMask & 0x7f;\n    lowerBits |= 0x80; /* Set marker bit to 1 */\n\n    os->writeU8(lowerBits);\n    os->writeU16(p.x);\n    os->writeU16(p.y);\n    os->writeU8(higherBits);\n  } else {\n    /* Marker bit must be set to 0, otherwise the server might confuse\n     * the marker bit with the highest bit in a normal PointerEvent\n     * message.\n    */\n    buttonMask &= 0x7f;\n    os->writeU8(buttonMask);\n    os->writeU16(p.x);\n    os->writeU16(p.y);\n  }\n  endMsg();\n}\n\n\nvoid CMsgWriter::writeClientCutText(const char* str)\n{\n  if (strchr(str, '\\r') != nullptr)\n    throw std::invalid_argument(\"Invalid carriage return in clipboard data\");\n\n  std::string latin1(core::utf8ToLatin1(str));\n\n  startMsg(msgTypeClientCutText);\n  os->pad(3);\n  os->writeU32(latin1.size());\n  os->writeBytes((const uint8_t*)latin1.data(), latin1.size());\n  endMsg();\n}\n\nvoid CMsgWriter::writeClipboardCaps(uint32_t caps,\n                                    const uint32_t* lengths)\n{\n  size_t i, count;\n\n  if (!(server->clipboardFlags() & clipboardCaps))\n    throw std::logic_error(\"Server does not support clipboard \\\"caps\\\" action\");\n\n  count = 0;\n  for (i = 0;i < 16;i++) {\n    if (caps & (1 << i))\n      count++;\n  }\n\n  startMsg(msgTypeClientCutText);\n  os->pad(3);\n  os->writeS32(-(4 + 4 * count));\n\n  os->writeU32(caps | clipboardCaps);\n\n  count = 0;\n  for (i = 0;i < 16;i++) {\n    if (caps & (1 << i))\n      os->writeU32(lengths[count++]);\n  }\n\n  endMsg();\n}\n\nvoid CMsgWriter::writeClipboardRequest(uint32_t flags)\n{\n  if (!(server->clipboardFlags() & clipboardRequest))\n    throw std::logic_error(\"Server does not support clipboard \\\"request\\\" action\");\n\n  startMsg(msgTypeClientCutText);\n  os->pad(3);\n  os->writeS32(-4);\n  os->writeU32(flags | clipboardRequest);\n  endMsg();\n}\n\nvoid CMsgWriter::writeClipboardPeek(uint32_t flags)\n{\n  if (!(server->clipboardFlags() & clipboardPeek))\n    throw std::logic_error(\"Server does not support clipboard \\\"peek\\\" action\");\n\n  startMsg(msgTypeClientCutText);\n  os->pad(3);\n  os->writeS32(-4);\n  os->writeU32(flags | clipboardPeek);\n  endMsg();\n}\n\nvoid CMsgWriter::writeClipboardNotify(uint32_t flags)\n{\n  if (!(server->clipboardFlags() & clipboardNotify))\n    throw std::logic_error(\"Server does not support clipboard \\\"notify\\\" action\");\n\n  startMsg(msgTypeClientCutText);\n  os->pad(3);\n  os->writeS32(-4);\n  os->writeU32(flags | clipboardNotify);\n  endMsg();\n}\n\nvoid CMsgWriter::writeClipboardProvide(uint32_t flags,\n                                      const size_t* lengths,\n                                      const uint8_t* const* data)\n{\n  rdr::MemOutStream mos;\n  rdr::ZlibOutStream zos;\n\n  int i, count;\n\n  if (!(server->clipboardFlags() & clipboardProvide))\n    throw std::logic_error(\"Server does not support clipboard \\\"provide\\\" action\");\n\n  zos.setUnderlying(&mos);\n\n  count = 0;\n  for (i = 0;i < 16;i++) {\n    if (!(flags & (1 << i)))\n      continue;\n    zos.writeU32(lengths[count]);\n    zos.writeBytes(data[count], lengths[count]);\n    count++;\n  }\n\n  zos.flush();\n\n  startMsg(msgTypeClientCutText);\n  os->pad(3);\n  os->writeS32(-(4 + mos.length()));\n  os->writeU32(flags | clipboardProvide);\n  os->writeBytes(mos.data(), mos.length());\n  endMsg();\n}\n\nvoid CMsgWriter::startMsg(int type)\n{\n  os->writeU8(type);\n}\n\nvoid CMsgWriter::endMsg()\n{\n  os->flush();\n}\n"
  },
  {
    "path": "common/rfb/CMsgWriter.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// CMsgWriter - class for writing RFB messages on the server side.\n//\n\n#ifndef __RFB_CMSGWRITER_H__\n#define __RFB_CMSGWRITER_H__\n\n#include <list>\n\n#include <stdint.h>\n\nnamespace core {\n  struct Point;\n  struct Rect;\n}\n\nnamespace rdr { class OutStream; }\n\nnamespace rfb {\n\n  class PixelFormat;\n  class ServerParams;\n  struct ScreenSet;\n\n  class CMsgWriter {\n  public:\n    CMsgWriter(ServerParams* server, rdr::OutStream* os);\n    virtual ~CMsgWriter();\n\n    void writeClientInit(bool shared);\n\n    void writeSetPixelFormat(const PixelFormat& pf);\n    void writeSetEncodings(const std::list<uint32_t> encodings);\n    void writeSetDesktopSize(int width, int height, const ScreenSet& layout);\n\n    void writeFramebufferUpdateRequest(const core::Rect& r,\n                                       bool incremental);\n    void writeEnableContinuousUpdates(bool enable, int x, int y, int w, int h);\n\n    void writeFence(uint32_t flags, unsigned len, const uint8_t data[]);\n\n    void writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down);\n    void writePointerEvent(const core::Point& pos, uint16_t buttonMask);\n\n    void writeClientCutText(const char* str);\n\n    void writeClipboardCaps(uint32_t caps, const uint32_t* lengths);\n    void writeClipboardRequest(uint32_t flags);\n    void writeClipboardPeek(uint32_t flags);\n    void writeClipboardNotify(uint32_t flags);\n    void writeClipboardProvide(uint32_t flags, const size_t* lengths,\n                               const uint8_t* const* data);\n\n  protected:\n    void startMsg(int type);\n    void endMsg();\n\n    ServerParams* server;\n    rdr::OutStream* os;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/CSecurity.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// CSecurity - class on the client side for handling security handshaking.  A\n// derived class for a particular security type overrides the processMsg()\n// method.\n\n// processMsg() is called first when the security type has been decided on, and\n// will keep being called whenever there is data to read from the server.  It\n// should return false when it needs more data, or true when the security\n// handshaking is over and we are now waiting for the SecurityResult message\n// from the server.  In the event of failure a suitable exception should be\n// thrown.\n//\n// Note that the first time processMsg() is called, there is no guarantee that\n// there is any data to read from the CConnection's InStream, but subsequent\n// calls guarantee there is at least one byte which can be read without\n// blocking.\n//\n// description is a string describing the level of encryption applied to the\n// session, or null if no encryption will be used.\n\n#ifndef __RFB_CSECURITY_H__\n#define __RFB_CSECURITY_H__\n\nnamespace rfb {\n  class CConnection;\n  class CSecurity {\n  public:\n    CSecurity(CConnection* cc_) : cc(cc_) {}\n    virtual ~CSecurity() {}\n    virtual bool processMsg() = 0;\n    virtual int getType() const = 0;\n    virtual bool isSecure() const { return false; }\n\n  protected:\n    CConnection* cc;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/CSecurityDH.cxx",
    "content": "/* \n * Copyright (C) 2022 Dinglan Peng\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#ifndef HAVE_NETTLE\n#error \"This header should not be compiled without HAVE_NETTLE defined\"\n#endif\n\n#include <stdlib.h>\n#ifndef WIN32\n#include <unistd.h>\n#endif\n#include <assert.h>\n\n#include <nettle/aes.h>\n#include <nettle/md5.h>\n#include <nettle/bignum.h>\n#include <rfb/CSecurityDH.h>\n#include <rfb/CConnection.h>\n#include <rdr/InStream.h>\n#include <rdr/OutStream.h>\n#include <rdr/RandomStream.h>\n#include <rfb/Exception.h>\n\nusing namespace rfb;\n\nconst int MinKeyLength = 128;\nconst int MaxKeyLength = 1024;\n\nCSecurityDH::CSecurityDH(CConnection* cc_)\n  : CSecurity(cc_), keyLength(0)\n{\n  mpz_init(g);\n  mpz_init(p);\n  mpz_init(A);\n  mpz_init(b);\n  mpz_init(B);\n  mpz_init(k);\n}\n\nCSecurityDH::~CSecurityDH()\n{\n  mpz_clear(g);\n  mpz_clear(p);\n  mpz_clear(A);\n  mpz_clear(b);\n  mpz_clear(B);\n  mpz_clear(k);\n}\n\nbool CSecurityDH::processMsg()\n{\n  if (readKey()) {\n    writeCredentials();\n    return true;\n  }\n  return false;\n}\n\nbool CSecurityDH::readKey()\n{\n  rdr::InStream* is = cc->getInStream();\n  if (!is->hasData(4))\n    return false;\n  is->setRestorePoint();\n  uint16_t gen = is->readU16();\n  keyLength = is->readU16();\n  if (keyLength < MinKeyLength)\n    throw protocol_error(\"DH key is too short\");\n  if (keyLength > MaxKeyLength)\n    throw protocol_error(\"DH key is too long\");\n  if (!is->hasDataOrRestore(keyLength * 2))\n    return false;\n  is->clearRestorePoint();\n  mpz_set_ui(g, gen);\n  std::vector<uint8_t> pBytes(keyLength);\n  std::vector<uint8_t> ABytes(keyLength);\n  is->readBytes(pBytes.data(), pBytes.size());\n  is->readBytes(ABytes.data(), ABytes.size());\n  nettle_mpz_set_str_256_u(p, pBytes.size(), pBytes.data());\n  nettle_mpz_set_str_256_u(A, ABytes.size(), ABytes.data());\n  return true;\n}\n\nvoid CSecurityDH::writeCredentials()\n{\n  std::string username;\n  std::string password;\n  rdr::RandomStream rs;\n\n  cc->getUserPasswd(isSecure(), &username, &password);\n\n  std::vector<uint8_t> bBytes(keyLength);\n  if (!rs.hasData(keyLength))\n    throw std::runtime_error(\"Failed to generate DH private key\");\n  rs.readBytes(bBytes.data(), bBytes.size());\n  nettle_mpz_set_str_256_u(b, bBytes.size(), bBytes.data());\n  mpz_powm(k, A, b, p);\n  mpz_powm(B, g, b, p);\n\n  std::vector<uint8_t> sharedSecret(keyLength);\n  std::vector<uint8_t> BBytes(keyLength);\n  nettle_mpz_get_str_256(sharedSecret.size(), sharedSecret.data(), k);\n  nettle_mpz_get_str_256(BBytes.size(), BBytes.data(), B);\n  uint8_t key[16];\n  struct md5_ctx md5Ctx;\n  md5_init(&md5Ctx);\n  md5_update(&md5Ctx, sharedSecret.size(), sharedSecret.data());\n  md5_digest(&md5Ctx, 16, key);\n  struct aes128_ctx aesCtx;\n  aes128_set_encrypt_key(&aesCtx, key);\n\n  uint8_t buf[128];\n  if (!rs.hasData(128))\n    throw std::runtime_error(\"Failed to generate random padding\");\n  rs.readBytes(buf, 128);\n  if (username.size() >= 64)\n    throw std::out_of_range(\"Username is too long\");\n  memcpy(buf, username.c_str(), username.size() + 1);\n  if (password.size() >= 64)\n    throw std::out_of_range(\"Password is too long\");\n  memcpy(buf + 64, password.c_str(), password.size() + 1);\n  aes128_encrypt(&aesCtx, 128, buf, buf);\n\n  rdr::OutStream* os = cc->getOutStream();\n  os->writeBytes(buf, 128);\n  os->writeBytes(BBytes.data(), BBytes.size());\n  os->flush();\n}\n"
  },
  {
    "path": "common/rfb/CSecurityDH.h",
    "content": "/* \n * Copyright (C) 2022 Dinglan Peng\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __C_SECURITY_DH_H__\n#define __C_SECURITY_DH_H__\n\n#ifndef HAVE_NETTLE\n#error \"This header should not be compiled without HAVE_NETTLE defined\"\n#endif\n\n#include <nettle/bignum.h>\n#include <rfb/CSecurity.h>\n#include <rfb/Security.h>\n\nnamespace rfb {\n  class CSecurityDH : public CSecurity {\n  public:\n    CSecurityDH(CConnection* cc);\n    virtual ~CSecurityDH();\n    bool processMsg() override;\n    int getType() const override { return secTypeDH; }\n    bool isSecure() const override { return false; }\n\n  private:\n    bool readKey();\n    void writeCredentials();\n\n    int keyLength;\n    mpz_t g, p, A, b, B, k;\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/CSecurityMSLogonII.cxx",
    "content": "/* \n * Copyright (C) 2022 Dinglan Peng\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#ifndef HAVE_NETTLE\n#error \"This header should not be compiled without HAVE_NETTLE defined\"\n#endif\n\n#include <stdlib.h>\n#ifndef WIN32\n#include <unistd.h>\n#endif\n#include <assert.h>\n\n#include <nettle/des.h>\n#include <nettle/cbc.h>\n#include <nettle/bignum.h>\n#include <rfb/CSecurityMSLogonII.h>\n#include <rfb/CConnection.h>\n#include <rdr/InStream.h>\n#include <rdr/OutStream.h>\n#include <rdr/RandomStream.h>\n\nusing namespace rfb;\n\nCSecurityMSLogonII::CSecurityMSLogonII(CConnection* cc_)\n  : CSecurity(cc_)\n{\n  mpz_init(g);\n  mpz_init(p);\n  mpz_init(A);\n  mpz_init(b);\n  mpz_init(B);\n  mpz_init(k);\n}\n\nCSecurityMSLogonII::~CSecurityMSLogonII()\n{\n  mpz_clear(g);\n  mpz_clear(p);\n  mpz_clear(A);\n  mpz_clear(b);\n  mpz_clear(B);\n  mpz_clear(k);\n}\n\nbool CSecurityMSLogonII::processMsg()\n{\n  if (readKey()) {\n    writeCredentials();\n    return true;\n  }\n  return false;\n}\n\nbool CSecurityMSLogonII::readKey()\n{\n  rdr::InStream* is = cc->getInStream();\n  if (!is->hasData(24))\n    return false;\n  uint8_t gBytes[8];\n  uint8_t pBytes[8];\n  uint8_t ABytes[8];\n  is->readBytes(gBytes, 8);\n  is->readBytes(pBytes, 8);\n  is->readBytes(ABytes, 8);\n  nettle_mpz_set_str_256_u(g, 8, gBytes);\n  nettle_mpz_set_str_256_u(p, 8, pBytes);\n  nettle_mpz_set_str_256_u(A, 8, ABytes);\n  return true;\n}\n\nvoid CSecurityMSLogonII::writeCredentials()\n{\n  std::string username;\n  std::string password;\n  rdr::RandomStream rs;\n\n  cc->getUserPasswd(isSecure(), &username, &password);\n\n  std::vector<uint8_t> bBytes(8);\n  if (!rs.hasData(8))\n    throw std::runtime_error(\"Failed to generate DH private key\");\n  rs.readBytes(bBytes.data(), bBytes.size());\n  nettle_mpz_set_str_256_u(b, bBytes.size(), bBytes.data());\n  mpz_powm(k, A, b, p);\n  mpz_powm(B, g, b, p);\n\n  uint8_t key[8];\n  uint8_t reversedKey[8];\n  uint8_t BBytes[8];\n  uint8_t user[256];\n  uint8_t pass[64];\n  nettle_mpz_get_str_256(8, key, k);\n  nettle_mpz_get_str_256(8, BBytes, B);\n  for (int i = 0; i < 8; ++i) {\n    uint8_t x = 0;\n    for (int j = 0; j < 8; ++j) {\n      x |= ((key[i] >> j) & 1) << (7 - j);\n    }\n    reversedKey[i] = x;\n  }\n\n  if (!rs.hasData(256 + 64))\n    throw std::runtime_error(\"Failed to generate random padding\");\n  rs.readBytes(user, 256);\n  rs.readBytes(pass, 64);\n  if (username.size() >= 256)\n    throw std::out_of_range(\"Username is too long\");\n  memcpy(user, username.c_str(), username.size() + 1);\n  if (password.size() >= 64)\n    throw std::out_of_range(\"Password is too long\");\n  memcpy(pass, password.c_str(), password.size() + 1);\n\n  // DES-CBC with the original key as IV, and the reversed one as the DES key\n  struct CBC_CTX(struct des_ctx, DES_BLOCK_SIZE) ctx;\n  des_fix_parity(8, reversedKey, reversedKey);\n  des_set_key(&ctx.ctx, reversedKey);\n  CBC_SET_IV(&ctx, key);\n  CBC_ENCRYPT(&ctx, des_encrypt, 256, user, user);\n  CBC_SET_IV(&ctx, key);\n  CBC_ENCRYPT(&ctx, des_encrypt, 64, pass, pass);\n\n  rdr::OutStream* os = cc->getOutStream();\n  os->writeBytes(BBytes, 8);\n  os->writeBytes(user, 256);\n  os->writeBytes(pass, 64);\n  os->flush();\n}\n"
  },
  {
    "path": "common/rfb/CSecurityMSLogonII.h",
    "content": "/* \n * Copyright (C) 2022 Dinglan Peng\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __C_SECURITY_MSLOGONII_H__\n#define __C_SECURITY_MSLOGONII_H__\n\n#ifndef HAVE_NETTLE\n#error \"This header should not be compiled without HAVE_NETTLE defined\"\n#endif\n\n#include <nettle/bignum.h>\n#include <rfb/CSecurity.h>\n#include <rfb/Security.h>\n\nnamespace rfb {\n  class CSecurityMSLogonII : public CSecurity {\n  public:\n    CSecurityMSLogonII(CConnection* cc);\n    virtual ~CSecurityMSLogonII();\n    bool processMsg() override;\n    int getType() const override { return secTypeMSLogonII; }\n    bool isSecure() const override { return false; }\n\n  private:\n    bool readKey();\n    void writeCredentials();\n\n    mpz_t g, p, A, b, B, k;\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/CSecurityNone.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// CSecurityNone.h\n//\n\n#ifndef __CSECURITYNONE_H__\n#define __CSECURITYNONE_H__\n\n#include <rfb/Security.h>\n#include <rfb/CSecurity.h>\n\nnamespace rfb {\n\n  class CSecurityNone : public CSecurity {\n  public:\n    CSecurityNone(CConnection* cc_) : CSecurity(cc_) {}\n    bool processMsg() override { return true; }\n    int getType() const override {return secTypeNone;}\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/CSecurityPlain.cxx",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rfb/CConnection.h>\n#include <rfb/CSecurityPlain.h>\n\n#include <rdr/OutStream.h>\n\nusing namespace rfb;\n\nbool CSecurityPlain::processMsg()\n{\n   rdr::OutStream* os = cc->getOutStream();\n\n  std::string username;\n  std::string password;\n\n  cc->getUserPasswd(cc->isSecure(), &username, &password);\n\n  // Return the response to the server\n  os->writeU32(username.size());\n  os->writeU32(password.size());\n  os->writeBytes((const uint8_t*)username.data(), username.size());\n  os->writeBytes((const uint8_t*)password.data(), password.size());\n  os->flush();\n  return true;\n}\n"
  },
  {
    "path": "common/rfb/CSecurityPlain.h",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_CSECURITYPLAIN_H__\n#define __RFB_CSECURITYPLAIN_H__\n\n#include <rfb/CSecurity.h>\n#include <rfb/Security.h>\n\nnamespace rfb {\n\n  class CSecurityPlain : public CSecurity {\n  public:\n    CSecurityPlain(CConnection* cc_) : CSecurity(cc_) {}\n    bool processMsg() override;\n    int getType() const override { return secTypePlain; }\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/CSecurityRSAAES.cxx",
    "content": "/* \n * Copyright (C) 2022 Dinglan Peng\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#ifndef HAVE_NETTLE\n#error \"This header should not be compiled without HAVE_NETTLE defined\"\n#endif\n\n#include <stdlib.h>\n#ifndef WIN32\n#include <unistd.h>\n#endif\n#include <assert.h>\n\n#include <nettle/bignum.h>\n#include <nettle/sha1.h>\n#include <nettle/sha2.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb/CSecurityRSAAES.h>\n#include <rfb/CConnection.h>\n#include <rfb/Exception.h>\n\n#include <rdr/AESInStream.h>\n#include <rdr/AESOutStream.h>\n#include <rdr/RandomStream.h>\n\nenum {\n  ReadPublicKey,\n  ReadRandom,\n  ReadHash,\n  ReadSubtype,\n};\n\nconst int MinKeyLength = 1024;\nconst int MaxKeyLength = 8192;\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"CSecurityRSAAES\");\n\nCSecurityRSAAES::CSecurityRSAAES(CConnection* cc_, uint32_t _secType,\n                                 int _keySize, bool _isAllEncrypted)\n  : CSecurity(cc_), state(ReadPublicKey),\n    keySize(_keySize), isAllEncrypted(_isAllEncrypted), secType(_secType),\n    clientKey(), clientPublicKey(), serverKey(),\n    serverKeyN(nullptr), serverKeyE(nullptr),\n    clientKeyN(nullptr), clientKeyE(nullptr),\n    rais(nullptr), raos(nullptr), rawis(nullptr), rawos(nullptr)\n{\n  assert(keySize == 128 || keySize == 256);\n}\n\nCSecurityRSAAES::~CSecurityRSAAES()\n{\n  cleanup();\n}\n\nvoid CSecurityRSAAES::cleanup()\n{\n  if (raos) {\n    try {\n      if (raos->hasBufferedData()) {\n        raos->cork(false);\n        raos->flush();\n        if (raos->hasBufferedData())\n          vlog.error(\"Failed to flush remaining socket data on close\");\n      }\n    } catch (std::exception& e) {\n      vlog.error(\"Failed to flush remaining socket data on close: %s\", e.what());\n    }\n  }\n\n  if (serverKeyN)\n    delete[] serverKeyN;\n  if (serverKeyE)\n    delete[] serverKeyE;\n  if (clientKeyN)\n    delete[] clientKeyN;\n  if (clientKeyE)\n    delete[] clientKeyE;\n  if (clientKey.size)\n    rsa_private_key_clear(&clientKey);\n  if (clientPublicKey.size)\n    rsa_public_key_clear(&clientPublicKey);\n  if (serverKey.size)\n    rsa_public_key_clear(&serverKey);\n  if (isAllEncrypted && rawis && rawos)\n    cc->setStreams(rawis, rawos);\n  if (rais)\n    delete rais;\n  if (raos)\n    delete raos;\n}\n\nbool CSecurityRSAAES::processMsg()\n{\n  switch (state) {\n    case ReadPublicKey:\n      if (!readPublicKey())\n        return false;\n      verifyServer();\n      writePublicKey();\n      writeRandom();\n      state = ReadRandom;\n      /* fall through */\n    case ReadRandom:\n      if (!readRandom())\n        return false;\n      setCipher();\n      writeHash();\n      state = ReadHash;\n      /* fall through */\n    case ReadHash:\n      if (!readHash())\n        return false;\n      clearSecrets();\n      state = ReadSubtype;\n      /* fall through */\n    case ReadSubtype:\n      if (!readSubtype())\n        return false;\n      writeCredentials();\n      return true;\n  }\n\n  throw std::logic_error(\"Invalid state\");\n\n  return false;\n}\n\nstatic void random_func(void*, size_t length, uint8_t* dst)\n{\n  rdr::RandomStream rs;\n  if (!rs.hasData(length))\n    throw std::runtime_error(\"Failed to generate random\");\n  rs.readBytes(dst, length);\n}\n\nvoid CSecurityRSAAES::writePublicKey()\n{\n  rdr::OutStream* os = cc->getOutStream();\n  // generate client key\n  rsa_public_key_init(&clientPublicKey);\n  rsa_private_key_init(&clientKey);\n  // match the server key size\n  clientKeyLength = serverKeyLength;\n  int rsaKeySize = (clientKeyLength + 7) / 8;\n  // set key size to non-zero to allow clearing the keys when cleanup\n  clientPublicKey.size = rsaKeySize;\n  clientKey.size = rsaKeySize;\n  // set e = 65537\n  mpz_set_ui(clientPublicKey.e, 65537);\n  if (!rsa_generate_keypair(&clientPublicKey, &clientKey,\n                            nullptr, random_func, nullptr, nullptr,\n                            clientKeyLength, 0))\n    throw std::runtime_error(\"Failed to generate key\");\n  clientKeyN = new uint8_t[rsaKeySize];\n  clientKeyE = new uint8_t[rsaKeySize];\n  nettle_mpz_get_str_256(rsaKeySize, clientKeyN, clientPublicKey.n);\n  nettle_mpz_get_str_256(rsaKeySize, clientKeyE, clientPublicKey.e);\n  os->writeU32(clientKeyLength);\n  os->writeBytes(clientKeyN, rsaKeySize);\n  os->writeBytes(clientKeyE, rsaKeySize);\n  os->flush();\n}\n\nbool CSecurityRSAAES::readPublicKey()\n{\n  rdr::InStream* is = cc->getInStream();\n  if (!is->hasData(4))\n    return false;\n  is->setRestorePoint();\n  serverKeyLength = is->readU32();\n  if (serverKeyLength < MinKeyLength)\n    throw protocol_error(\"Server key is too short\");\n  if (serverKeyLength > MaxKeyLength)\n    throw protocol_error(\"Server key is too long\");\n  size_t size = (serverKeyLength + 7) / 8;\n  if (!is->hasDataOrRestore(size * 2))\n    return false;\n  is->clearRestorePoint();\n  serverKeyE = new uint8_t[size];\n  serverKeyN = new uint8_t[size];\n  is->readBytes(serverKeyN, size);\n  is->readBytes(serverKeyE, size);\n  rsa_public_key_init(&serverKey);\n  nettle_mpz_set_str_256_u(serverKey.n, size, serverKeyN);\n  nettle_mpz_set_str_256_u(serverKey.e, size, serverKeyE);\n  if (!rsa_public_key_prepare(&serverKey))\n    throw protocol_error(\"Server key is invalid\");\n  return true;\n}\n\nvoid CSecurityRSAAES::verifyServer()\n{\n  uint8_t lenServerKey[4] = {\n    (uint8_t)((serverKeyLength & 0xff000000) >> 24),\n    (uint8_t)((serverKeyLength & 0xff0000) >> 16),\n    (uint8_t)((serverKeyLength & 0xff00) >> 8),\n    (uint8_t)(serverKeyLength & 0xff)\n  };\n  uint8_t f[8];\n  struct sha1_ctx ctx;\n  sha1_init(&ctx);\n  sha1_update(&ctx, 4, lenServerKey);\n  sha1_update(&ctx, serverKey.size, serverKeyN);\n  sha1_update(&ctx, serverKey.size, serverKeyE);\n  sha1_digest(&ctx, sizeof(f), f);\n  const char *title = \"Server key fingerprint\";\n  std::string text = core::format(\n    \"The server has provided the following identifying information:\\n\"\n    \"Fingerprint: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\\n\"\n    \"Please verify that the information is correct and press \\\"Yes\\\". \"\n    \"Otherwise press \\\"No\\\"\", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]);\n  if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, title, text.c_str()))\n    throw auth_cancelled();\n}\n\nvoid CSecurityRSAAES::writeRandom()\n{\n  rdr::RandomStream rs;\n  rdr::OutStream* os = cc->getOutStream();\n  if (!rs.hasData(keySize / 8))\n    throw std::runtime_error(\"Failed to generate random\");\n  rs.readBytes(clientRandom, keySize / 8);\n  mpz_t x;\n  mpz_init(x);\n  int res;\n  try {\n    res = rsa_encrypt(&serverKey, &rs, random_func, keySize / 8,\n                      clientRandom, x);\n  } catch (...) {\n    mpz_clear(x);\n    throw;\n  }\n  if (!res) {\n    mpz_clear(x);\n    throw std::runtime_error(\"Failed to encrypt random\");\n  }\n  uint8_t* buffer = new uint8_t[serverKey.size];\n  nettle_mpz_get_str_256(serverKey.size, buffer, x);\n  mpz_clear(x);\n  os->writeU16(serverKey.size);\n  os->writeBytes(buffer, serverKey.size);\n  os->flush();\n  delete[] buffer;\n}\n\nbool CSecurityRSAAES::readRandom()\n{\n  rdr::InStream* is = cc->getInStream();\n  if (!is->hasData(2))\n    return false;\n  is->setRestorePoint();\n  size_t size = is->readU16();\n  if (size != clientKey.size)\n    throw protocol_error(\"Client key length doesn't match\");\n  if (!is->hasDataOrRestore(size))\n    return false;\n  is->clearRestorePoint();\n  uint8_t* buffer = new uint8_t[size];\n  is->readBytes(buffer, size);\n  size_t randomSize = keySize / 8;\n  mpz_t x;\n  nettle_mpz_init_set_str_256_u(x, size, buffer);\n  delete[] buffer;\n  if (!rsa_decrypt(&clientKey, &randomSize, serverRandom, x) ||\n      randomSize != (size_t)keySize / 8) {\n    mpz_clear(x);\n    throw protocol_error(\"Failed to decrypt server random\");\n  }\n  mpz_clear(x);\n  return true;\n}\n\nvoid CSecurityRSAAES::setCipher()\n{\n  rawis = cc->getInStream();\n  rawos = cc->getOutStream();\n  uint8_t key[32];\n  if (keySize == 128) {\n    struct sha1_ctx ctx;\n    sha1_init(&ctx);\n    sha1_update(&ctx, 16, clientRandom);\n    sha1_update(&ctx, 16, serverRandom);\n    sha1_digest(&ctx, 16, key);\n    rais = new rdr::AESInStream(rawis, key, 128);\n    sha1_init(&ctx);\n    sha1_update(&ctx, 16, serverRandom);\n    sha1_update(&ctx, 16, clientRandom);\n    sha1_digest(&ctx, 16, key);\n    raos = new rdr::AESOutStream(rawos, key, 128);\n  } else {\n    struct sha256_ctx ctx;\n    sha256_init(&ctx);\n    sha256_update(&ctx, 32, clientRandom);\n    sha256_update(&ctx, 32, serverRandom);\n    sha256_digest(&ctx, 32, key);\n    rais = new rdr::AESInStream(rawis, key, 256);\n    sha256_init(&ctx);\n    sha256_update(&ctx, 32, serverRandom);\n    sha256_update(&ctx, 32, clientRandom);\n    sha256_digest(&ctx, 32, key);\n    raos = new rdr::AESOutStream(rawos, key, 256);\n  }\n  if (isAllEncrypted)\n    cc->setStreams(rais, raos);\n}\n\nvoid CSecurityRSAAES::writeHash()\n{\n  uint8_t hash[32];\n  size_t len = serverKeyLength;\n  uint8_t lenServerKey[4] = {\n    (uint8_t)((len & 0xff000000) >> 24),\n    (uint8_t)((len & 0xff0000) >> 16),\n    (uint8_t)((len & 0xff00) >> 8),\n    (uint8_t)(len & 0xff)\n  };\n  len = clientKeyLength;\n  uint8_t lenClientKey[4] = {\n    (uint8_t)((len & 0xff000000) >> 24),\n    (uint8_t)((len & 0xff0000) >> 16),\n    (uint8_t)((len & 0xff00) >> 8),\n    (uint8_t)(len & 0xff)\n  };\n  int hashSize;\n  if (keySize == 128) {\n    hashSize = 20;\n    struct sha1_ctx ctx;\n    sha1_init(&ctx);\n    sha1_update(&ctx, 4, lenClientKey);\n    sha1_update(&ctx, clientKey.size, clientKeyN);\n    sha1_update(&ctx, clientKey.size, clientKeyE);\n    sha1_update(&ctx, 4, lenServerKey);\n    sha1_update(&ctx, serverKey.size, serverKeyN);\n    sha1_update(&ctx, serverKey.size, serverKeyE);\n    sha1_digest(&ctx, hashSize, hash);\n  } else {\n    hashSize = 32;\n    struct sha256_ctx ctx;\n    sha256_init(&ctx);\n    sha256_update(&ctx, 4, lenClientKey);\n    sha256_update(&ctx, clientKey.size, clientKeyN);\n    sha256_update(&ctx, clientKey.size, clientKeyE);\n    sha256_update(&ctx, 4, lenServerKey);\n    sha256_update(&ctx, serverKey.size, serverKeyN);\n    sha256_update(&ctx, serverKey.size, serverKeyE);\n    sha256_digest(&ctx, hashSize, hash);\n  }\n  raos->writeBytes(hash, hashSize);\n  raos->flush();\n}\n\nbool CSecurityRSAAES::readHash()\n{\n  uint8_t hash[32];\n  uint8_t realHash[32];\n  int hashSize = keySize == 128 ? 20 : 32;\n  if (!rais->hasData(hashSize))\n    return false;\n  rais->readBytes(hash, hashSize);\n  size_t len = serverKeyLength;\n  uint8_t lenServerKey[4] = {\n    (uint8_t)((len & 0xff000000) >> 24),\n    (uint8_t)((len & 0xff0000) >> 16),\n    (uint8_t)((len & 0xff00) >> 8),\n    (uint8_t)(len & 0xff)\n  };\n  len = clientKeyLength;\n  uint8_t lenClientKey[4] = {\n    (uint8_t)((len & 0xff000000) >> 24),\n    (uint8_t)((len & 0xff0000) >> 16),\n    (uint8_t)((len & 0xff00) >> 8),\n    (uint8_t)(len & 0xff)\n  };\n  if (keySize == 128) {\n    struct sha1_ctx ctx;\n    sha1_init(&ctx);\n    sha1_update(&ctx, 4, lenServerKey);\n    sha1_update(&ctx, serverKey.size, serverKeyN);\n    sha1_update(&ctx, serverKey.size, serverKeyE);\n    sha1_update(&ctx, 4, lenClientKey);\n    sha1_update(&ctx, clientKey.size, clientKeyN);\n    sha1_update(&ctx, clientKey.size, clientKeyE);\n    sha1_digest(&ctx, hashSize, realHash);\n  } else {\n    struct sha256_ctx ctx;\n    sha256_init(&ctx);\n    sha256_update(&ctx, 4, lenServerKey);\n    sha256_update(&ctx, serverKey.size, serverKeyN);\n    sha256_update(&ctx, serverKey.size, serverKeyE);\n    sha256_update(&ctx, 4, lenClientKey);\n    sha256_update(&ctx, clientKey.size, clientKeyN);\n    sha256_update(&ctx, clientKey.size, clientKeyE);\n    sha256_digest(&ctx, hashSize, realHash);\n  }\n  if (memcmp(hash, realHash, hashSize) != 0)\n    throw protocol_error(\"Hash doesn't match\");\n  return true;\n}\n\nvoid CSecurityRSAAES::clearSecrets()\n{\n  rsa_private_key_clear(&clientKey);\n  rsa_public_key_clear(&clientPublicKey);\n  rsa_public_key_clear(&serverKey);\n  clientKey.size = 0;\n  clientPublicKey.size = 0;\n  serverKey.size = 0;\n  delete[] serverKeyN;\n  delete[] serverKeyE;\n  delete[] clientKeyN;\n  delete[] clientKeyE;\n  serverKeyN = nullptr;\n  serverKeyE = nullptr;\n  clientKeyN = nullptr;\n  clientKeyE = nullptr;\n  memset(serverRandom, 0, sizeof(serverRandom));\n  memset(clientRandom, 0, sizeof(clientRandom));\n}\n\nbool CSecurityRSAAES::readSubtype()\n{\n  if (!rais->hasData(1))\n    return false;\n  subtype = rais->readU8();\n  if (subtype != secTypeRA2UserPass && subtype != secTypeRA2Pass)\n    throw protocol_error(\"Unknown RSA-AES subtype\");\n  return true;\n}\n\nvoid CSecurityRSAAES::writeCredentials()\n{\n  std::string username;\n  std::string password;\n\n  if (subtype == secTypeRA2UserPass)\n    cc->getUserPasswd(isSecure(), &username, &password);\n  else\n    cc->getUserPasswd(isSecure(), nullptr, &password);\n\n  if (subtype == secTypeRA2UserPass) {\n    if (username.size() > 255)\n      throw std::out_of_range(\"Username is too long\");\n    raos->writeU8(username.size());\n    raos->writeBytes((const uint8_t*)username.data(), username.size());\n  } else {\n    raos->writeU8(0);\n  }\n\n  if (password.size() > 255)\n    throw std::out_of_range(\"Password is too long\");\n  raos->writeU8(password.size());\n  raos->writeBytes((const uint8_t*)password.data(), password.size());\n  raos->flush();\n}\n"
  },
  {
    "path": "common/rfb/CSecurityRSAAES.h",
    "content": "/* \n * Copyright (C) 2022 Dinglan Peng\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __C_SECURITY_RSAAES_H__\n#define __C_SECURITY_RSAAES_H__\n\n#ifndef HAVE_NETTLE\n#error \"This header should not be compiled without HAVE_NETTLE defined\"\n#endif\n\n#include <nettle/rsa.h>\n\n#include <rfb/CSecurity.h>\n#include <rfb/Security.h>\n\nnamespace core { class IntParameter; }\n\nnamespace rdr {\n  class InStream;\n  class OutStream;\n  class AESInStream;\n  class AESOutStream;\n}\n\nnamespace rfb {\n\n  class CSecurityRSAAES : public CSecurity {\n  public:\n    CSecurityRSAAES(CConnection* cc, uint32_t secType,\n                    int keySize, bool isAllEncrypted);\n    virtual ~CSecurityRSAAES();\n    bool processMsg() override;\n    int getType() const override { return secType; }\n    bool isSecure() const override { return secType == secTypeRA256; }\n\n    static core::IntParameter RSAKeyLength;\n\n  private:\n    void cleanup();\n    void writePublicKey();\n    bool readPublicKey();\n    void verifyServer();\n    void writeRandom();\n    bool readRandom();\n    void setCipher();\n    void writeHash();\n    bool readHash();\n    void clearSecrets();\n    bool readSubtype();\n    void writeCredentials();\n\n    int state;\n    int keySize;\n    bool isAllEncrypted;\n    uint32_t secType;\n    uint8_t subtype;\n    struct rsa_private_key clientKey;\n    struct rsa_public_key clientPublicKey;\n    struct rsa_public_key serverKey;\n    uint32_t serverKeyLength;\n    uint8_t* serverKeyN;\n    uint8_t* serverKeyE;\n    uint32_t clientKeyLength;\n    uint8_t* clientKeyN;\n    uint8_t* clientKeyE;\n    uint8_t serverRandom[32];\n    uint8_t clientRandom[32];\n\n    rdr::AESInStream* rais;\n    rdr::AESOutStream* raos;\n\n    rdr::InStream* rawis;\n    rdr::OutStream* rawos;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/CSecurityStack.cxx",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rfb/CSecurityStack.h>\n\nusing namespace rfb;\n\nCSecurityStack::CSecurityStack(CConnection* cc_, int Type,\n                               CSecurity* s0, CSecurity* s1)\n  : CSecurity(cc_), type(Type)\n{\n  state = 0;\n  state0 = s0;\n  state1 = s1;\n}\n\nCSecurityStack::~CSecurityStack()\n{\n  delete state0;\n  delete state1;\n}\n\nbool CSecurityStack::processMsg()\n{\n  bool res=true;\n  if (state == 0) {\n    if (state0)\n      res = state0->processMsg();\n\n    if (!res)\n      return res;\n\n    state++;\n  }\n\n  if (state == 1) {\n    if(state1)\n      res = state1->processMsg();\n\n    if(!res)\n      return res;\n\n    state++;\n  }\n\n  return res;\n}\n\nbool CSecurityStack::isSecure() const\n{\n  if (state0 && state0->isSecure())\n    return true;\n  if (state == 1 && state1 && state1->isSecure())\n    return true;\n  return false;\n}\n"
  },
  {
    "path": "common/rfb/CSecurityStack.h",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_CSECURITYSTACK_H__\n#define __RFB_CSECURITYSTACK_H__\n\n#include <rfb/CSecurity.h>\n\nnamespace rfb {\n\n  class CSecurityStack : public CSecurity {\n  public:\n    CSecurityStack(CConnection* cc, int Type,\n                   CSecurity* s0 = nullptr, CSecurity* s1 = nullptr);\n    ~CSecurityStack();\n    bool processMsg() override;\n    int getType() const override {return type;};\n    bool isSecure() const override;\n  protected:\n    int state;\n    CSecurity* state0;\n    CSecurity* state1;\n    int type;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/CSecurityTLS.cxx",
    "content": "/*\n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2010 m-privacy GmbH\n * Copyright 2012-2025 Pierre Ossman for Cendio AB\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#ifndef HAVE_GNUTLS\n#error \"This header should not be compiled without HAVE_GNUTLS defined\"\n#endif\n\n#include <stdlib.h>\n#ifndef WIN32\n#include <unistd.h>\n#endif\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n#include <core/xdgdirs.h>\n\n#include <rfb/CSecurityTLS.h>\n#include <rfb/CConnection.h>\n#include <rfb/Exception.h>\n\n#include <rdr/TLSException.h>\n#include <rdr/TLSSocket.h>\n\n#include <gnutls/x509.h>\n\nusing namespace rfb;\n\nstatic const char* configdirfn(const char* fn);\n\ncore::StringParameter CSecurityTLS::X509CA(\"X509CA\", \"X509 CA certificate\",\n                                           configdirfn(\"x509_ca.pem\"));\ncore::StringParameter CSecurityTLS::X509CRL(\"X509CRL\", \"X509 CRL file\",\n                                            configdirfn(\"x509_crl.pem\"));\n\nstatic core::LogWriter vlog(\"TLS\");\n\nstatic const char* configdirfn(const char* fn)\n{\n  static char full_path[PATH_MAX];\n  const char* configdir;\n\n  configdir = core::getvncconfigdir();\n  if (configdir == nullptr)\n    return \"\";\n\n  snprintf(full_path, sizeof(full_path), \"%s/%s\", configdir, fn);\n  return full_path;\n}\n\nCSecurityTLS::CSecurityTLS(CConnection* cc_, bool _anon)\n  : CSecurity(cc_), session(nullptr),\n    anon_cred(nullptr), cert_cred(nullptr),\n    anon(_anon), tlssock(nullptr),\n    rawis(nullptr), rawos(nullptr)\n{\n  int err = gnutls_global_init();\n  if (err != GNUTLS_E_SUCCESS)\n    throw rdr::tls_error(\"gnutls_global_init()\", err);\n}\n\nvoid CSecurityTLS::shutdown()\n{\n  if (tlssock)\n    tlssock->shutdown();\n\n  if (anon_cred) {\n    gnutls_anon_free_client_credentials(anon_cred);\n    anon_cred = nullptr;\n  }\n\n  if (cert_cred) {\n    gnutls_certificate_free_credentials(cert_cred);\n    cert_cred = nullptr;\n  }\n\n  if (rawis && rawos) {\n    cc->setStreams(rawis, rawos);\n    rawis = nullptr;\n    rawos = nullptr;\n  }\n\n  if (tlssock) {\n    delete tlssock;\n    tlssock = nullptr;\n  }\n\n  if (session) {\n    gnutls_deinit(session);\n    session = nullptr;\n  }\n}\n\n\nCSecurityTLS::~CSecurityTLS()\n{\n  shutdown();\n\n  gnutls_global_deinit();\n}\n\nbool CSecurityTLS::processMsg()\n{\n  rdr::InStream* is = cc->getInStream();\n  rdr::OutStream* os = cc->getOutStream();\n  client = cc;\n\n  if (!session) {\n    int ret;\n\n    if (!is->hasData(1))\n      return false;\n\n    if (is->readU8() == 0)\n      throw protocol_error(\"Server failed to initialize TLS session\");\n\n    ret = gnutls_init(&session, GNUTLS_CLIENT);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_init()\", ret);\n\n    ret = gnutls_set_default_priority(session);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_set_default_priority()\", ret);\n\n    setParam();\n\n    tlssock = new rdr::TLSSocket(is, os, session);\n\n    rawis = is;\n    rawos = os;\n  }\n\n  try {\n    if (!tlssock->handshake())\n      return false;\n  } catch (std::exception&) {\n    shutdown();\n    throw;\n  }\n\n  vlog.debug(\"TLS handshake completed with %s\",\n             gnutls_session_get_desc(session));\n\n  checkSession();\n\n  cc->setStreams(&tlssock->inStream(), &tlssock->outStream());\n\n  return true;\n}\n\nvoid CSecurityTLS::setParam()\n{\n  static const char kx_anon_priority[] = \"+ANON-ECDH:+ANON-DH\";\n\n  int ret;\n\n  // Custom priority string specified?\n  if (strcmp(Security::GnuTLSPriority, \"\") != 0) {\n    std::string prio;\n    const char *err;\n\n    prio = (const char*)Security::GnuTLSPriority;\n    if (anon) {\n      prio += \":\";\n      prio += kx_anon_priority;\n    }\n\n    ret = gnutls_priority_set_direct(session, prio.c_str(), &err);\n    if (ret != GNUTLS_E_SUCCESS) {\n      if (ret == GNUTLS_E_INVALID_REQUEST)\n        vlog.error(\"GnuTLS priority syntax error at: %s\", err);\n      throw rdr::tls_error(\"gnutls_set_priority_direct()\", ret);\n    }\n  } else if (anon) {\n    const char *err;\n\n#if GNUTLS_VERSION_NUMBER >= 0x030603\n    ret = gnutls_set_default_priority_append(session, kx_anon_priority, &err, 0);\n    if (ret != GNUTLS_E_SUCCESS) {\n      if (ret == GNUTLS_E_INVALID_REQUEST)\n        vlog.error(\"GnuTLS priority syntax error at: %s\", err);\n      throw rdr::tls_error(\"gnutls_set_default_priority_append()\", ret);\n    }\n#else\n    std::string prio;\n\n    // We don't know what the system default priority is, so we guess\n    // it's what upstream GnuTLS has\n    prio = \"NORMAL\";\n    prio += \":\";\n    prio += kx_anon_priority;\n\n    ret = gnutls_priority_set_direct(session, prio.c_str(), &err);\n    if (ret != GNUTLS_E_SUCCESS) {\n      if (ret == GNUTLS_E_INVALID_REQUEST)\n        vlog.error(\"GnuTLS priority syntax error at: %s\", err);\n      throw rdr::tls_error(\"gnutls_set_priority_direct()\", ret);\n    }\n#endif\n  }\n\n  if (anon) {\n    ret = gnutls_anon_allocate_client_credentials(&anon_cred);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_anon_allocate_client_credentials()\", ret);\n\n    ret = gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_credentials_set()\", ret);\n\n    vlog.debug(\"Anonymous session has been set\");\n  } else {\n    const char* hostname;\n    size_t len;\n    bool valid;\n\n    ret = gnutls_certificate_allocate_credentials(&cert_cred);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_certificate_allocate_credentials()\", ret);\n\n    if (gnutls_certificate_set_x509_system_trust(cert_cred) < 1)\n      vlog.error(\"Could not load system certificate trust store\");\n\n    if (gnutls_certificate_set_x509_trust_file(cert_cred, X509CA, GNUTLS_X509_FMT_PEM) < 0)\n      vlog.error(\"Could not load user specified certificate authority\");\n\n    if (gnutls_certificate_set_x509_crl_file(cert_cred, X509CRL, GNUTLS_X509_FMT_PEM) < 0)\n      vlog.error(\"Could not load user specified certificate revocation list\");\n\n    ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_credentials_set()\", ret);\n\n    // Only DNS hostnames are allowed, and some servers will reject the\n    // connection if we provide anything else (e.g. an IPv6 address)\n    hostname = client->getServerName();\n    len = strlen(hostname);\n    valid = true;\n    for (size_t i = 0; i < len; i++) {\n      if (!isalnum(hostname[i]) && hostname[i] != '.')\n        valid = false;\n    }\n\n    if (valid) {\n      if (gnutls_server_name_set(session, GNUTLS_NAME_DNS,\n                                 client->getServerName(),\n                                 strlen(client->getServerName())) != GNUTLS_E_SUCCESS)\n        vlog.error(\"Failed to configure the server name for TLS handshake\");\n    }\n\n    vlog.debug(\"X509 session has been set\");\n  }\n}\n\nvoid CSecurityTLS::checkSession()\n{\n  const unsigned allowed_errors = GNUTLS_CERT_INVALID |\n\t\t\t\t  GNUTLS_CERT_SIGNER_NOT_FOUND |\n\t\t\t\t  GNUTLS_CERT_SIGNER_NOT_CA |\n\t\t\t\t  GNUTLS_CERT_NOT_ACTIVATED |\n\t\t\t\t  GNUTLS_CERT_EXPIRED |\n\t\t\t\t  GNUTLS_CERT_INSECURE_ALGORITHM;\n  unsigned int status;\n  const gnutls_datum_t *cert_list;\n  unsigned int cert_list_size = 0;\n  int err, known;\n  bool hostname_match;\n\n  const char *hostsDir;\n  gnutls_datum_t info;\n  size_t len;\n\n  if (anon)\n    return;\n\n  if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) {\n    gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                      GNUTLS_A_UNSUPPORTED_CERTIFICATE);\n    throw protocol_error(\"Unsupported certificate type\");\n  }\n\n  err = gnutls_certificate_verify_peers2(session, &status);\n  if (err != 0) {\n    vlog.error(\"Server certificate verification failed: %s\", gnutls_strerror(err));\n    gnutls_alert_send_appropriate(session, err);\n    throw rdr::tls_error(\"Server certificate verification()\", err);\n  }\n\n  if (status != 0) {\n    gnutls_datum_t status_str;\n    unsigned int fatal_status;\n\n    fatal_status = status & (~allowed_errors);\n\n    if (fatal_status != 0) {\n      std::string error;\n\n      err = gnutls_certificate_verification_status_print(fatal_status,\n                                                         GNUTLS_CRT_X509,\n                                                         &status_str,\n                                                         0);\n      if (err != GNUTLS_E_SUCCESS) {\n        gnutls_alert_send_appropriate(session, err);\n        throw rdr::tls_error(\"Failed to get certificate error description\", err);\n      }\n\n      error = (const char*)status_str.data;\n\n      gnutls_free(status_str.data);\n\n      gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                        GNUTLS_A_BAD_CERTIFICATE);\n      throw protocol_error(\n        core::format(\"Invalid server certificate: %s\", error.c_str()));\n    }\n\n    err = gnutls_certificate_verification_status_print(status,\n                                                       GNUTLS_CRT_X509,\n                                                       &status_str,\n                                                       0);\n    if (err != GNUTLS_E_SUCCESS) {\n      gnutls_alert_send_appropriate(session, err);\n      throw rdr::tls_error(\"Failed to get certificate error description\", err);\n    }\n\n    vlog.info(\"Server certificate errors: %s\", status_str.data);\n\n    gnutls_free(status_str.data);\n  }\n\n  /* Process overridable errors later */\n\n  cert_list = gnutls_certificate_get_peers(session, &cert_list_size);\n  if (!cert_list_size) {\n    gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                      GNUTLS_A_UNSUPPORTED_CERTIFICATE);\n    throw protocol_error(\"Empty certificate chain\");\n  }\n\n  /* Process only server's certificate, not issuer's certificate */\n  gnutls_x509_crt_t crt;\n  gnutls_x509_crt_init(&crt);\n\n  err = gnutls_x509_crt_import(crt, &cert_list[0], GNUTLS_X509_FMT_DER);\n  if (err != GNUTLS_E_SUCCESS) {\n    gnutls_alert_send_appropriate(session, err);\n    throw rdr::tls_error(\"Failed to decode server certificate\", err);\n  }\n\n  if (gnutls_x509_crt_check_hostname(crt, client->getServerName()) == 0) {\n    vlog.info(\"Server certificate doesn't match given server name\");\n    hostname_match = false;\n  } else {\n    hostname_match = true;\n  }\n\n  if ((status == 0) && hostname_match) {\n    /* Everything is fine (hostname + verification) */\n    gnutls_x509_crt_deinit(crt);\n    return;\n  }\n\n  /* Certificate has some user overridable problems, so TOFU time */\n\n  hostsDir = core::getvncstatedir();\n  if (hostsDir == nullptr) {\n    throw std::runtime_error(\"Could not obtain VNC state directory \"\n                             \"path for known hosts storage\");\n  }\n\n  std::string dbPath;\n  dbPath = (std::string)hostsDir + \"/x509_known_hosts\";\n\n  known = gnutls_verify_stored_pubkey(dbPath.c_str(), nullptr,\n                                      client->getServerName(), nullptr,\n                                      GNUTLS_CRT_X509, &cert_list[0], 0);\n\n  /* Previously known? */\n  if (known == GNUTLS_E_SUCCESS) {\n    vlog.info(\"Server certificate found in known hosts file\");\n    gnutls_x509_crt_deinit(crt);\n    return;\n  }\n\n  if ((known != GNUTLS_E_NO_CERTIFICATE_FOUND) &&\n      (known != GNUTLS_E_CERTIFICATE_KEY_MISMATCH)) {\n    gnutls_alert_send_appropriate(session, known);\n    throw rdr::tls_error(\"Could not load known hosts database\", known);\n  }\n\n  err = gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_ONELINE, &info);\n  if (err != GNUTLS_E_SUCCESS) {\n    gnutls_alert_send_appropriate(session, known);\n    throw rdr::tls_error(\"Could not find certificate to display\", err);\n  }\n\n  len = strlen((char*)info.data);\n  for (size_t i = 0; i < len - 1; i++) {\n    if (info.data[i] == ',' && info.data[i + 1] == ' ')\n      info.data[i] = '\\n';\n  }\n\n  /* New host */\n  if (known == GNUTLS_E_NO_CERTIFICATE_FOUND) {\n    std::string text;\n\n    vlog.info(\"Server host not previously known\");\n    vlog.info(\"%s\", info.data);\n\n    if (status & (GNUTLS_CERT_INVALID |\n                  GNUTLS_CERT_SIGNER_NOT_FOUND |\n                  GNUTLS_CERT_SIGNER_NOT_CA)) {\n      text = core::format(\n        \"This certificate has been signed by an unknown authority:\\n\"\n        \"\\n\"\n        \"%s\\n\"\n        \"\\n\"\n        \"Someone could be trying to impersonate the site and you \"\n        \"should not continue.\\n\"\n        \"\\n\"\n        \"Do you want to make an exception for this server?\",\n        info.data);\n\n      if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,\n                           \"Unknown certificate issuer\",\n                           text.c_str())) {\n        gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                          GNUTLS_A_UNKNOWN_CA);\n        throw auth_cancelled();\n      }\n\n      status &= ~(GNUTLS_CERT_INVALID |\n                  GNUTLS_CERT_SIGNER_NOT_FOUND |\n                  GNUTLS_CERT_SIGNER_NOT_CA);\n    }\n\n    if (status & GNUTLS_CERT_NOT_ACTIVATED) {\n      text = core::format(\n        \"This certificate is not yet valid:\\n\"\n        \"\\n\"\n        \"%s\\n\"\n        \"\\n\"\n        \"Someone could be trying to impersonate the site and you \"\n        \"should not continue.\\n\"\n        \"\\n\"\n        \"Do you want to make an exception for this server?\",\n        info.data);\n\n      if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,\n                           \"Certificate is not yet valid\",\n                           text.c_str())) {\n        gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                          GNUTLS_A_BAD_CERTIFICATE);\n        throw auth_cancelled();\n      }\n\n      status &= ~GNUTLS_CERT_NOT_ACTIVATED;\n    }\n\n    if (status & GNUTLS_CERT_EXPIRED) {\n      text = core::format(\n        \"This certificate has expired:\\n\"\n        \"\\n\"\n        \"%s\\n\"\n        \"\\n\"\n        \"Someone could be trying to impersonate the site and you \"\n        \"should not continue.\\n\"\n        \"\\n\"\n        \"Do you want to make an exception for this server?\",\n        info.data);\n\n      if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,\n                           \"Expired certificate\",\n                           text.c_str())) {\n        gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                          GNUTLS_A_BAD_CERTIFICATE);\n        throw auth_cancelled();\n      }\n\n      status &= ~GNUTLS_CERT_EXPIRED;\n    }\n\n    if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {\n      text = core::format(\n        \"This certificate uses an insecure algorithm:\\n\"\n        \"\\n\"\n        \"%s\\n\"\n        \"\\n\"\n        \"Someone could be trying to impersonate the site and you \"\n        \"should not continue.\\n\"\n        \"\\n\"\n        \"Do you want to make an exception for this server?\",\n        info.data);\n\n      if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,\n                           \"Insecure certificate algorithm\",\n                           text.c_str())) {\n        gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                          GNUTLS_A_BAD_CERTIFICATE);\n        throw auth_cancelled();\n      }\n\n      status &= ~GNUTLS_CERT_INSECURE_ALGORITHM;\n    }\n\n    if (status != 0) {\n      vlog.error(\"Unhandled certificate problems: 0x%x\", status);\n      gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                        GNUTLS_A_BAD_CERTIFICATE);\n      throw std::logic_error(\"Unhandled certificate problems\");\n    }\n\n    if (!hostname_match) {\n      text = core::format(\n        \"The specified hostname \\\"%s\\\" does not match the certificate \"\n        \"provided by the server:\\n\"\n        \"\\n\"\n        \"%s\\n\"\n        \"\\n\"\n        \"Someone could be trying to impersonate the site and you \"\n        \"should not continue.\\n\"\n        \"\\n\"\n        \"Do you want to make an exception for this server?\",\n        client->getServerName(), info.data);\n\n      if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,\n                           \"Certificate hostname mismatch\",\n                           text.c_str())) {\n        gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                          GNUTLS_A_BAD_CERTIFICATE);\n        throw auth_cancelled();\n      }\n    }\n  } else if (known == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {\n    std::string text;\n\n    vlog.info(\"Server host key mismatch\");\n    vlog.info(\"%s\", info.data);\n\n    if (status & (GNUTLS_CERT_INVALID |\n                  GNUTLS_CERT_SIGNER_NOT_FOUND |\n                  GNUTLS_CERT_SIGNER_NOT_CA)) {\n      text = core::format(\n        \"This host is previously known with a different certificate, \"\n        \"and the new certificate has been signed by an unknown \"\n        \"authority:\\n\"\n        \"\\n\"\n        \"%s\\n\"\n        \"\\n\"\n        \"Someone could be trying to impersonate the site and you \"\n        \"should not continue.\\n\"\n        \"\\n\"\n        \"Do you want to make an exception for this server?\",\n        info.data);\n\n      if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,\n                           \"Unexpected server certificate\",\n                           text.c_str())) {\n        gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                          GNUTLS_A_UNKNOWN_CA);\n        throw auth_cancelled();\n      }\n\n      status &= ~(GNUTLS_CERT_INVALID |\n                  GNUTLS_CERT_SIGNER_NOT_FOUND |\n                  GNUTLS_CERT_SIGNER_NOT_CA);\n    }\n\n    if (status & GNUTLS_CERT_NOT_ACTIVATED) {\n      text = core::format(\n        \"This host is previously known with a different certificate, \"\n        \"and the new certificate is not yet valid:\\n\"\n        \"\\n\"\n        \"%s\\n\"\n        \"\\n\"\n        \"Someone could be trying to impersonate the site and you \"\n        \"should not continue.\\n\"\n        \"\\n\"\n        \"Do you want to make an exception for this server?\",\n        info.data);\n\n      if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,\n                           \"Unexpected server certificate\",\n                           text.c_str())) {\n        gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                          GNUTLS_A_BAD_CERTIFICATE);\n        throw auth_cancelled();\n      }\n\n      status &= ~GNUTLS_CERT_NOT_ACTIVATED;\n    }\n\n    if (status & GNUTLS_CERT_EXPIRED) {\n      text = core::format(\n        \"This host is previously known with a different certificate, \"\n        \"and the new certificate has expired:\\n\"\n        \"\\n\"\n        \"%s\\n\"\n        \"\\n\"\n        \"Someone could be trying to impersonate the site and you \"\n        \"should not continue.\\n\"\n        \"\\n\"\n        \"Do you want to make an exception for this server?\",\n        info.data);\n\n      if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,\n                           \"Unexpected server certificate\",\n                           text.c_str())) {\n        gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                          GNUTLS_A_BAD_CERTIFICATE);\n        throw auth_cancelled();\n      }\n\n      status &= ~GNUTLS_CERT_EXPIRED;\n    }\n\n    if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {\n      text = core::format(\n        \"This host is previously known with a different certificate, \"\n        \"and the new certificate uses an insecure algorithm:\\n\"\n        \"\\n\"\n        \"%s\\n\"\n        \"\\n\"\n        \"Someone could be trying to impersonate the site and you \"\n        \"should not continue.\\n\"\n        \"\\n\"\n        \"Do you want to make an exception for this server?\",\n        info.data);\n\n      if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,\n                           \"Unexpected server certificate\",\n                           text.c_str())) {\n        gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                          GNUTLS_A_BAD_CERTIFICATE);\n        throw auth_cancelled();\n      }\n\n      status &= ~GNUTLS_CERT_INSECURE_ALGORITHM;\n    }\n\n    if (status != 0) {\n      vlog.error(\"Unhandled certificate problems: 0x%x\", status);\n      gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                        GNUTLS_A_BAD_CERTIFICATE);\n      throw std::logic_error(\"Unhandled certificate problems\");\n    }\n\n    if (!hostname_match) {\n      text = core::format(\n        \"This host is previously known with a different certificate, \"\n        \"and the specified hostname \\\"%s\\\" does not match the new \"\n        \"certificate provided by the server:\\n\"\n        \"\\n\"\n        \"%s\\n\"\n        \"\\n\"\n        \"Someone could be trying to impersonate the site and you \"\n        \"should not continue.\\n\"\n        \"\\n\"\n        \"Do you want to make an exception for this server?\",\n        client->getServerName(), info.data);\n\n      if (!cc->showMsgBox(MsgBoxFlags::M_YESNO,\n                           \"Unexpected server certificate\",\n                           text.c_str())) {\n        gnutls_alert_send(session, GNUTLS_AL_FATAL,\n                          GNUTLS_A_BAD_CERTIFICATE);\n        throw auth_cancelled();\n      }\n    }\n  }\n\n  if (gnutls_store_pubkey(dbPath.c_str(), nullptr,\n                          client->getServerName(), nullptr,\n                          GNUTLS_CRT_X509, &cert_list[0], 0, 0))\n    vlog.error(\"Failed to store server certificate to known hosts database\");\n\n  vlog.info(\"Exception added for server host\");\n\n  gnutls_x509_crt_deinit(crt);\n  gnutls_free(info.data);\n}\n\n"
  },
  {
    "path": "common/rfb/CSecurityTLS.h",
    "content": "/* \n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright 2012-2025 Pierre Ossman for Cendio AB\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __C_SECURITY_TLS_H__\n#define __C_SECURITY_TLS_H__\n\n#ifndef HAVE_GNUTLS\n#error \"This header should not be compiled without HAVE_GNUTLS defined\"\n#endif\n\n#include <rfb/CSecurity.h>\n#include <rfb/Security.h>\n\n#include <gnutls/gnutls.h>\n\nnamespace rdr {\n  class InStream;\n  class OutStream;\n  class TLSSocket;\n}\n\nnamespace rfb {\n  class CSecurityTLS : public CSecurity {\n  public:\n    CSecurityTLS(CConnection* cc, bool _anon);\n    virtual ~CSecurityTLS();\n    bool processMsg() override;\n    int getType() const override { return anon ? secTypeTLSNone : secTypeX509None; }\n    bool isSecure() const override { return !anon; }\n\n    static core::StringParameter X509CA;\n    static core::StringParameter X509CRL;\n\n  protected:\n    void shutdown();\n    void freeResources();\n    void setParam();\n    void checkSession();\n    CConnection *client;\n\n  private:\n    gnutls_session_t session;\n    gnutls_anon_client_credentials_t anon_cred;\n    gnutls_certificate_credentials_t cert_cred;\n    bool anon;\n\n    rdr::TLSSocket* tlssock;\n\n    rdr::InStream* rawis;\n    rdr::OutStream* rawos;\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/CSecurityVeNCrypt.cxx",
    "content": "/* \n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2005-2006 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// CSecurityVeNCrypt\n//\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <algorithm>\n#include <list>\n\n#include <core/LogWriter.h>\n\n#include <rfb/Exception.h>\n#include <rdr/InStream.h>\n#include <rdr/OutStream.h>\n#include <rfb/CConnection.h>\n#include <rfb/CSecurityVeNCrypt.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"CVeNCrypt\");\n\nCSecurityVeNCrypt::CSecurityVeNCrypt(CConnection* cc_,\n                                     SecurityClient* sec)\n  : CSecurity(cc_), csecurity(nullptr), security(sec)\n{\n  haveRecvdMajorVersion = false;\n  haveRecvdMinorVersion = false;\n  haveSentVersion = false;\n  haveAgreedVersion = false;\n  haveListOfTypes = false;\n  haveNumberOfTypes = false;\n  haveChosenType = false;\n  majorVersion = 0;\n  minorVersion = 0;\n  chosenType = secTypeVeNCrypt;\n  nAvailableTypes = 0;\n  availableTypes = nullptr;\n}\n\nCSecurityVeNCrypt::~CSecurityVeNCrypt()\n{\n  delete[] availableTypes;\n  delete csecurity;\n}\n\nbool CSecurityVeNCrypt::processMsg()\n{\n  rdr::InStream* is = cc->getInStream();\n  rdr::OutStream* os = cc->getOutStream();\n\n  /* get major, minor versions, send what we can support (or 0.0 for can't support it) */\n  if (!haveRecvdMajorVersion) {\n    if (!is->hasData(1))\n      return false;\n\n    majorVersion = is->readU8();\n    haveRecvdMajorVersion = true;\n  }\n\n  if (!haveRecvdMinorVersion) {\n    if (!is->hasData(1))\n      return false;\n\n    minorVersion = is->readU8();\n    haveRecvdMinorVersion = true;\n  }\n\n  /* major version in upper 8 bits and minor version in lower 8 bits */\n  uint16_t Version = (((uint16_t) majorVersion) << 8) |\n                      ((uint16_t) minorVersion);\n  \n  if (!haveSentVersion) {\n    /* Currently we don't support former VeNCrypt 0.1 */\n    if (Version >= 0x0002) {\n      majorVersion = 0;\n      minorVersion = 2;\n      os->writeU8(majorVersion);\n      os->writeU8(minorVersion);\n      os->flush();\n    } else {\n      /* Send 0.0 to indicate no support */\n      majorVersion = 0;\n      minorVersion = 0;\n      os->writeU8(0);\n      os->writeU8(0);\n      os->flush();\n      throw protocol_error(\"The server reported an unsupported VeNCrypt version\");\n     }\n\n     haveSentVersion = true;\n  }\n\n  /* Check that the server is OK */\n  if (!haveAgreedVersion) {\n    if (!is->hasData(1))\n      return false;\n\n    if (is->readU8())\n      throw protocol_error(\"The server reported it could not \"\n                           \"support the VeNCrypt version\");\n\n    haveAgreedVersion = true;\n  }\n  \n  /* get a number of types */\n  if (!haveNumberOfTypes) {\n    if (!is->hasData(1))\n      return false;\n\n    nAvailableTypes = is->readU8();\n\n    if (!nAvailableTypes)\n      throw protocol_error(\"The server reported no VeNCrypt sub-types\");\n\n    availableTypes = new uint32_t[nAvailableTypes];\n    haveNumberOfTypes = true;\n  }\n\n  if (nAvailableTypes) {\n    /* read in the types possible */\n    if (!haveListOfTypes) {\n      if (!is->hasData(4 * nAvailableTypes))\n        return false;\n\n      for (int i = 0;i < nAvailableTypes;i++) {\n        availableTypes[i] = is->readU32();\n        vlog.debug(\"Server offers security type %s (%d)\",\n                   secTypeName(availableTypes[i]),\n                   availableTypes[i]);\n      }\n\n      haveListOfTypes = true;\n    }\n\n    /* make a choice and send it to the server, meanwhile set up the stack */\n    if (!haveChosenType) {\n      chosenType = secTypeInvalid;\n      uint8_t i;\n      std::list<uint32_t> secTypes;\n\n      secTypes = security->GetEnabledExtSecTypes();\n\n      /* Honor server's security type order */\n      for (i = 0; i < nAvailableTypes; i++) {\n        if (std::find(secTypes.begin(), secTypes.end(),\n                      availableTypes[i]) != secTypes.end()) {\n          chosenType = availableTypes[i];\n          break;\n        }\n      }\n\n      /* Set up the stack according to the chosen type: */\n      if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)\n        throw protocol_error(\"No valid VeNCrypt sub-type\");\n\n      vlog.info(\"Choosing security type %s (%d)\", secTypeName(chosenType),\n\t\t chosenType);\n\n      csecurity = security->GetCSecurity(cc, chosenType);\n\n      /* send chosen type to server */\n      os->writeU32(chosenType);\n      os->flush();\n\n      haveChosenType = true;\n    }\n  } else {\n    /*\n     * Server told us that there are 0 types it can support - this should not\n     * happen, since if the server supports 0 sub-types, it doesn't support\n     * this security type\n     */\n    throw protocol_error(\"The server reported 0 VeNCrypt sub-types\");\n  }\n\n  return csecurity->processMsg();\n}\n\nbool CSecurityVeNCrypt::isSecure() const\n{\n  if (csecurity && csecurity->isSecure())\n    return true;\n  return false;\n}\n"
  },
  {
    "path": "common/rfb/CSecurityVeNCrypt.h",
    "content": "/*\n * Copyright (C) 2005-2006 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// CSecurityVeNCrypt\n//\n\n#ifndef __CSECURITYVENCRYPT_H__\n#define __CSECURITYVENCRYPT_H__\n\n#include <stdint.h>\n\n#include <rfb/CSecurity.h>\n\nnamespace rfb {\n\n  class SecurityClient;\n\n  class CSecurityVeNCrypt : public CSecurity {\n  public:\n\n    CSecurityVeNCrypt(CConnection* cc, SecurityClient* sec);\n    ~CSecurityVeNCrypt();\n    bool processMsg() override;\n    int getType() const override {return chosenType;}\n    bool isSecure() const override;\n\n  protected:\n    CSecurity *csecurity;\n    SecurityClient *security;\n    bool haveRecvdMajorVersion;\n    bool haveRecvdMinorVersion;\n    bool haveSentVersion;\n    bool haveAgreedVersion;\n    bool haveListOfTypes;\n    bool haveNumberOfTypes;\n    bool haveChosenType;\n    uint8_t majorVersion, minorVersion;\n    uint32_t chosenType;\n    uint8_t nAvailableTypes;\n    uint32_t *availableTypes;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/CSecurityVncAuth.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// CSecurityVncAuth\n//\n// XXX not thread-safe, because d3des isn't - do we need to worry about this?\n//\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string.h>\n#include <stdio.h>\n\n#include <rfb/CConnection.h>\n#include <rfb/CSecurityVncAuth.h>\n#include <rfb/Security.h>\nextern \"C\" {\n#include <rfb/d3des.h>\n}\n\n#include <rdr/InStream.h>\n#include <rdr/OutStream.h>\n\nusing namespace rfb;\n\nstatic const int vncAuthChallengeSize = 16;\n\nbool CSecurityVncAuth::processMsg()\n{\n  rdr::InStream* is = cc->getInStream();\n  rdr::OutStream* os = cc->getOutStream();\n\n  if (!is->hasData(vncAuthChallengeSize))\n    return false;\n\n  // Read the challenge & obtain the user's password\n  uint8_t challenge[vncAuthChallengeSize];\n  is->readBytes(challenge, vncAuthChallengeSize);\n  std::string passwd;\n  cc->getUserPasswd(cc->isSecure(), nullptr, &passwd);\n\n  // Calculate the correct response\n  uint8_t key[8];\n  for (size_t i=0; i<8; i++)\n    key[i] = i<passwd.size() ? passwd[i] : 0;\n  deskey(key, EN0);\n  for (int j = 0; j < vncAuthChallengeSize; j += 8)\n    des(challenge+j, challenge+j);\n\n  // Return the response to the server\n  os->writeBytes(challenge, vncAuthChallengeSize);\n  os->flush();\n  return true;\n}\n"
  },
  {
    "path": "common/rfb/CSecurityVncAuth.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_CSECURITYVNCAUTH_H__\n#define __RFB_CSECURITYVNCAUTH_H__\n\n#include <rfb/CSecurity.h>\n#include <rfb/Security.h>\n\nnamespace rfb {\n\n  class CSecurityVncAuth : public CSecurity {\n  public:\n    CSecurityVncAuth(CConnection* cc_) : CSecurity(cc_) {}\n    virtual ~CSecurityVncAuth() {}\n    bool processMsg() override;\n    int getType() const override {return secTypeVncAuth;};\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/ClientParams.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdexcept>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb/encodings.h>\n#include <rfb/ledStates.h>\n#include <rfb/clipboardTypes.h>\n#include <rfb/ClientParams.h>\n#include <rfb/Cursor.h>\n#include <rfb/ScreenSet.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"ClientParams\");\n\nClientParams::ClientParams()\n  : majorVersion(0), minorVersion(0),\n    compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),\n    subsampling(subsampleUndefined),\n    width_(0), height_(0),\n    cursorPos_(0, 0), ledState_(ledUnknown)\n{\n  setName(\"\");\n\n  screenLayout_ = new ScreenSet();\n\n  pf_ = new PixelFormat();\n\n  cursor_ = new Cursor(0, 0, {}, nullptr);\n\n  clipFlags = clipboardUTF8 | clipboardRTF | clipboardHTML |\n              clipboardRequest | clipboardNotify | clipboardProvide;\n  memset(clipSizes, 0, sizeof(clipSizes));\n  clipSizes[0] = 20 * 1024 * 1024;\n}\n\nClientParams::~ClientParams()\n{\n  delete screenLayout_;\n  delete cursor_;\n  delete pf_;\n}\n\nvoid ClientParams::setDimensions(int width, int height)\n{\n  ScreenSet layout;\n  layout.add_screen(rfb::Screen(0, 0, 0, width, height, 0));\n  setDimensions(width, height, layout);\n}\n\nvoid ClientParams::setDimensions(int width, int height, const ScreenSet& layout)\n{\n  if (!layout.validate(width, height)) {\n    char buffer[2048];\n    vlog.debug(\"Invalid screen layout for %dx%d:\", width, height);\n    layout.print(buffer, sizeof(buffer));\n    vlog.debug(\"%s\", buffer);\n\n    throw std::invalid_argument(\"Attempted to configure an invalid screen layout\");\n  }\n\n  width_ = width;\n  height_ = height;\n  delete screenLayout_;\n  screenLayout_ = new ScreenSet(layout);\n}\n\nvoid ClientParams::setPF(const PixelFormat& pf)\n{\n  delete pf_;\n  pf_ = new PixelFormat(pf);\n\n  if (pf.bpp != 8 && pf.bpp != 16 && pf.bpp != 32)\n    throw std::invalid_argument(\"setPF: Not 8, 16 or 32 bpp?\");\n}\n\nvoid ClientParams::setName(const char* name)\n{\n  name_ = name;\n}\n\nvoid ClientParams::setCursor(const Cursor& other)\n{\n  delete cursor_;\n  cursor_ = new Cursor(other);\n}\n\nvoid ClientParams::setCursorPos(const core::Point& pos)\n{\n  cursorPos_ = pos;\n}\n\nbool ClientParams::supportsEncoding(int32_t encoding) const\n{\n  return encodings_.count(encoding) != 0;\n}\n\nvoid ClientParams::setEncodings(int nEncodings, const int32_t* encodings)\n{\n  compressLevel = -1;\n  qualityLevel = -1;\n  fineQualityLevel = -1;\n  subsampling = subsampleUndefined;\n\n  encodings_.clear();\n  encodings_.insert(encodingRaw);\n\n  for (int i = nEncodings-1; i >= 0; i--) {\n    switch (encodings[i]) {\n    case pseudoEncodingSubsamp1X:\n      subsampling = subsampleNone;\n      break;\n    case pseudoEncodingSubsampGray:\n      subsampling = subsampleGray;\n      break;\n    case pseudoEncodingSubsamp2X:\n      subsampling = subsample2X;\n      break;\n    case pseudoEncodingSubsamp4X:\n      subsampling = subsample4X;\n      break;\n    case pseudoEncodingSubsamp8X:\n      subsampling = subsample8X;\n      break;\n    case pseudoEncodingSubsamp16X:\n      subsampling = subsample16X;\n      break;\n    }\n\n    if (encodings[i] >= pseudoEncodingCompressLevel0 &&\n        encodings[i] <= pseudoEncodingCompressLevel9)\n      compressLevel = encodings[i] - pseudoEncodingCompressLevel0;\n\n    if (encodings[i] >= pseudoEncodingQualityLevel0 &&\n        encodings[i] <= pseudoEncodingQualityLevel9)\n      qualityLevel = encodings[i] - pseudoEncodingQualityLevel0;\n\n    if (encodings[i] >= pseudoEncodingFineQualityLevel0 &&\n        encodings[i] <= pseudoEncodingFineQualityLevel100)\n      fineQualityLevel = encodings[i] - pseudoEncodingFineQualityLevel0;\n\n    encodings_.insert(encodings[i]);\n  }\n}\n\nvoid ClientParams::setLEDState(unsigned int state)\n{\n  ledState_ = state;\n}\n\nuint32_t ClientParams::clipboardSize(unsigned int format) const\n{\n  int i;\n\n  for (i = 0;i < 16;i++) {\n    if (((unsigned)1 << i) == format)\n      return clipSizes[i];\n  }\n\n  throw std::invalid_argument(core::format(\"Invalid clipboard format 0x%x\", format));\n}\n\nvoid ClientParams::setClipboardCaps(uint32_t flags, const uint32_t* lengths)\n{\n  int i, num;\n\n  clipFlags = flags;\n\n  num = 0;\n  for (i = 0;i < 16;i++) {\n    if (!(flags & (1 << i)))\n      continue;\n    clipSizes[i] = lengths[num++];\n  }\n}\n\nbool ClientParams::supportsLocalCursor() const\n{\n  if (supportsEncoding(pseudoEncodingCursorWithAlpha))\n    return true;\n  if (supportsEncoding(pseudoEncodingVMwareCursor))\n    return true;\n  if (supportsEncoding(pseudoEncodingCursor))\n    return true;\n  if (supportsEncoding(pseudoEncodingXCursor))\n    return true;\n  return false;\n}\n\nbool ClientParams::supportsCursorPosition() const\n{\n  if (supportsEncoding(pseudoEncodingVMwareCursorPosition))\n    return true;\n  return false;\n}\n\nbool ClientParams::supportsDesktopSize() const\n{\n  if (supportsEncoding(pseudoEncodingExtendedDesktopSize))\n    return true;\n  if (supportsEncoding(pseudoEncodingDesktopSize))\n    return true;\n  return false;\n}\n\nbool ClientParams::supportsLEDState() const\n{\n  if (supportsEncoding(pseudoEncodingLEDState))\n    return true;\n  if (supportsEncoding(pseudoEncodingVMwareLEDState))\n    return true;\n  return false;\n}\n\nbool ClientParams::supportsFence() const\n{\n  if (supportsEncoding(pseudoEncodingFence))\n    return true;\n  return false;\n}\n\nbool ClientParams::supportsContinuousUpdates() const\n{\n  if (supportsEncoding(pseudoEncodingContinuousUpdates))\n    return true;\n  return false;\n}\n\nbool ClientParams::supportsExtendedMouseButtons() const\n{\n  if (supportsEncoding(pseudoEncodingExtendedMouseButtons))\n    return true;\n  return false;\n}\n"
  },
  {
    "path": "common/rfb/ClientParams.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// ClientParams - structure describing the current state of the remote client\n//\n\n#ifndef __RFB_CLIENTPARAMS_H__\n#define __RFB_CLIENTPARAMS_H__\n\n#include <set>\n#include <string>\n\n#include <stdint.h>\n\n#include <core/Rect.h>\n\nnamespace rfb {\n\n  class Cursor;\n  class PixelFormat;\n  struct ScreenSet;\n\n  const int subsampleUndefined = -1;\n  const int subsampleNone = 0;\n  const int subsampleGray = 1;\n  const int subsample2X = 2;\n  const int subsample4X = 3;\n  const int subsample8X = 4;\n  const int subsample16X = 5;\n\n  class ClientParams {\n  public:\n    ClientParams();\n    ~ClientParams();\n\n    int majorVersion;\n    int minorVersion;\n\n    void setVersion(int major, int minor) {\n      majorVersion = major; minorVersion = minor;\n    }\n    bool isVersion(int major, int minor) const {\n      return majorVersion == major && minorVersion == minor;\n    }\n    bool beforeVersion(int major, int minor) const {\n      return (majorVersion < major ||\n              (majorVersion == major && minorVersion < minor));\n    }\n    bool afterVersion(int major, int minor) const {\n      return !beforeVersion(major,minor+1);\n    }\n\n    int width() const { return width_; }\n    int height() const { return height_; }\n    const ScreenSet& screenLayout() const { return *screenLayout_; }\n    void setDimensions(int width, int height);\n    void setDimensions(int width, int height, const ScreenSet& layout);\n\n    const PixelFormat& pf() const { return *pf_; }\n    void setPF(const PixelFormat& pf);\n\n    const char* name() const { return name_.c_str(); }\n    void setName(const char* name);\n\n    const Cursor& cursor() const { return *cursor_; }\n    void setCursor(const Cursor& cursor);\n\n    const core::Point& cursorPos() const { return cursorPos_; }\n    void setCursorPos(const core::Point& pos);\n\n    bool supportsEncoding(int32_t encoding) const;\n\n    void setEncodings(int nEncodings, const int32_t* encodings);\n\n    unsigned int ledState() { return ledState_; }\n    void setLEDState(unsigned int state);\n\n    uint32_t clipboardFlags() const { return clipFlags; }\n    uint32_t clipboardSize(unsigned int format) const;\n    void setClipboardCaps(uint32_t flags, const uint32_t* lengths);\n\n    // Wrappers to check for functionality rather than specific\n    // encodings\n    bool supportsLocalCursor() const;\n    bool supportsCursorPosition() const;\n    bool supportsDesktopSize() const;\n    bool supportsLEDState() const;\n    bool supportsFence() const;\n    bool supportsContinuousUpdates() const;\n    bool supportsExtendedMouseButtons() const;\n\n    int compressLevel;\n    int qualityLevel;\n    int fineQualityLevel;\n    int subsampling;\n\n  private:\n\n    int width_;\n    int height_;\n    ScreenSet* screenLayout_;\n\n    PixelFormat* pf_;\n    std::string name_;\n    Cursor* cursor_;\n    core::Point cursorPos_;\n    std::set<int32_t> encodings_;\n    unsigned int ledState_;\n    uint32_t clipFlags;\n    uint32_t clipSizes[16];\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/ComparingUpdateTracker.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <string.h>\n\n#include <algorithm>\n#include <vector>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb/ComparingUpdateTracker.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"ComparingUpdateTracker\");\n\nComparingUpdateTracker::ComparingUpdateTracker(PixelBuffer* buffer)\n  : fb(buffer), oldFb(fb->getPF(), 0, 0), firstCompare(true),\n    enabled(true), totalPixels(0), missedPixels(0)\n{\n    changed.assign_union(fb->getRect());\n}\n\nComparingUpdateTracker::~ComparingUpdateTracker()\n{\n}\n\n\n#define BLOCK_SIZE 64\n\nbool ComparingUpdateTracker::compare()\n{\n  std::vector<core::Rect> rects;\n  std::vector<core::Rect>::iterator i;\n\n  if (!enabled)\n    return false;\n\n  if (firstCompare) {\n    // NB: We leave the change region untouched on this iteration,\n    // since in effect the entire framebuffer has changed.\n    oldFb.setSize(fb->width(), fb->height());\n\n    for (int y=0; y<fb->height(); y+=BLOCK_SIZE) {\n      core::Rect pos(0, y, fb->width(), std::min(fb->height(), y+BLOCK_SIZE));\n      int srcStride;\n      const uint8_t* srcData = fb->getBuffer(pos, &srcStride);\n      oldFb.imageRect(pos, srcData, srcStride);\n    }\n\n    firstCompare = false;\n\n    return false;\n  }\n\n  copied.get_rects(&rects, copy_delta.x<=0, copy_delta.y<=0);\n  for (i = rects.begin(); i != rects.end(); i++)\n    oldFb.copyRect(*i, copy_delta);\n\n  changed.get_rects(&rects);\n\n  core::Region newChanged;\n  for (i = rects.begin(); i != rects.end(); i++)\n    compareRect(*i, &newChanged);\n\n  changed.get_rects(&rects);\n  for (i = rects.begin(); i != rects.end(); i++)\n    totalPixels += i->area();\n  newChanged.get_rects(&rects);\n  for (i = rects.begin(); i != rects.end(); i++)\n    missedPixels += i->area();\n\n  if (changed == newChanged)\n    return false;\n\n  changed = newChanged;\n\n  return true;\n}\n\nvoid ComparingUpdateTracker::enable()\n{\n  enabled = true;\n}\n\nvoid ComparingUpdateTracker::disable()\n{\n  enabled = false;\n\n  // Make sure we update the framebuffer next time we get enabled\n  firstCompare = true;\n}\n\nvoid ComparingUpdateTracker::compareRect(const core::Rect& r,\n                                         core::Region* newChanged)\n{\n  if (!r.enclosed_by(fb->getRect())) {\n    core::Rect safe;\n    // Crop the rect and try again\n    safe = r.intersect(fb->getRect());\n    if (!safe.is_empty())\n      compareRect(safe, newChanged);\n    return;\n  }\n\n  int bytesPerPixel = fb->getPF().bpp/8;\n  int oldStride;\n  uint8_t* oldData = oldFb.getBufferRW(r, &oldStride);\n  int oldStrideBytes = oldStride * bytesPerPixel;\n\n  // Used to efficiently crop the left and right of the change rectangle\n  int minCompareWidthInPixels = BLOCK_SIZE / 8;\n  int minCompareWidthInBytes = minCompareWidthInPixels * bytesPerPixel;\n\n  for (int blockTop = r.tl.y; blockTop < r.br.y; blockTop += BLOCK_SIZE)\n  {\n    // Get a strip of the source buffer\n    core::Rect pos(r.tl.x, blockTop, r.br.x, std::min(r.br.y, blockTop+BLOCK_SIZE));\n    int fbStride;\n    const uint8_t* newBlockPtr = fb->getBuffer(pos, &fbStride);\n    int newStrideBytes = fbStride * bytesPerPixel;\n\n    uint8_t* oldBlockPtr = oldData;\n    int blockBottom = std::min(blockTop+BLOCK_SIZE, r.br.y);\n\n    for (int blockLeft = r.tl.x; blockLeft < r.br.x; blockLeft += BLOCK_SIZE)\n    {\n      const uint8_t* newPtr = newBlockPtr;\n      uint8_t* oldPtr = oldBlockPtr;\n\n      int blockRight = std::min(blockLeft+BLOCK_SIZE, r.br.x);\n      int blockWidthInBytes = (blockRight-blockLeft) * bytesPerPixel;\n\n      // Scan the block top to bottom, to identify the first row of change\n      for (int y = blockTop; y < blockBottom; y++)\n      {\n        if (memcmp(oldPtr, newPtr, blockWidthInBytes) != 0)\n        {\n          // Define the change rectangle using pessimistic values to start\n          int changeHeight = blockBottom - y;\n          int changeLeft = blockLeft;\n          int changeRight = blockRight;\n\n          // For every unchanged row at the bottom of the block, decrement change height\n          {\n            const uint8_t* newRowPtr = newPtr + ((changeHeight - 1) * newStrideBytes);\n            const uint8_t* oldRowPtr = oldPtr + ((changeHeight - 1) * oldStrideBytes);\n            while (changeHeight > 1 && memcmp(oldRowPtr, newRowPtr, blockWidthInBytes) == 0)\n            {\n              newRowPtr -= newStrideBytes;\n              oldRowPtr -= oldStrideBytes;\n\n              changeHeight--;\n            }\n          }\n\n          // For every unchanged column at the left of the block, increment change left\n          {\n            const uint8_t* newColumnPtr = newPtr;\n            const uint8_t* oldColumnPtr = oldPtr;\n            while (changeLeft + minCompareWidthInPixels < changeRight)\n            {\n              const uint8_t* newRowPtr = newColumnPtr;\n              const uint8_t* oldRowPtr = oldColumnPtr;\n              for (int row = 0; row < changeHeight; row++)\n              {\n                if (memcmp(oldRowPtr, newRowPtr, minCompareWidthInBytes) != 0)\n                  goto endOfChangeLeft;\n\n                newRowPtr += newStrideBytes;\n                oldRowPtr += oldStrideBytes;\n              }\n\n              newColumnPtr += minCompareWidthInBytes;\n              oldColumnPtr += minCompareWidthInBytes;\n\n              changeLeft += minCompareWidthInPixels;\n            }\n          }\n        endOfChangeLeft:\n\n          // For every unchanged column at the right of the block, decrement change right\n          {\n            const uint8_t* newColumnPtr = newPtr + blockWidthInBytes;\n            const uint8_t* oldColumnPtr = oldPtr + blockWidthInBytes;\n            while (changeLeft + minCompareWidthInPixels < changeRight)\n            {\n              newColumnPtr -= minCompareWidthInBytes;\n              oldColumnPtr -= minCompareWidthInBytes;\n\n              const uint8_t* newRowPtr = newColumnPtr;\n              const uint8_t* oldRowPtr = oldColumnPtr;\n              for (int row = 0; row < changeHeight; row++)\n              {\n                if (memcmp(oldRowPtr, newRowPtr, minCompareWidthInBytes) != 0)\n                  goto endOfChangeRight;\n\n                newRowPtr += newStrideBytes;\n                oldRowPtr += oldStrideBytes;\n              }\n\n              changeRight -= minCompareWidthInPixels;\n            }\n          }\n        endOfChangeRight:\n\n          // Block change extends from (changeLeft, y) to (changeRight,\n          // y + changeHeight)\n          newChanged->assign_union({{changeLeft, y,\n                                     changeRight, y + changeHeight}});\n\n          // Copy the change from fb to oldFb to allow future changes to be identified\n          for (int row = 0; row < changeHeight; row++)\n          {\n            memcpy(oldPtr, newPtr, blockWidthInBytes);\n            newPtr += newStrideBytes;\n            oldPtr += oldStrideBytes;\n          }\n\n          // No further processing is required for this block\n          break;\n        }\n\n        newPtr += newStrideBytes;\n        oldPtr += oldStrideBytes;\n      }\n\n      oldBlockPtr += blockWidthInBytes;\n      newBlockPtr += blockWidthInBytes;\n    }\n\n    oldData += oldStrideBytes * BLOCK_SIZE;\n  }\n\n  oldFb.commitBufferRW(r);\n}\n\nvoid ComparingUpdateTracker::logStats()\n{\n  double ratio;\n\n  ratio = (double)totalPixels / missedPixels;\n\n  // FIXME: This gets spammed on each session resize, so we'll have to\n  //        keep it on a debug level for now\n  vlog.debug(\"%s in / %s out\",\n             core::siPrefix(totalPixels, \"pixels\").c_str(),\n             core::siPrefix(missedPixels, \"pixels\").c_str());\n  vlog.debug(\"(1:%g ratio)\", ratio);\n\n  totalPixels = missedPixels = 0;\n}\n"
  },
  {
    "path": "common/rfb/ComparingUpdateTracker.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_COMPARINGUPDATETRACKER_H__\n#define __RFB_COMPARINGUPDATETRACKER_H__\n\n#include <rfb/PixelBuffer.h>\n#include <rfb/UpdateTracker.h>\n\nnamespace rfb {\n\n  class ComparingUpdateTracker : public SimpleUpdateTracker {\n  public:\n    ComparingUpdateTracker(PixelBuffer* buffer);\n    ~ComparingUpdateTracker();\n\n    // compare() does the comparison and reduces its changed and copied regions\n    // as appropriate. Returns true if the regions were altered.\n\n    virtual bool compare();\n\n    // enable()/disable() turns the comparing functionality on/off. With it\n    // disabled, the object will behave like a dumb update tracker (i.e.\n    // compare() will be a no-op). It is harmless to repeatedly call these\n    // methods.\n\n    virtual void enable();\n    virtual void disable();\n\n    void logStats();\n\n  private:\n    void compareRect(const core::Rect& r, core::Region* newchanged);\n    PixelBuffer* fb;\n    ManagedPixelBuffer oldFb;\n    bool firstCompare;\n    bool enabled;\n\n    unsigned long long totalPixels, missedPixels;\n  };\n\n}\n#endif\n"
  },
  {
    "path": "common/rfb/Congestion.cxx",
    "content": "/* Copyright 2009-2018 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n/*\n * This code implements congestion control in the same way as TCP in\n * order to avoid excessive latency in the transport. This is needed\n * because \"buffer bloat\" is unfortunately still a very real problem.\n *\n * The basic principle is TCP Congestion Control (RFC 5618), with the\n * addition of using the TCP Vegas algorithm. The reason we use Vegas\n * is that we run on top of a reliable transport so we need a latency\n * based algorithm rather than a loss based one. There is also a lot of\n * interpolation of values. This is because we have rather horrible\n * granularity in our measurements.\n *\n * We use a simplistic form of slow start in order to ramp up quickly\n * from an idle state. We do not have any persistent threshold though\n * as we have too much noise for it to be reliable.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <string.h>\n#include <sys/time.h>\n\n#ifdef __linux__\n#include <sys/ioctl.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include <linux/sockios.h>\n#endif\n\n#include <core/LogWriter.h>\n#include <core/time.h>\n\n#include <rfb/Congestion.h>\n\n// Debug output on what the congestion control is up to\n#undef CONGESTION_DEBUG\n\n// Dump socket congestion window debug trace to disk\n#undef CONGESTION_TRACE\n\nusing namespace rfb;\n\n// This window should get us going fairly fast on a decent bandwidth network.\n// If it's too high, it will rapidly be reduced and stay low.\nstatic const unsigned INITIAL_WINDOW = 16384;\n\n// TCP's minimal window is 3*MSS. But since we don't know the MSS, we\n// make a guess at 4 KiB (it's probably a bit higher).\nstatic const unsigned MINIMUM_WINDOW = 4096;\n\n// The current default maximum window for Linux (4 MiB). Should be a good\n// limit for now...\nstatic const unsigned MAXIMUM_WINDOW = 4194304;\n\n// Compare position even when wrapped around\nstatic inline bool isAfter(unsigned a, unsigned b) {\n  return a != b && a - b <= UINT_MAX / 2;\n}\n\nstatic core::LogWriter vlog(\"Congestion\");\n\nCongestion::Congestion() :\n    lastPosition(0), extraBuffer(0),\n    baseRTT(-1), congWindow(INITIAL_WINDOW), inSlowStart(true),\n    safeBaseRTT(-1), measurements(0), minRTT(-1), minCongestedRTT(-1)\n{\n  gettimeofday(&lastUpdate, nullptr);\n  gettimeofday(&lastSent, nullptr);\n  memset(&lastPong, 0, sizeof(lastPong));\n  gettimeofday(&lastPongArrival, nullptr);\n  gettimeofday(&lastAdjustment, nullptr);\n}\n\nCongestion::~Congestion()\n{\n}\n\nvoid Congestion::updatePosition(unsigned pos)\n{\n  struct timeval now;\n  unsigned idle, delta, consumed;\n\n  gettimeofday(&now, nullptr);\n\n  delta = pos - lastPosition;\n  if ((delta > 0) || (extraBuffer > 0))\n    lastSent = now;\n\n  // Idle for too long?\n  // We use a very crude RTO calculation in order to keep things simple\n  // FIXME: should implement RFC 2861\n  idle = core::msBetween(&lastSent, &now);\n  if (idle > 100 && idle > baseRTT*2) {\n\n#ifdef CONGESTION_DEBUG\n    vlog.debug(\"Connection idle for %d ms, resetting congestion control\",\n               idle);\n#endif\n\n    // Close congestion window and redo wire latency measurement\n    if (congWindow > INITIAL_WINDOW)\n      congWindow = INITIAL_WINDOW;\n    baseRTT = -1;\n    measurements = 0;\n    gettimeofday(&lastAdjustment, nullptr);\n    minRTT = minCongestedRTT = -1;\n    inSlowStart = true;\n  }\n\n  // Commonly we will be in a state of overbuffering. We need to\n  // estimate the extra delay that causes so we can separate it from\n  // the delay caused by an incorrect congestion window.\n  // (we cannot do this until we have a RTT measurement though)\n  if (baseRTT != (unsigned)-1) {\n    extraBuffer += delta;\n    consumed = core::msBetween(&lastUpdate, &now) * congWindow / baseRTT;\n    if (extraBuffer < consumed)\n      extraBuffer = 0;\n    else\n      extraBuffer -= consumed;\n  }\n\n  lastPosition = pos;\n  lastUpdate = now;\n}\n\nvoid Congestion::sentPing()\n{\n  struct RTTInfo rttInfo;\n\n  memset(&rttInfo, 0, sizeof(struct RTTInfo));\n\n  gettimeofday(&rttInfo.tv, nullptr);\n  rttInfo.pos = lastPosition;\n  rttInfo.extra = getExtraBuffer();\n  rttInfo.congested = isCongested();\n\n  pings.push_back(rttInfo);\n}\n\nvoid Congestion::gotPong()\n{\n  struct timeval now;\n  struct RTTInfo rttInfo;\n  unsigned rtt, delay;\n\n  if (pings.empty())\n    return;\n\n  gettimeofday(&now, nullptr);\n\n  rttInfo = pings.front();\n  pings.pop_front();\n\n  lastPong = rttInfo;\n  lastPongArrival = now;\n\n  rtt = core::msBetween(&rttInfo.tv, &now);\n  if (rtt < 1)\n    rtt = 1;\n\n  // Try to estimate wire latency by tracking lowest seen latency\n  if (rtt < baseRTT)\n    safeBaseRTT = baseRTT = rtt;\n\n  // Pings sent before the last adjustment aren't interesting as they\n  // aren't a measurement of the current congestion window\n  if (core::isBefore(&rttInfo.tv, &lastAdjustment))\n    return;\n\n  // Estimate added delay because of overtaxed buffers (see above)\n  delay = rttInfo.extra * baseRTT / congWindow;\n  if (delay < rtt)\n    rtt -= delay;\n  else\n    rtt = 1;\n\n  // A latency less than the wire latency means that we've\n  // understimated the congestion window. We can't really determine\n  // how much, so pretend that we got no buffer latency at all.\n  if (rtt < baseRTT)\n    rtt = baseRTT;\n\n  // Record the minimum seen delay (hopefully ignores jitter) and let\n  // the congestion control do its thing.\n  //\n  // Note: We are delay based rather than loss based, which means we\n  //       need to look at pongs even if they weren't limited by the\n  //       current window (\"congested\"). Otherwise we will fail to\n  //       detect increasing congestion until the application exceeds\n  //       the congestion window.\n  if (rtt < minRTT)\n    minRTT = rtt;\n  if (rttInfo.congested) {\n    if (rtt < minCongestedRTT)\n      minCongestedRTT = rtt;\n  }\n\n  measurements++;\n  updateCongestion();\n}\n\nbool Congestion::isCongested()\n{\n  if (getInFlight() < congWindow)\n    return false;\n\n  return true;\n}\n\nint Congestion::getUncongestedETA()\n{\n  unsigned targetAcked;\n\n  const struct RTTInfo* prevPing;\n  unsigned eta, elapsed;\n  unsigned etaNext, delay;\n\n  std::list<struct RTTInfo>::const_iterator iter;\n\n  targetAcked = lastPosition - congWindow;\n\n  // Simple case?\n  if (isAfter(lastPong.pos, targetAcked))\n    return 0;\n\n  // No measurements yet?\n  if (baseRTT == (unsigned)-1)\n    return -1;\n\n  prevPing = &lastPong;\n  eta = 0;\n  elapsed = core::msSince(&lastPongArrival);\n\n  // Walk the ping queue and figure out which one we are waiting for to\n  // get to an uncongested state\n\n  for (iter = pings.begin(); ;++iter) {\n    struct RTTInfo curPing;\n\n    // If we aren't waiting for a pong that will clear the congested\n    // state then we have to estimate the final bit by pretending that\n    // we had a ping just after the last position update.\n    if (iter == pings.end()) {\n      curPing.tv = lastUpdate;\n      curPing.pos = lastPosition;\n      curPing.extra = extraBuffer;\n    } else {\n      curPing = *iter;\n    }\n\n    etaNext = core::msBetween(&prevPing->tv, &curPing.tv);\n    // Compensate for buffering delays\n    delay = curPing.extra * baseRTT / congWindow;\n    etaNext += delay;\n    delay = prevPing->extra * baseRTT / congWindow;\n    if (delay >= etaNext)\n      etaNext = 0;\n    else\n      etaNext -= delay;\n\n    // Found it?\n    if (isAfter(curPing.pos, targetAcked)) {\n      eta += etaNext * (curPing.pos - targetAcked) / (curPing.pos - prevPing->pos);\n      if (elapsed > eta)\n        return 0;\n      else\n        return eta - elapsed;\n    }\n\n    assert(iter != pings.end());\n\n    eta += etaNext;\n    prevPing = &*iter;\n  }\n}\n\nsize_t Congestion::getBandwidth()\n{\n  size_t bandwidth;\n\n  // No measurements yet? Guess RTT of 60 ms\n  if (safeBaseRTT == (unsigned)-1)\n    bandwidth = congWindow * 1000 / 60;\n  else\n    bandwidth = congWindow * 1000 / safeBaseRTT;\n\n  // We're still probing so guess actual bandwidth is halfway between\n  // the current guess and the next one (slow start doubles each time)\n  if (inSlowStart)\n    bandwidth = bandwidth + bandwidth / 2;\n\n  return bandwidth;\n}\n\nvoid Congestion::debugTrace(const char* filename, int fd)\n{\n  (void)filename;\n  (void)fd;\n#ifdef CONGESTION_TRACE\n#ifdef __linux__\n  FILE *f;\n  f = fopen(filename, \"ab\");\n  if (f != nullptr) {\n    struct tcp_info info;\n    int buffered;\n    socklen_t len;\n    len = sizeof(info);\n    if ((getsockopt(fd, IPPROTO_TCP,\n                    TCP_INFO, &info, &len) == 0) &&\n        (ioctl(fd, SIOCOUTQ, &buffered) == 0)) {\n      struct timeval now;\n      gettimeofday(&now, nullptr);\n      fprintf(f, \"%u.%06u,%u,%u,%u,%u\\n\",\n              (unsigned)now.tv_sec, (unsigned)now.tv_usec,\n              congWindow, info.tcpi_snd_cwnd * info.tcpi_snd_mss,\n              getInFlight(), buffered);\n    }\n    fclose(f);\n  }\n#endif\n#endif\n}\n\nunsigned Congestion::getExtraBuffer()\n{\n  unsigned elapsed;\n  unsigned consumed;\n\n  if (baseRTT == (unsigned)-1)\n    return 0;\n\n  elapsed = core::msSince(&lastUpdate);\n  consumed = elapsed * congWindow / baseRTT;\n\n  if (consumed >= extraBuffer)\n    return 0;\n  else\n    return extraBuffer - consumed;\n}\n\nunsigned Congestion::getInFlight()\n{\n  struct RTTInfo nextPong;\n  unsigned etaNext, delay, elapsed, acked;\n\n  // Simple case?\n  if (lastPosition == lastPong.pos)\n    return 0;\n\n  // No measurements yet?\n  if (baseRTT == (unsigned)-1) {\n    if (!pings.empty())\n      return lastPosition - pings.front().pos;\n    return 0;\n  }\n\n  // If we aren't waiting for any pong then we have to estimate things\n  // by pretending that we had a ping just after the last position\n  // update.\n  if (pings.empty()) {\n    nextPong.tv = lastUpdate;\n    nextPong.pos = lastPosition;\n    nextPong.extra = extraBuffer;\n  } else {\n    nextPong = pings.front();\n  }\n\n  // First we need to estimate how many bytes have made it through\n  // completely. Look at the next ping that should arrive and figure\n  // out how far behind it should be and interpolate the positions.\n\n  etaNext = core::msBetween(&lastPong.tv, &nextPong.tv);\n  // Compensate for buffering delays\n  delay = nextPong.extra * baseRTT / congWindow;\n  etaNext += delay;\n  delay = lastPong.extra * baseRTT / congWindow;\n  if (delay >= etaNext)\n    etaNext = 0;\n  else\n    etaNext -= delay;\n\n  elapsed = core::msSince(&lastPongArrival);\n\n  // The pong should be here any second. Be optimistic and assume\n  // we can already use its value.\n  if (etaNext <= elapsed)\n    acked = nextPong.pos;\n  else {\n    acked = lastPong.pos;\n    acked += (nextPong.pos - lastPong.pos) * elapsed / etaNext;\n  }\n\n  return lastPosition - acked;\n}\n\nvoid Congestion::updateCongestion()\n{\n  unsigned diff;\n\n  // We want at least three measurements to avoid noise\n  if (measurements < 3)\n    return;\n\n  assert(minRTT >= baseRTT);\n  assert(minCongestedRTT >= baseRTT);\n\n  // The goal is to have a slightly too large congestion window since\n  // a \"perfect\" one cannot be distinguished from a too small one. This\n  // translates to a goal of a few extra milliseconds of delay.\n\n  diff = minRTT - baseRTT;\n\n  if (diff > 100 && diff > baseRTT/2) {\n    // We have no way of detecting loss, so assume massive latency\n    // spike means packet loss. Adjust the window and go directly\n    // to congestion avoidance.\n#ifdef CONGESTION_DEBUG\n    vlog.debug(\"Latency spike! Backing off...\");\n#endif\n    congWindow = congWindow * baseRTT / minRTT;\n    inSlowStart = false;\n  }\n\n  if (inSlowStart) {\n    // Slow start. Aggressive growth until we see congestion.\n\n    if (diff > 25) {\n      // If we see an increased latency then we assume we've hit the\n      // limit and it's time to leave slow start and switch to\n      // congestion avoidance\n      congWindow = congWindow * baseRTT / minRTT;\n      inSlowStart = false;\n    } else {\n      // It's not safe to increase unless we actually used the entire\n      // congestion window, hence we look at minCongestedRTT and not\n      // minRTT\n\n      diff = minCongestedRTT - baseRTT;\n      if (diff < 25)\n        congWindow *= 2;\n    }\n  } else {\n    // Congestion avoidance (VEGAS)\n\n    if (diff > 50) {\n      // Slightly too fast\n      congWindow -= 4096;\n    } else {\n      // Only the \"congested\" pongs are checked to see if the\n      // window is too small.\n\n      diff = minCongestedRTT - baseRTT;\n\n      if (diff < 5) {\n        // Way too slow\n        congWindow += 8192;\n      } else if (diff < 25) {\n        // Too slow\n        congWindow += 4096;\n      }\n    }\n  }\n\n  if (congWindow < MINIMUM_WINDOW)\n    congWindow = MINIMUM_WINDOW;\n  if (congWindow > MAXIMUM_WINDOW)\n    congWindow = MAXIMUM_WINDOW;\n\n#ifdef CONGESTION_DEBUG\n  vlog.debug(\"RTT: %d/%d ms (%d ms), Window: %d KiB, Bandwidth: %g Mbps%s\",\n             minRTT, minCongestedRTT, baseRTT, congWindow / 1024,\n             congWindow * 8.0 / baseRTT / 1000.0,\n             inSlowStart ? \" (slow start)\" : \"\");\n#endif\n\n  measurements = 0;\n  gettimeofday(&lastAdjustment, nullptr);\n  minRTT = minCongestedRTT = -1;\n}\n\n"
  },
  {
    "path": "common/rfb/Congestion.h",
    "content": "/* Copyright 2009-2018 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_CONGESTION_H__\n#define __RFB_CONGESTION_H__\n\n#include <list>\n\nnamespace rfb {\n  class Congestion {\n  public:\n    Congestion();\n    ~Congestion();\n\n    // updatePosition() registers the current stream position and can\n    // and should be called often.\n    void updatePosition(unsigned pos);\n\n    // sentPing() must be called when a marker is placed on the\n    // outgoing stream. gotPong() must be called when the response for\n    // such a marker is received.\n    void sentPing();\n    void gotPong();\n\n    // isCongested() determines if the transport is currently congested\n    // or if more data can be sent.\n    bool isCongested();\n\n    // getUncongestedETA() returns the number of milliseconds until the\n    // transport is no longer congested. Returns 0 if there is no\n    // congestion, and -1 if it is unknown when the transport will no\n    // longer be congested.\n    int getUncongestedETA();\n\n    // getBandwidth() returns the current bandwidth estimation in bytes\n    // per second.\n    size_t getBandwidth();\n\n    // debugTrace() writes the current congestion window, as well as the\n    // congestion window of the underlying TCP layer, to the specified\n    // file\n    void debugTrace(const char* filename, int fd);\n\n  protected:\n    unsigned getExtraBuffer();\n    unsigned getInFlight();\n\n    void updateCongestion();\n\n  private:\n    unsigned lastPosition;\n    unsigned extraBuffer;\n    struct timeval lastUpdate;\n    struct timeval lastSent;\n\n    unsigned baseRTT;\n    unsigned congWindow;\n    bool inSlowStart;\n\n    unsigned safeBaseRTT;\n\n    struct RTTInfo {\n      struct timeval tv;\n      unsigned pos;\n      unsigned extra;\n      bool congested;\n    };\n\n    std::list<struct RTTInfo> pings;\n\n    struct RTTInfo lastPong;\n    struct timeval lastPongArrival;\n\n    int measurements;\n    struct timeval lastAdjustment;\n    unsigned minRTT, minCongestedRTT;\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/CopyRectDecoder.cxx",
    "content": "/* Copyright 2014 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Region.h>\n\n#include <rdr/MemInStream.h>\n#include <rdr/OutStream.h>\n\n#include <rfb/PixelBuffer.h>\n#include <rfb/CopyRectDecoder.h>\n\nusing namespace rfb;\n\nCopyRectDecoder::CopyRectDecoder() : Decoder(DecoderPlain)\n{\n}\n\nCopyRectDecoder::~CopyRectDecoder()\n{\n}\n\nbool CopyRectDecoder::readRect(const core::Rect& /*r*/,\n                               rdr::InStream* is,\n                               const ServerParams& /*server*/,\n                               rdr::OutStream* os)\n{\n  if (!is->hasData(4))\n    return false;\n  os->copyBytes(is, 4);\n  return true;\n}\n\n\nvoid CopyRectDecoder::getAffectedRegion(const core::Rect& rect,\n                                        const uint8_t* buffer,\n                                        size_t buflen,\n                                        const ServerParams& server,\n                                        core::Region* region)\n{\n  rdr::MemInStream is(buffer, buflen);\n  int srcX = is.readU16();\n  int srcY = is.readU16();\n\n  Decoder::getAffectedRegion(rect, buffer, buflen, server, region);\n\n  region->assign_union(rect.translate({srcX-rect.tl.x,\n                                       srcY-rect.tl.y}));\n}\n\nvoid CopyRectDecoder::decodeRect(const core::Rect& r,\n                                 const uint8_t* buffer,\n                                 size_t buflen,\n                                 const ServerParams& /*server*/,\n                                 ModifiablePixelBuffer* pb)\n{\n  rdr::MemInStream is(buffer, buflen);\n  int srcX = is.readU16();\n  int srcY = is.readU16();\n  pb->copyRect(r, {r.tl.x-srcX, r.tl.y-srcY});\n}\n"
  },
  {
    "path": "common/rfb/CopyRectDecoder.h",
    "content": "/* Copyright 2014 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_COPYRECTDECODER_H__\n#define __RFB_COPYRECTDECODER_H__\n\n#include <rfb/Decoder.h>\n\nnamespace rfb {\n\n  class CopyRectDecoder : public Decoder {\n  public:\n    CopyRectDecoder();\n    virtual ~CopyRectDecoder();\n    bool readRect(const core::Rect& r, rdr::InStream* is,\n                  const ServerParams& server,\n                  rdr::OutStream* os) override;\n    void getAffectedRegion(const core::Rect& rect, const uint8_t* buffer,\n                           size_t buflen, const ServerParams& server,\n                           core::Region* region) override;\n    void decodeRect(const core::Rect& r, const uint8_t* buffer,\n                    size_t buflen, const ServerParams& server,\n                    ModifiablePixelBuffer* pb) override;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/Cursor.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2023 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <string.h>\n\n#include <stdexcept>\n\n#include <core/LogWriter.h>\n\n#include <rfb/Cursor.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"Cursor\");\n\nCursor::Cursor(int width, int height, const core::Point& hotspot,\n               const uint8_t* data_) :\n  width_(width), height_(height), hotspot_(hotspot)\n{\n  data = new uint8_t[width_*height_*4];\n  memcpy(data, data_, width_*height_*4);\n}\n\nCursor::Cursor(const Cursor& other) :\n  width_(other.width_), height_(other.height_),\n  hotspot_(other.hotspot_)\n{\n  data = new uint8_t[width_*height_*4];\n  memcpy(data, other.data, width_*height_*4);\n}\n\nCursor::~Cursor()\n{\n  delete [] data;\n}\n\nstatic unsigned short pow223[] = { 0, 30, 143, 355, 676, 1113, 1673,\n                                   2361, 3181, 4139, 5237, 6479, 7869,\n                                   9409, 11103, 12952, 14961, 17130,\n                                   19462, 21960, 24626, 27461, 30467,\n                                   33647, 37003, 40535, 44245, 48136,\n                                   52209, 56466, 60907, 65535 };\n\nstatic unsigned short ipow(unsigned short val, unsigned short lut[])\n{\n  int idx = val >> (16-5);\n  int a, b;\n\n  if (val < 0x8000) {\n    a = lut[idx];\n    b = lut[idx+1];\n  } else {\n    a = lut[idx-1];\n    b = lut[idx];\n  }\n\n  return (val & 0x7ff) * (b-a) / 0x7ff + a;\n}\n\nstatic unsigned short srgb_to_lin(unsigned char srgb)\n{\n  return ipow((unsigned)srgb * 65535 / 255, pow223);\n}\n\n// Floyd-Steinberg dithering\nstatic void dither(int width, int height, int32_t* data)\n{\n  for (int y = 0; y < height; y++) {\n    for (int x_ = 0; x_ < width; x_++) {\n      int x = (y & 1) ? (width - x_ - 1) : x_;\n      int error;\n\n      if (data[x] > 32767) {\n        error = data[x] - 65535;\n        data[x] = 65535;\n      } else {\n        error = data[x] - 0;\n        data[x] = 0;\n      }\n\n      if (y & 1) {\n        if (x > 0) {\n          data[x - 1] += error * 7 / 16;\n        }\n        if ((y + 1) < height) {\n          if (x > 0)\n            data[x - 1 + width] += error * 3 / 16;\n          data[x + width] += error * 5 / 16;\n          if ((x + 1) < width)\n            data[x + 1] += error * 1 / 16;\n        }\n      } else {\n        if ((x + 1) < width) {\n          data[x + 1] += error * 7 / 16;\n        }\n        if ((y + 1) < height) {\n          if ((x + 1) < width)\n            data[x + 1 + width] += error * 3 / 16;\n          data[x + width] += error * 5 / 16;\n          if (x > 0)\n            data[x - 1] += error * 1 / 16;\n        }\n      }\n    }\n    data += width;\n  }\n}\n\nstd::vector<uint8_t> Cursor::getBitmap() const\n{\n  // First step is converting to luminance\n  std::vector<int32_t> luminance(width()*height());\n  int32_t *lum_ptr = luminance.data();\n  const uint8_t *data_ptr = data;\n  for (int y = 0; y < height(); y++) {\n    for (int x = 0; x < width(); x++) {\n      int32_t lum;\n\n      // Use BT.709 coefficients for grayscale\n      lum = 0;\n      lum += (uint32_t)srgb_to_lin(data_ptr[0]) * 6947;  // 0.2126\n      lum += (uint32_t)srgb_to_lin(data_ptr[1]) * 23436; // 0.7152\n      lum += (uint32_t)srgb_to_lin(data_ptr[2]) * 2366;  // 0.0722\n      lum /= 32768;\n\n      *lum_ptr++ = lum;\n      data_ptr += 4;\n    }\n  }\n\n  // Then diterhing\n  dither(width(), height(), luminance.data());\n\n  // Then conversion to a bit mask\n  std::vector<uint8_t> source((width()+7)/8*height());\n  memset(source.data(), 0, source.size());\n  int maskBytesPerRow = (width() + 7) / 8;\n  lum_ptr = luminance.data();\n  data_ptr = data;\n  for (int y = 0; y < height(); y++) {\n    for (int x = 0; x < width(); x++) {\n      int byte = y * maskBytesPerRow + x / 8;\n      int bit = 7 - x % 8;\n      if (*lum_ptr > 32767)\n        source[byte] |= (1 << bit);\n      lum_ptr++;\n      data_ptr += 4;\n    }\n  }\n\n  return source;\n}\n\nstd::vector<uint8_t> Cursor::getMask() const\n{\n  // First step is converting to integer array\n  std::vector<int32_t> alpha(width()*height());\n  int32_t *alpha_ptr = alpha.data();\n  const uint8_t *data_ptr = data;\n  for (int y = 0; y < height(); y++) {\n    for (int x = 0; x < width(); x++) {\n      *alpha_ptr++ = (uint32_t)data_ptr[3] * 65535 / 255;\n      data_ptr += 4;\n    }\n  }\n\n  // Then diterhing\n  dither(width(), height(), alpha.data());\n\n  // Then conversion to a bit mask\n  std::vector<uint8_t> mask((width()+7)/8*height());\n  memset(mask.data(), 0, mask.size());\n  int maskBytesPerRow = (width() + 7) / 8;\n  alpha_ptr = alpha.data();\n  data_ptr = data;\n  for (int y = 0; y < height(); y++) {\n    for (int x = 0; x < width(); x++) {\n      int byte = y * maskBytesPerRow + x / 8;\n      int bit = 7 - x % 8;\n      if (*alpha_ptr > 32767)\n        mask[byte] |= (1 << bit);\n      alpha_ptr++;\n      data_ptr += 4;\n    }\n  }\n\n  return mask;\n}\n\n// crop() determines the \"busy\" rectangle for the cursor - the minimum bounding\n// rectangle containing actual pixels.  This isn't the most efficient algorithm\n// but it's short.  For sanity, we make sure that the busy rectangle always\n// includes the hotspot (the hotspot is unsigned on the wire so otherwise it\n// would cause problems if it was above or left of the actual pixels)\n\nvoid Cursor::crop()\n{\n  core::Rect busy(0, 0, width_, height_);\n  busy = busy.intersect({hotspot_.x, hotspot_.y,\n                         hotspot_.x+1, hotspot_.y+1});\n  int x, y;\n  uint8_t *data_ptr = data;\n  for (y = 0; y < height(); y++) {\n    for (x = 0; x < width(); x++) {\n      if (data_ptr[3] > 0) {\n        if (x < busy.tl.x) busy.tl.x = x;\n        if (x+1 > busy.br.x) busy.br.x = x+1;\n        if (y < busy.tl.y) busy.tl.y = y;\n        if (y+1 > busy.br.y) busy.br.y = y+1;\n      }\n      data_ptr += 4;\n    }\n  }\n\n  if (width() == busy.width() && height() == busy.height()) return;\n\n  // Copy the pixel data\n  int newDataLen = busy.area() * 4;\n  uint8_t* newData = new uint8_t[newDataLen];\n  data_ptr = newData;\n  for (y = busy.tl.y; y < busy.br.y; y++) {\n    memcpy(data_ptr, data + y*width()*4 + busy.tl.x*4, busy.width()*4);\n    data_ptr += busy.width()*4;\n  }\n\n  // Set the size and data to the new, cropped cursor.\n  width_ = busy.width();\n  height_ = busy.height();\n  hotspot_ = hotspot_.subtract(busy.tl);\n  delete [] data;\n  data = newData;\n}\n\nRenderedCursor::RenderedCursor()\n{\n}\n\nconst uint8_t* RenderedCursor::getBuffer(const core::Rect& _r,\n                                         int* stride) const\n{\n  core::Rect r;\n\n  r = _r.translate(offset.negate());\n  if (!r.enclosed_by(buffer.getRect()))\n    throw std::out_of_range(\"RenderedCursor: Invalid area requested\");\n\n  return buffer.getBuffer(r, stride);\n}\n\nvoid RenderedCursor::update(PixelBuffer* framebuffer,\n                            Cursor* cursor, const core::Point& pos)\n{\n  core::Point rawOffset, diff;\n  core::Rect clippedRect;\n\n  const uint8_t* data;\n  int stride;\n\n  assert(framebuffer);\n  assert(cursor);\n\n  format = framebuffer->getPF();\n  setSize(framebuffer->width(), framebuffer->height());\n\n  rawOffset = pos.subtract(cursor->hotspot());\n  clippedRect = core::Rect(0, 0, cursor->width(), cursor->height())\n                .translate(rawOffset)\n                .intersect(framebuffer->getRect());\n  offset = clippedRect.tl;\n\n  buffer.setPF(format);\n  buffer.setSize(clippedRect.width(), clippedRect.height());\n\n  // Bail out early to avoid pestering the framebuffer with\n  // bogus coordinates\n  if (clippedRect.area() == 0)\n    return;\n\n  data = framebuffer->getBuffer(buffer.getRect(offset), &stride);\n  buffer.imageRect(buffer.getRect(), data, stride);\n\n  diff = offset.subtract(rawOffset);\n  for (int y = 0;y < buffer.height();y++) {\n    for (int x = 0;x < buffer.width();x++) {\n      size_t idx;\n      uint8_t bg[4], fg[4];\n      uint8_t rgb[3];\n\n      idx = (y+diff.y)*cursor->width() + (x+diff.x);\n      memcpy(fg, cursor->getBuffer() + idx*4, 4);\n\n      if (fg[3] == 0x00)\n        continue;\n      else if (fg[3] == 0xff) {\n        memcpy(rgb, fg, 3);\n      } else {\n        buffer.getImage(bg, {x, y, x+1, y+1});\n        format.rgbFromBuffer(rgb, bg, 1);\n        // FIXME: Gamma aware blending\n        for (int i = 0;i < 3;i++) {\n          rgb[i] = (unsigned)rgb[i]*(255-fg[3])/255 +\n                   (unsigned)fg[i]*fg[3]/255;\n        }\n      }\n\n      format.bufferFromRGB(bg, rgb, 1);\n      buffer.imageRect({x, y, x+1, y+1}, bg);\n    }\n  }\n}\n"
  },
  {
    "path": "common/rfb/Cursor.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2023 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// Cursor - structure containing information describing\n//          the current cursor shape\n//\n\n#ifndef __RFB_CURSOR_H__\n#define __RFB_CURSOR_H__\n\n#include <vector>\n\n#include <core/Rect.h>\n\n#include <rfb/PixelBuffer.h>\n\nnamespace rfb {\n\n  class Cursor {\n  public:\n    Cursor(int width, int height, const core::Point& hotspot,\n           const uint8_t* data);\n    Cursor(const Cursor& other);\n    ~Cursor();\n\n    int width() const { return width_; };\n    int height() const { return height_; };\n    const core::Point& hotspot() const { return hotspot_; };\n    const uint8_t* getBuffer() const { return data; };\n\n    // getBitmap() returns a monochrome version of the cursor\n    std::vector<uint8_t> getBitmap() const;\n    // getMask() returns a simple mask version of the alpha channel\n    std::vector<uint8_t> getMask() const;\n\n    // crop() crops the cursor down to the smallest possible size, based on the\n    // mask.\n    void crop();\n\n  protected:\n    int width_, height_;\n    core::Point hotspot_;\n    uint8_t* data;\n  };\n\n  class RenderedCursor : public PixelBuffer {\n  public:\n    RenderedCursor();\n\n    core::Rect getEffectiveRect() const { return buffer.getRect(offset); }\n\n    const uint8_t* getBuffer(const core::Rect& r, int* stride) const override;\n\n    void update(PixelBuffer* framebuffer, Cursor* cursor,\n                const core::Point& pos);\n\n  protected:\n    ManagedPixelBuffer buffer;\n    core::Point offset;\n  };\n\n}\n#endif\n"
  },
  {
    "path": "common/rfb/DecodeManager.cxx",
    "content": "/* Copyright 2015 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <string.h>\n\n#include <core/LogWriter.h>\n#include <core/Region.h>\n#include <core/string.h>\n\n#include <rfb/CConnection.h>\n#include <rfb/DecodeManager.h>\n#include <rfb/Decoder.h>\n#include <rfb/Exception.h>\n\n#include <rdr/MemOutStream.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"DecodeManager\");\n\nDecodeManager::DecodeManager(CConnection *conn_) :\n  conn(conn_), partialEntry(nullptr), threadException(nullptr)\n{\n  size_t cpuCount;\n\n  memset(decoders, 0, sizeof(decoders));\n\n  memset(stats, 0, sizeof(stats));\n\n  cpuCount = std::thread::hardware_concurrency();\n  if (cpuCount == 0) {\n    vlog.error(\"Unable to determine the number of CPU cores on this system\");\n    cpuCount = 1;\n  } else {\n    vlog.info(\"Detected %d CPU core(s)\", (int)cpuCount);\n    // No point creating more threads than this, they'll just end up\n    // wasting CPU fighting for locks\n    if (cpuCount > 4)\n      cpuCount = 4;\n  }\n\n  vlog.info(\"Creating %d decoder thread(s)\", (int)cpuCount);\n\n  while (cpuCount--) {\n    // Twice as many possible entries in the queue as there\n    // are worker threads to make sure they don't stall\n    freeBuffers.push_back(new rdr::MemOutStream());\n    freeBuffers.push_back(new rdr::MemOutStream());\n\n    threads.push_back(new DecodeThread(this));\n  }\n}\n\nDecodeManager::~DecodeManager()\n{\n  logStats();\n\n  while (!threads.empty()) {\n    delete threads.back();\n    threads.pop_back();\n  }\n\n  while (!freeBuffers.empty()) {\n    delete freeBuffers.back();\n    freeBuffers.pop_back();\n  }\n\n  for (Decoder* decoder : decoders)\n    delete decoder;\n\n  delete partialEntry;\n}\n\nbool DecodeManager::decodeRect(const core::Rect& r, int encoding,\n                               ModifiablePixelBuffer* pb)\n{\n  int equiv;\n\n  assert(pb != nullptr);\n\n  if (partialEntry == nullptr) {\n    Decoder *decoder;\n    rdr::MemOutStream *bufferStream;\n\n    if (!Decoder::supported(encoding)) {\n      vlog.error(\"Unknown encoding %d\", encoding);\n      throw protocol_error(\"Unknown encoding\");\n    }\n\n    if (!decoders[encoding]) {\n      decoders[encoding] = Decoder::createDecoder(encoding);\n      if (!decoders[encoding]) {\n        vlog.error(\"Unknown encoding %d\", encoding);\n        throw protocol_error(\"Unknown encoding\");\n      }\n    }\n\n    decoder = decoders[encoding];\n\n    // Wait for an available memory buffer\n    std::unique_lock<std::mutex> lock(queueMutex);\n\n    // FIXME: Should we return and let other things run here?\n    while (freeBuffers.empty())\n      producerCond.wait(lock);\n\n    // Don't pop the buffer as we don't know if we'll finish filling it\n    // in a single round\n    bufferStream = freeBuffers.front();\n    bufferStream->clear();\n\n    lock.unlock();\n\n    partialEntry = new QueueEntry();\n\n    partialEntry->active = false;\n    partialEntry->rect = r;\n    partialEntry->encoding = encoding;\n    partialEntry->decoder = decoder;\n    partialEntry->server = &conn->server;\n    partialEntry->pb = pb;\n    partialEntry->bufferStream = bufferStream;\n\n    beforePos = conn->getInStream()->pos();\n  } else {\n    assert(partialEntry->rect == r);\n    assert(partialEntry->encoding == encoding);\n    assert(partialEntry->pb == pb);\n  }\n\n  // First check if any thread has encountered a problem\n  throwThreadException();\n\n  // Read the rect\n  if (!partialEntry->decoder->readRect(\n        partialEntry->rect, conn->getInStream(), conn->server,\n        partialEntry->bufferStream))\n    return false;\n\n  partialEntry->decoder->getAffectedRegion(\n    r, partialEntry->bufferStream->data(),\n    partialEntry->bufferStream->length(), conn->server,\n    &partialEntry->affectedRegion);\n\n  stats[encoding].rects++;\n  stats[encoding].bytes += 12 + conn->getInStream()->pos() - beforePos;\n  stats[encoding].pixels += r.area();\n  equiv = 12 + r.area() * (conn->server.pf().bpp/8);\n  stats[encoding].equivalent += equiv;\n\n  // Then try to put it on the queue\n\n  std::unique_lock<std::mutex> lock(queueMutex);\n\n  // The workers add buffers to the end so it's safe to assume\n  // the front is still the same buffer\n  freeBuffers.pop_front();\n\n  workQueue.push_back(partialEntry);\n  partialEntry = nullptr;\n\n  // We only put a single entry on the queue so waking a single\n  // thread is sufficient\n  consumerCond.notify_one();\n\n  lock.unlock();\n\n  return true;\n}\n\nvoid DecodeManager::flush()\n{\n  std::unique_lock<std::mutex> lock(queueMutex);\n\n  while (!workQueue.empty())\n    producerCond.wait(lock);\n\n  lock.unlock();\n\n  throwThreadException();\n}\n\nvoid DecodeManager::logStats()\n{\n  size_t i;\n\n  unsigned rects;\n  unsigned long long pixels, bytes, equivalent;\n\n  double ratio;\n\n  rects = 0;\n  pixels = bytes = equivalent = 0;\n\n  for (i = 0;i < (sizeof(stats)/sizeof(stats[0]));i++) {\n    // Did this class do anything at all?\n    if (stats[i].rects == 0)\n      continue;\n\n    rects += stats[i].rects;\n    pixels += stats[i].pixels;\n    bytes += stats[i].bytes;\n    equivalent += stats[i].equivalent;\n\n    ratio = (double)stats[i].equivalent / stats[i].bytes;\n\n    vlog.info(\"    %s: %s, %s\", encodingName(i),\n              core::siPrefix(stats[i].rects, \"rects\").c_str(),\n              core::siPrefix(stats[i].pixels, \"pixels\").c_str());\n    vlog.info(\"    %*s  %s (1:%g ratio)\",\n              (int)strlen(encodingName(i)), \"\",\n              core::iecPrefix(stats[i].bytes, \"B\").c_str(), ratio);\n  }\n\n  ratio = (double)equivalent / bytes;\n\n  vlog.info(\"  Total: %s, %s\",\n            core::siPrefix(rects, \"rects\").c_str(),\n            core::siPrefix(pixels, \"pixels\").c_str());\n  vlog.info(\"         %s (1:%g ratio)\",\n            core::iecPrefix(bytes, \"B\").c_str(), ratio);\n}\n\nvoid DecodeManager::setThreadException()\n{\n  const std::lock_guard<std::mutex> lock(queueMutex);\n\n  if (threadException)\n    return;\n\n  threadException = std::current_exception();\n}\n\nvoid DecodeManager::throwThreadException()\n{\n  const std::lock_guard<std::mutex> lock(queueMutex);\n\n  if (!threadException)\n    return;\n\n  try {\n    std::rethrow_exception(threadException);\n  } catch (...) {\n    threadException = nullptr;\n    throw;\n  }\n}\n\nDecodeManager::DecodeThread::DecodeThread(DecodeManager* manager_)\n  : manager(manager_), thread(nullptr), stopRequested(false)\n{\n  start();\n}\n\nDecodeManager::DecodeThread::~DecodeThread()\n{\n  stop();\n  if (thread != nullptr) {\n    thread->join();\n    delete thread;\n  }\n}\n\nvoid DecodeManager::DecodeThread::start()\n{\n  assert(thread == nullptr);\n\n  thread = new std::thread(&DecodeThread::worker, this);\n}\n\nvoid DecodeManager::DecodeThread::stop()\n{\n  const std::lock_guard<std::mutex> lock(manager->queueMutex);\n\n  if (thread == nullptr)\n    return;\n\n  stopRequested = true;\n\n  // We can't wake just this thread, so wake everyone\n  manager->consumerCond.notify_all();\n}\n\nvoid DecodeManager::DecodeThread::worker()\n{\n  std::unique_lock<std::mutex> lock(manager->queueMutex);\n\n  while (!stopRequested) {\n    DecodeManager::QueueEntry *entry;\n\n    // Look for an available entry in the work queue\n    entry = findEntry();\n    if (entry == nullptr) {\n      // Wait and try again\n      manager->consumerCond.wait(lock);\n      continue;\n    }\n\n    // This is ours now\n    entry->active = true;\n\n    lock.unlock();\n\n    // Do the actual decoding\n    try {\n      entry->decoder->decodeRect(entry->rect, entry->bufferStream->data(),\n                                 entry->bufferStream->length(),\n                                 *entry->server, entry->pb);\n    } catch (std::exception& e) {\n      manager->setThreadException();\n    } catch(...) {\n      assert(false);\n    }\n\n    lock.lock();\n\n    // Remove the entry from the queue and give back the memory buffer\n    manager->freeBuffers.push_back(entry->bufferStream);\n    manager->workQueue.remove(entry);\n    delete entry;\n\n    // Wake the main thread in case it is waiting for a memory buffer\n    manager->producerCond.notify_one();\n    // This rect might have been blocking multiple other rects, so\n    // wake up every worker thread\n    if (manager->workQueue.size() > 1)\n      manager->consumerCond.notify_all();\n  }\n}\n\nDecodeManager::QueueEntry* DecodeManager::DecodeThread::findEntry()\n{\n  core::Region lockedRegion;\n\n  if (manager->workQueue.empty())\n    return nullptr;\n\n  if (!manager->workQueue.front()->active)\n    return manager->workQueue.front();\n\n  for (DecodeManager::QueueEntry* entry : manager->workQueue) {\n    // Another thread working on this?\n    if (entry->active)\n      goto next;\n\n    // If this is an ordered decoder then make sure this is the first\n    // rectangle in the queue for that decoder\n    if (entry->decoder->flags & DecoderOrdered) {\n      for (DecodeManager::QueueEntry* entry2 : manager->workQueue) {\n        if (entry2 == entry)\n          break;\n        if (entry->encoding == entry2->encoding)\n          goto next;\n      }\n    }\n\n    // For a partially ordered decoder we must ask the decoder for each\n    // pair of rectangles.\n    if (entry->decoder->flags & DecoderPartiallyOrdered) {\n      for (DecodeManager::QueueEntry* entry2 : manager->workQueue) {\n        if (entry2 == entry)\n          break;\n        if (entry->encoding != entry2->encoding)\n          continue;\n        if (entry->decoder->doRectsConflict(entry->rect,\n                                            entry->bufferStream->data(),\n                                            entry->bufferStream->length(),\n                                            entry2->rect,\n                                            entry2->bufferStream->data(),\n                                            entry2->bufferStream->length(),\n                                            *entry->server))\n          goto next;\n      }\n    }\n\n    // Check overlap with earlier rectangles\n    if (!lockedRegion.intersect(entry->affectedRegion).is_empty())\n      goto next;\n\n    return entry;\n\nnext:\n    lockedRegion.assign_union(entry->affectedRegion);\n  }\n\n  return nullptr;\n}\n"
  },
  {
    "path": "common/rfb/DecodeManager.h",
    "content": "/* Copyright 2015 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_DECODEMANAGER_H__\n#define __RFB_DECODEMANAGER_H__\n\n#include <condition_variable>\n#include <exception>\n#include <list>\n#include <mutex>\n#include <thread>\n\n#include <core/Region.h>\n\n#include <rfb/encodings.h>\n\nnamespace core {\n  struct Rect;\n}\n\nnamespace rdr {\n  class MemOutStream;\n}\n\nnamespace rfb {\n\n  class CConnection;\n  class Decoder;\n  class ModifiablePixelBuffer;\n\n  class DecodeManager {\n  public:\n    DecodeManager(CConnection *conn);\n    ~DecodeManager();\n\n    bool decodeRect(const core::Rect& r, int encoding,\n                    ModifiablePixelBuffer* pb);\n\n    void flush();\n\n  private:\n    void logStats();\n\n    void setThreadException();\n    void throwThreadException();\n\n  private:\n    CConnection *conn;\n    Decoder *decoders[encodingMax+1];\n\n    struct DecoderStats {\n      unsigned rects;\n      unsigned long long bytes;\n      unsigned long long pixels;\n      unsigned long long equivalent;\n    };\n\n    DecoderStats stats[encodingMax+1];\n    size_t beforePos;\n\n    struct QueueEntry {\n      bool active;\n      core::Rect rect;\n      int encoding;\n      Decoder* decoder;\n      const ServerParams* server;\n      ModifiablePixelBuffer* pb;\n      rdr::MemOutStream* bufferStream;\n      core::Region affectedRegion;\n    };\n\n    std::list<rdr::MemOutStream*> freeBuffers;\n    std::list<QueueEntry*> workQueue;\n    QueueEntry* partialEntry;\n\n    std::mutex queueMutex;\n    std::condition_variable producerCond;\n    std::condition_variable consumerCond;\n\n  private:\n    class DecodeThread {\n    public:\n      DecodeThread(DecodeManager* manager);\n      ~DecodeThread();\n\n      void start();\n      void stop();\n\n    protected:\n      void worker();\n      DecodeManager::QueueEntry* findEntry();\n\n    private:\n      DecodeManager* manager;\n\n      std::thread* thread;\n      bool stopRequested;\n    };\n\n    std::list<DecodeThread*> threads;\n    std::exception_ptr threadException;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/Decoder.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n\n#include <core/Region.h>\n\n#include <rfb/encodings.h>\n#include <rfb/Decoder.h>\n#include <rfb/RawDecoder.h>\n#include <rfb/CopyRectDecoder.h>\n#include <rfb/RREDecoder.h>\n#include <rfb/HextileDecoder.h>\n#include <rfb/JPEGDecoder.h>\n#include <rfb/ZRLEDecoder.h>\n#include <rfb/TightDecoder.h>\n#ifdef HAVE_H264\n#include <rfb/H264Decoder.h>\n#endif\n\nusing namespace rfb;\n\nDecoder::Decoder(enum DecoderFlags flags_) : flags(flags_)\n{\n}\n\nDecoder::~Decoder()\n{\n}\n\nvoid Decoder::getAffectedRegion(const core::Rect& rect,\n                                const uint8_t* /*buffer*/,\n                                size_t /*buflen*/,\n                                const ServerParams& /*server*/,\n                                core::Region* region)\n{\n  region->reset(rect);\n}\n\nbool Decoder::doRectsConflict(const core::Rect& /*rectA*/,\n                              const uint8_t* /*bufferA*/,\n                              size_t /*buflenA*/,\n                              const core::Rect& /*rectB*/,\n                              const uint8_t* /*bufferB*/,\n                              size_t /*buflenB*/,\n                              const ServerParams& /*server*/)\n{\n  return false;\n}\n\nbool Decoder::supported(int encoding)\n{\n  switch (encoding) {\n  case encodingRaw:\n  case encodingCopyRect:\n  case encodingRRE:\n  case encodingHextile:\n  case encodingJPEG:\n  case encodingZRLE:\n  case encodingTight:\n#ifdef HAVE_H264\n  case encodingH264:\n#endif\n    return true;\n  default:\n    return false;\n  }\n}\n\nDecoder* Decoder::createDecoder(int encoding)\n{\n  switch (encoding) {\n  case encodingRaw:\n    return new RawDecoder();\n  case encodingCopyRect:\n    return new CopyRectDecoder();\n  case encodingRRE:\n    return new RREDecoder();\n  case encodingHextile:\n    return new HextileDecoder();\n  case encodingJPEG:\n    return new JPEGDecoder();\n  case encodingZRLE:\n    return new ZRLEDecoder();\n  case encodingTight:\n    return new TightDecoder();\n#ifdef HAVE_H264\n  case encodingH264:\n    return new H264Decoder();\n#endif\n  default:\n    return nullptr;\n  }\n}\n"
  },
  {
    "path": "common/rfb/Decoder.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_DECODER_H__\n#define __RFB_DECODER_H__\n\n#include <stddef.h>\n#include <stdint.h>\n\nnamespace core {\n  class Region;\n  struct Rect;\n}\n\nnamespace rdr {\n  class InStream;\n  class OutStream;\n}\n\nnamespace rfb {\n\n  class ServerParams;\n  class ModifiablePixelBuffer;\n\n  enum DecoderFlags {\n    // A constant for decoders that don't need anything special\n    DecoderPlain = 0,\n    // All rects for this decoder must be handled in order\n    DecoderOrdered = 1 << 0,\n    // Only some of the rects must be handled in order,\n    // see doesRectsConflict()\n    DecoderPartiallyOrdered = 1 << 1,\n  };\n\n  class Decoder {\n  public:\n    Decoder(enum DecoderFlags flags);\n    virtual ~Decoder();\n\n    // These functions are the main interface to an individual decoder\n\n    // readRect() transfers data for the given rectangle from the\n    // InStream to the OutStream, possibly changing it along the way to\n    // make it easier to decode. This function will always be called in\n    // a serial manner on the main thread.\n    virtual bool readRect(const core::Rect& r, rdr::InStream* is,\n                          const ServerParams& server, rdr::OutStream* os)=0;\n\n    // These functions will be called from any of the worker threads.\n    // A lock will be held whilst these are called so it is safe to\n    // read and update internal state as necessary.\n\n    // getAffectedRegion() returns the parts of the frame buffer will\n    // be either read from or written do when decoding this rect. The\n    // default implementation simply returns the given rectangle.\n    virtual void getAffectedRegion(const core::Rect& rect, const uint8_t* buffer,\n                                   size_t buflen, const ServerParams& server,\n                                   core::Region* region);\n\n    // doesRectsConflict() determines if two rectangles must be decoded\n    // in the order they were received. This will only be called if the\n    // DecoderPartiallyOrdered flag has been set.\n    virtual bool doRectsConflict(const core::Rect& rectA,\n                                 const uint8_t* bufferA,\n                                 size_t buflenA,\n                                 const core::Rect& rectB,\n                                 const uint8_t* bufferB,\n                                 size_t buflenB,\n                                 const ServerParams& server);\n\n    // decodeRect() decodes the given rectangle with data from the\n    // given buffer, onto the ModifiablePixelBuffer. The PixelFormat of\n    // the PixelBuffer might not match the ConnParams and it is up to\n    // the decoder to do any necessary conversion.\n    virtual void decodeRect(const core::Rect& r, const uint8_t* buffer,\n                            size_t buflen, const ServerParams& server,\n                            ModifiablePixelBuffer* pb)=0;\n\n  public:\n    static bool supported(int encoding);\n    static Decoder* createDecoder(int encoding);\n\n  public:\n    const enum DecoderFlags flags;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/EncodeManager.cxx",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014-2025 Pierre Ossman for Cendio AB\n * Copyright 2018 Peter Astrand for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdlib.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb/Cursor.h>\n#include <rfb/EncodeManager.h>\n#include <rfb/Encoder.h>\n#include <rfb/Palette.h>\n#include <rfb/SConnection.h>\n#include <rfb/SMsgWriter.h>\n#include <rfb/UpdateTracker.h>\n#include <rfb/encodings.h>\n\n#include <rfb/RawEncoder.h>\n#include <rfb/RREEncoder.h>\n#include <rfb/HextileEncoder.h>\n#include <rfb/JPEGEncoder.h>\n#include <rfb/ZRLEEncoder.h>\n#include <rfb/TightEncoder.h>\n#include <rfb/TightJPEGEncoder.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"EncodeManager\");\n\n// Split each rectangle into smaller ones no larger than this area,\n// and no wider than this width.\nstatic const int SubRectMaxArea = 65536;\nstatic const int SubRectMaxWidth = 2048;\n\n// The size in pixels of either side of each block tested when looking\n// for solid blocks.\nstatic const int SolidSearchBlock = 16;\n// Don't bother with blocks smaller than this\nstatic const int SolidBlockMinArea = 2048;\n\n// How long we consider a region recently changed (in ms)\nstatic const int RecentChangeTimeout = 50;\n\nnamespace rfb {\n\nenum EncoderClass {\n  encoderRaw,\n  encoderRRE,\n  encoderHextile,\n  encoderTight,\n  encoderTightJPEG,\n  encoderZRLE,\n  encoderJPEG,\n  encoderClassMax,\n};\n\nenum EncoderType {\n  encoderSolid,\n  encoderBitmap,\n  encoderBitmapRLE,\n  encoderIndexed,\n  encoderIndexedRLE,\n  encoderFullColour,\n  encoderTypeMax,\n};\n\nstruct RectInfo {\n  int rleRuns;\n  Palette palette;\n};\n\n};\n\nstatic const char *encoderClassName(EncoderClass klass)\n{\n  switch (klass) {\n  case encoderRaw:\n    return \"Raw\";\n  case encoderRRE:\n    return \"RRE\";\n  case encoderHextile:\n    return \"Hextile\";\n  case encoderTight:\n    return \"Tight\";\n  case encoderTightJPEG:\n    return \"Tight (JPEG)\";\n  case encoderZRLE:\n    return \"ZRLE\";\n  case encoderJPEG:\n    return \"JPEG\";\n  case encoderClassMax:\n    break;\n  }\n\n  return \"Unknown Encoder Class\";\n}\n\nstatic const char *encoderTypeName(EncoderType type)\n{\n  switch (type) {\n  case encoderSolid:\n    return \"Solid\";\n  case encoderBitmap:\n    return \"Bitmap\";\n  case encoderBitmapRLE:\n    return \"Bitmap RLE\";\n  case encoderIndexed:\n    return \"Indexed\";\n  case encoderIndexedRLE:\n    return \"Indexed RLE\";\n  case encoderFullColour:\n    return \"Full Colour\";\n  case encoderTypeMax:\n    break;\n  }\n\n  return \"Unknown Encoder Type\";\n}\n\nEncodeManager::EncodeManager(SConnection* conn_)\n  : conn(conn_), recentChangeTimer(this)\n{\n  StatsVector::iterator iter;\n\n  encoders.resize(encoderClassMax, nullptr);\n  activeEncoders.resize(encoderTypeMax, encoderRaw);\n\n  encoders[encoderRaw] = new RawEncoder(conn);\n  encoders[encoderRRE] = new RREEncoder(conn);\n  encoders[encoderHextile] = new HextileEncoder(conn);\n  encoders[encoderTight] = new TightEncoder(conn);\n  encoders[encoderTightJPEG] = new TightJPEGEncoder(conn);\n  encoders[encoderZRLE] = new ZRLEEncoder(conn);\n  encoders[encoderJPEG] = new JPEGEncoder(conn);\n\n  updates = 0;\n  memset(&copyStats, 0, sizeof(copyStats));\n  stats.resize(encoderClassMax);\n  for (iter = stats.begin();iter != stats.end();++iter) {\n    StatsVector::value_type::iterator iter2;\n    iter->resize(encoderTypeMax);\n    for (iter2 = iter->begin();iter2 != iter->end();++iter2)\n      memset(&*iter2, 0, sizeof(EncoderStats));\n  }\n}\n\nEncodeManager::~EncodeManager()\n{\n  logStats();\n\n  for (Encoder* encoder : encoders)\n    delete encoder;\n}\n\nvoid EncodeManager::logStats()\n{\n  size_t i, j;\n\n  unsigned rects;\n  unsigned long long pixels, bytes, equivalent;\n\n  double ratio;\n\n  rects = 0;\n  pixels = bytes = equivalent = 0;\n\n  vlog.info(\"Framebuffer updates: %u\", updates);\n\n  if (copyStats.rects != 0) {\n    vlog.info(\"  %s:\", \"CopyRect\");\n\n    rects += copyStats.rects;\n    pixels += copyStats.pixels;\n    bytes += copyStats.bytes;\n    equivalent += copyStats.equivalent;\n\n    ratio = (double)copyStats.equivalent / copyStats.bytes;\n\n    vlog.info(\"    %s: %s, %s\", \"Copies\",\n              core::siPrefix(copyStats.rects, \"rects\").c_str(),\n              core::siPrefix(copyStats.pixels, \"pixels\").c_str());\n    vlog.info(\"    %*s  %s (1:%g ratio)\",\n              (int)strlen(\"Copies\"), \"\",\n              core::iecPrefix(copyStats.bytes, \"B\").c_str(), ratio);\n  }\n\n  for (i = 0;i < stats.size();i++) {\n    // Did this class do anything at all?\n    for (j = 0;j < stats[i].size();j++) {\n      if (stats[i][j].rects != 0)\n        break;\n    }\n    if (j == stats[i].size())\n      continue;\n\n    vlog.info(\"  %s:\", encoderClassName((EncoderClass)i));\n\n    for (j = 0;j < stats[i].size();j++) {\n      if (stats[i][j].rects == 0)\n        continue;\n\n      rects += stats[i][j].rects;\n      pixels += stats[i][j].pixels;\n      bytes += stats[i][j].bytes;\n      equivalent += stats[i][j].equivalent;\n\n      ratio = (double)stats[i][j].equivalent / stats[i][j].bytes;\n\n      vlog.info(\"    %s: %s, %s\", encoderTypeName((EncoderType)j),\n                core::siPrefix(stats[i][j].rects, \"rects\").c_str(),\n                core::siPrefix(stats[i][j].pixels, \"pixels\").c_str());\n      vlog.info(\"    %*s  %s (1:%g ratio)\",\n                (int)strlen(encoderTypeName((EncoderType)j)), \"\",\n                core::iecPrefix(stats[i][j].bytes, \"B\").c_str(), ratio);\n    }\n  }\n\n  ratio = (double)equivalent / bytes;\n\n  vlog.info(\"  Total: %s, %s\",\n            core::siPrefix(rects, \"rects\").c_str(),\n            core::siPrefix(pixels, \"pixels\").c_str());\n  vlog.info(\"         %s (1:%g ratio)\",\n            core::iecPrefix(bytes, \"B\").c_str(), ratio);\n}\n\nbool EncodeManager::supported(int encoding)\n{\n  switch (encoding) {\n  case encodingRaw:\n  case encodingRRE:\n  case encodingHextile:\n  case encodingJPEG:\n  case encodingZRLE:\n  case encodingTight:\n    return true;\n  default:\n    return false;\n  }\n}\n\nbool EncodeManager::needsLosslessRefresh(const core::Region& req)\n{\n  return !lossyRegion.intersect(req).is_empty();\n}\n\nint EncodeManager::getNextLosslessRefresh(const core::Region& req)\n{\n  // Do we have something we can send right away?\n  if (!pendingRefreshRegion.intersect(req).is_empty())\n    return 0;\n\n  assert(needsLosslessRefresh(req));\n  assert(recentChangeTimer.isStarted());\n\n  return recentChangeTimer.getNextTimeout();\n}\n\nvoid EncodeManager::pruneLosslessRefresh(const core::Region& limits)\n{\n  lossyRegion.assign_intersect(limits);\n  pendingRefreshRegion.assign_intersect(limits);\n}\n\nvoid EncodeManager::forceRefresh(const core::Region& req)\n{\n  lossyRegion.assign_union(req);\n  if (!recentChangeTimer.isStarted())\n    pendingRefreshRegion.assign_union(req);\n}\n\nvoid EncodeManager::writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb,\n                                const RenderedCursor* renderedCursor)\n{\n  doUpdate(true, ui.changed, ui.copied, ui.copy_delta, pb, renderedCursor);\n\n  recentlyChangedRegion.assign_union(ui.changed);\n  recentlyChangedRegion.assign_union(ui.copied);\n  if (!recentChangeTimer.isStarted())\n    recentChangeTimer.start(RecentChangeTimeout);\n}\n\nvoid EncodeManager::writeLosslessRefresh(const core::Region& req,\n                                         const PixelBuffer* pb,\n                                         const RenderedCursor* renderedCursor,\n                                         size_t maxUpdateSize)\n{\n  doUpdate(false, getLosslessRefresh(req, maxUpdateSize),\n           {}, {}, pb, renderedCursor);\n}\n\nvoid EncodeManager::handleTimeout(core::Timer* t)\n{\n  if (t == &recentChangeTimer) {\n    // Any lossy region that wasn't recently updated can\n    // now be scheduled for a refresh\n    pendingRefreshRegion.assign_union(lossyRegion.subtract(recentlyChangedRegion));\n    recentlyChangedRegion.clear();\n\n    // Will there be more to do? (i.e. do we need another round)\n    if (!lossyRegion.subtract(pendingRefreshRegion).is_empty())\n      t->repeat();\n  }\n}\n\nvoid EncodeManager::doUpdate(bool allowLossy, const\n                             core::Region& changed_,\n                             const core::Region& copied,\n                             const core::Point& copyDelta,\n                             const PixelBuffer* pb,\n                             const RenderedCursor* renderedCursor)\n{\n    int nRects;\n    core::Region changed, cursorRegion;\n\n    updates++;\n\n    prepareEncoders(allowLossy);\n\n    changed = changed_;\n\n    if (!conn->client.supportsEncoding(encodingCopyRect))\n      changed.assign_union(copied);\n\n    /*\n     * We need to render the cursor seperately as it has its own\n     * magical pixel buffer, so split it out from the changed region.\n     */\n    if (renderedCursor != nullptr) {\n      cursorRegion = changed.intersect(renderedCursor->getEffectiveRect());\n      changed.assign_subtract(renderedCursor->getEffectiveRect());\n    }\n\n    if (conn->client.supportsEncoding(pseudoEncodingLastRect))\n      nRects = 0xFFFF;\n    else {\n      nRects = 0;\n      if (conn->client.supportsEncoding(encodingCopyRect))\n        nRects += copied.numRects();\n      nRects += computeNumRects(changed);\n      nRects += computeNumRects(cursorRegion);\n    }\n\n    conn->writer()->writeFramebufferUpdateStart(nRects);\n\n    if (conn->client.supportsEncoding(encodingCopyRect))\n      writeCopyRects(copied, copyDelta);\n\n    /*\n     * We start by searching for solid rects, which are then removed\n     * from the changed region.\n     */\n    if (conn->client.supportsEncoding(pseudoEncodingLastRect))\n      writeSolidRects(&changed, pb);\n\n    writeRects(changed, pb);\n    writeRects(cursorRegion, renderedCursor);\n\n    conn->writer()->writeFramebufferUpdateEnd();\n}\n\nvoid EncodeManager::prepareEncoders(bool allowLossy)\n{\n  enum EncoderClass solid, bitmap, bitmapRLE;\n  enum EncoderClass indexed, indexedRLE, fullColour;\n\n  int32_t preferred;\n\n  std::vector<int>::iterator iter;\n\n  solid = bitmap = bitmapRLE = encoderRaw;\n  indexed = indexedRLE = fullColour = encoderRaw;\n\n  // Try to respect the client's wishes\n  preferred = conn->getPreferredEncoding();\n  switch (preferred) {\n  case encodingRRE:\n    // Horrible for anything high frequency and/or lots of colours\n    bitmapRLE = indexedRLE = encoderRRE;\n    break;\n  case encodingHextile:\n    // Slightly less horrible\n    bitmapRLE = indexedRLE = fullColour = encoderHextile;\n    break;\n  case encodingTight:\n    // Prefer the plain JPEG encoder as it compresses better\n    if (encoders[encoderJPEG]->isSupported())\n      fullColour = encoderJPEG;\n    else if (encoders[encoderTightJPEG]->isSupported())\n      fullColour = encoderTightJPEG;\n    else\n      fullColour = encoderTight;\n    indexed = indexedRLE = encoderTight;\n    bitmap = bitmapRLE = encoderTight;\n    break;\n  case encodingZRLE:\n    fullColour = encoderZRLE;\n    bitmapRLE = indexedRLE = encoderZRLE;\n    bitmap = indexed = encoderZRLE;\n    break;\n  case encodingJPEG:\n    fullColour = encoderJPEG;\n    break;\n  }\n\n  // JPEG is the only encoder that can reduce things to grayscale\n  if ((conn->client.subsampling == subsampleGray) && allowLossy) {\n    if (encoders[encoderJPEG]->isSupported()) {\n      solid = bitmap = bitmapRLE = encoderJPEG;\n      indexed = indexedRLE = fullColour = encoderJPEG;\n    } else if (encoders[encoderTightJPEG]->isSupported()) {\n      solid = bitmap = bitmapRLE = encoderTightJPEG;\n      indexed = indexedRLE = fullColour = encoderTightJPEG;\n    }\n  }\n\n  // Can't use lossy encoders for lossless refresh\n  if (!allowLossy) {\n    if ((fullColour != encoderRaw) &&\n        (encoders[fullColour]->flags & EncoderLossy) &&\n        (encoders[fullColour]->losslessQuality == -1))\n      fullColour = encoderRaw;\n    if ((indexed != encoderRaw) &&\n        (encoders[indexed]->flags & EncoderLossy) &&\n        (encoders[indexed]->losslessQuality == -1))\n      indexed = encoderRaw;\n    if ((indexedRLE != encoderRaw) &&\n        (encoders[indexedRLE]->flags & EncoderLossy) &&\n        (encoders[indexedRLE]->losslessQuality == -1))\n      indexedRLE = encoderRaw;\n    if ((bitmap != encoderRaw) &&\n        (encoders[bitmap]->flags & EncoderLossy) &&\n        (encoders[bitmap]->losslessQuality == -1))\n      bitmap = encoderRaw;\n    if ((bitmapRLE != encoderRaw) &&\n        (encoders[bitmapRLE]->flags & EncoderLossy) &&\n        (encoders[bitmapRLE]->losslessQuality == -1))\n      bitmapRLE = encoderRaw;\n  }\n\n  // Any encoders still unassigned?\n\n  if (fullColour == encoderRaw) {\n    if (encoders[encoderJPEG]->isSupported() &&\n        (allowLossy || encoders[encoderJPEG]->losslessQuality != -1))\n      fullColour = encoderJPEG;\n    else if (encoders[encoderTightJPEG]->isSupported() &&\n             (allowLossy ||\n              encoders[encoderTightJPEG]->losslessQuality != -1))\n      fullColour = encoderTightJPEG;\n    else if (encoders[encoderZRLE]->isSupported())\n      fullColour = encoderZRLE;\n    else if (encoders[encoderTight]->isSupported())\n      fullColour = encoderTight;\n    else if (encoders[encoderHextile]->isSupported())\n      fullColour = encoderHextile;\n  }\n\n  if (indexed == encoderRaw) {\n    if (encoders[encoderZRLE]->isSupported())\n      indexed = encoderZRLE;\n    else if (encoders[encoderTight]->isSupported())\n      indexed = encoderTight;\n    else if (encoders[encoderHextile]->isSupported())\n      indexed = encoderHextile;\n  }\n\n  if (indexedRLE == encoderRaw)\n    indexedRLE = indexed;\n\n  if (bitmap == encoderRaw)\n    bitmap = indexed;\n  if (bitmapRLE == encoderRaw)\n    bitmapRLE = bitmap;\n\n  if (solid == encoderRaw) {\n    if (encoders[encoderTight]->isSupported())\n      solid = encoderTight;\n    else if (encoders[encoderRRE]->isSupported())\n      solid = encoderRRE;\n    else if (encoders[encoderZRLE]->isSupported())\n      solid = encoderZRLE;\n    else if (encoders[encoderHextile]->isSupported())\n      solid = encoderHextile;\n  }\n\n  activeEncoders[encoderSolid] = solid;\n  activeEncoders[encoderBitmap] = bitmap;\n  activeEncoders[encoderBitmapRLE] = bitmapRLE;\n  activeEncoders[encoderIndexed] = indexed;\n  activeEncoders[encoderIndexedRLE] = indexedRLE;\n  activeEncoders[encoderFullColour] = fullColour;\n\n  for (iter = activeEncoders.begin(); iter != activeEncoders.end(); ++iter) {\n    Encoder *encoder;\n\n    encoder = encoders[*iter];\n\n    encoder->setCompressLevel(conn->client.compressLevel);\n\n    if (allowLossy) {\n      encoder->setQualityLevel(conn->client.qualityLevel);\n      encoder->setFineQualityLevel(conn->client.fineQualityLevel,\n                                   conn->client.subsampling);\n    } else {\n      if (conn->client.qualityLevel < encoder->losslessQuality)\n        encoder->setQualityLevel(encoder->losslessQuality);\n      else\n        encoder->setQualityLevel(conn->client.qualityLevel);\n      encoder->setFineQualityLevel(-1, subsampleUndefined);\n    }\n  }\n}\n\ncore::Region EncodeManager::getLosslessRefresh(const core::Region& req,\n                                               size_t maxUpdateSize)\n{\n  std::vector<core::Rect> rects;\n  core::Region refresh;\n  size_t area;\n\n  // We make a conservative guess at the compression ratio at 2:1\n  maxUpdateSize *= 2;\n\n  // We will measure pixels, not bytes (assume 32 bpp)\n  maxUpdateSize /= 4;\n\n  area = 0;\n  pendingRefreshRegion.intersect(req).get_rects(&rects);\n  while (!rects.empty()) {\n    size_t idx;\n    core::Rect rect;\n\n    // Grab a random rect so we don't keep damaging and restoring the\n    // same rect over and over\n    idx = rand() % rects.size();\n\n    rect = rects[idx];\n\n    // Add rects until we exceed the threshold, then include as much as\n    // possible of the final rect\n    if ((area + rect.area()) > maxUpdateSize) {\n      // Use the narrowest axis to avoid getting to thin rects\n      if (rect.width() > rect.height()) {\n        int width = (maxUpdateSize - area) / rect.height();\n        if (width < 1)\n          width = 1;\n        rect.br.x = rect.tl.x + width;\n      } else {\n        int height = (maxUpdateSize - area) / rect.width();\n        if (height < 1)\n          height = 1;\n        rect.br.y = rect.tl.y + height;\n      }\n      refresh.assign_union(rect);\n      break;\n    }\n\n    area += rect.area();\n    refresh.assign_union(rect);\n\n    rects.erase(rects.begin() + idx);\n  }\n\n  return refresh;\n}\n\nint EncodeManager::computeNumRects(const core::Region& changed)\n{\n  int numRects;\n  std::vector<core::Rect> rects;\n  std::vector<core::Rect>::const_iterator rect;\n\n  numRects = 0;\n  changed.get_rects(&rects);\n  for (rect = rects.begin(); rect != rects.end(); ++rect) {\n    int w, h, sw, sh;\n\n    w = rect->width();\n    h = rect->height();\n\n    // No split necessary?\n    if (((w*h) < SubRectMaxArea) && (w < SubRectMaxWidth)) {\n      numRects += 1;\n      continue;\n    }\n\n    if (w <= SubRectMaxWidth)\n      sw = w;\n    else\n      sw = SubRectMaxWidth;\n\n    sh = SubRectMaxArea / sw;\n\n    // ceil(w/sw) * ceil(h/sh)\n    numRects += (((w - 1)/sw) + 1) * (((h - 1)/sh) + 1);\n  }\n\n  return numRects;\n}\n\nEncoder* EncodeManager::startRect(const core::Rect& rect, int type)\n{\n  Encoder *encoder;\n  int klass, equiv;\n\n  activeType = type;\n  klass = activeEncoders[activeType];\n\n  beforeLength = conn->getOutStream()->length();\n\n  stats[klass][activeType].rects++;\n  stats[klass][activeType].pixels += rect.area();\n  equiv = 12 + rect.area() * (conn->client.pf().bpp/8);\n  stats[klass][activeType].equivalent += equiv;\n\n  encoder = encoders[klass];\n  conn->writer()->startRect(rect, encoder->encoding);\n\n  if ((encoder->flags & EncoderLossy) &&\n      ((encoder->losslessQuality == -1) ||\n       (encoder->getQualityLevel() < encoder->losslessQuality)))\n    lossyRegion.assign_union(rect);\n  else\n    lossyRegion.assign_subtract(rect);\n\n  // This was either a rect getting refreshed, or a rect that just got\n  // new content. Either way we should not try to refresh it anymore.\n  pendingRefreshRegion.assign_subtract(rect);\n\n  return encoder;\n}\n\nvoid EncodeManager::endRect()\n{\n  int klass;\n  int length;\n\n  conn->writer()->endRect();\n\n  length = conn->getOutStream()->length() - beforeLength;\n\n  klass = activeEncoders[activeType];\n  stats[klass][activeType].bytes += length;\n}\n\nvoid EncodeManager::writeCopyRects(const core::Region& copied,\n                                   const core::Point& delta)\n{\n  std::vector<core::Rect> rects;\n  std::vector<core::Rect>::const_iterator rect;\n\n  core::Region lossyCopy;\n\n  beforeLength = conn->getOutStream()->length();\n\n  copied.get_rects(&rects, delta.x <= 0, delta.y <= 0);\n  for (rect = rects.begin(); rect != rects.end(); ++rect) {\n    int equiv;\n\n    copyStats.rects++;\n    copyStats.pixels += rect->area();\n    equiv = 12 + rect->area() * (conn->client.pf().bpp/8);\n    copyStats.equivalent += equiv;\n\n    conn->writer()->writeCopyRect(*rect, rect->tl.x - delta.x,\n                                   rect->tl.y - delta.y);\n  }\n\n  copyStats.bytes += conn->getOutStream()->length() - beforeLength;\n\n  lossyCopy = lossyRegion;\n  lossyCopy.translate(delta);\n  lossyCopy.assign_intersect(copied);\n  lossyRegion.assign_union(lossyCopy);\n\n  // Stop any pending refresh as a copy is enough that we consider\n  // this region to be recently changed\n  pendingRefreshRegion.assign_subtract(copied);\n}\n\nvoid EncodeManager::writeSolidRects(core::Region* changed,\n                                    const PixelBuffer* pb)\n{\n  std::vector<core::Rect> rects;\n  std::vector<core::Rect>::const_iterator rect;\n\n  changed->get_rects(&rects);\n  for (rect = rects.begin(); rect != rects.end(); ++rect)\n    findSolidRect(*rect, changed, pb);\n}\n\nvoid EncodeManager::findSolidRect(const core::Rect& rect,\n                                  core::Region* changed,\n                                  const PixelBuffer* pb)\n{\n  core::Rect sr;\n  int dx, dy, dw, dh;\n\n  // We start by finding a solid 16x16 block\n  for (dy = rect.tl.y; dy < rect.br.y; dy += SolidSearchBlock) {\n\n    dh = SolidSearchBlock;\n    if (dy + dh > rect.br.y)\n      dh = rect.br.y - dy;\n\n    for (dx = rect.tl.x; dx < rect.br.x; dx += SolidSearchBlock) {\n      // We define it like this to guarantee alignment\n      uint32_t _buffer;\n      uint8_t* colourValue = (uint8_t*)&_buffer;\n\n      dw = SolidSearchBlock;\n      if (dx + dw > rect.br.x)\n        dw = rect.br.x - dx;\n\n      pb->getImage(colourValue, {dx, dy, dx+1, dy+1});\n\n      sr.setXYWH(dx, dy, dw, dh);\n      if (checkSolidTile(sr, colourValue, pb)) {\n        core::Rect erb, erp;\n\n        Encoder *encoder;\n\n        // We then try extending the area by adding more blocks\n        // in both directions and pick the combination that gives\n        // the largest area.\n        sr.setXYWH(dx, dy, rect.br.x - dx, rect.br.y - dy);\n        extendSolidAreaByBlock(sr, colourValue, pb, &erb);\n\n        // Did we end up getting the entire rectangle?\n        if (erb == rect)\n          erp = erb;\n        else {\n          // Don't bother with sending tiny rectangles\n          if (erb.area() < SolidBlockMinArea)\n            continue;\n\n          // Extend the area again, but this time one pixel\n          // row/column at a time.\n          extendSolidAreaByPixel(rect, erb, colourValue, pb, &erp);\n        }\n\n        // FIXME: This should ideally be done whilst scanning to avoid\n        //        scanning the same area twice.\n        if (erp.width() > SubRectMaxWidth)\n          erp.br.x = erp.tl.x + SubRectMaxWidth;\n        if (erp.area() > SubRectMaxArea)\n          erp.br.y = erp.tl.y + SubRectMaxArea/erp.width();\n\n        // Send solid-color rectangle.\n        encoder = startRect(erp, encoderSolid);\n        if (encoder->flags & EncoderUseNativePF) {\n          encoder->writeSolidRect(erp.width(), erp.height(),\n                                  pb->getPF(), colourValue);\n        } else {\n          uint32_t _buffer2;\n          uint8_t* converted = (uint8_t*)&_buffer2;\n\n          conn->client.pf().bufferFromBuffer(converted, pb->getPF(),\n                                         colourValue, 1);\n\n          encoder->writeSolidRect(erp.width(), erp.height(),\n                                  conn->client.pf(), converted);\n        }\n        endRect();\n\n        changed->assign_subtract(erp);\n\n        // Search remaining areas by recursion\n        // FIXME: Is this the best way to divide things up?\n\n        // Left? (Note that we've already searched a SolidSearchBlock\n        //        pixels high strip here)\n        if ((erp.tl.x != rect.tl.x) && (erp.height() > SolidSearchBlock)) {\n          sr.setXYWH(rect.tl.x, erp.tl.y + SolidSearchBlock,\n                     erp.tl.x - rect.tl.x, erp.height() - SolidSearchBlock);\n          findSolidRect(sr, changed, pb);\n        }\n\n        // Right?\n        if (erp.br.x != rect.br.x) {\n          sr.setXYWH(erp.br.x, erp.tl.y, rect.br.x - erp.br.x, erp.height());\n          findSolidRect(sr, changed, pb);\n        }\n\n        // Below?\n        if (erp.br.y != rect.br.y) {\n          sr.setXYWH(rect.tl.x, erp.br.y, rect.width(), rect.br.y - erp.br.y);\n          findSolidRect(sr, changed, pb);\n        }\n\n        return;\n      }\n    }\n  }\n}\n\nvoid EncodeManager::writeRects(const core::Region& changed,\n                               const PixelBuffer* pb)\n{\n  std::vector<core::Rect> rects;\n  std::vector<core::Rect>::const_iterator rect;\n\n  changed.get_rects(&rects);\n  for (rect = rects.begin(); rect != rects.end(); ++rect) {\n    int w, h, sw, sh;\n    core::Rect sr;\n\n    w = rect->width();\n    h = rect->height();\n\n    // No split necessary?\n    if (((w*h) < SubRectMaxArea) && (w < SubRectMaxWidth)) {\n      writeSubRect(*rect, pb);\n      continue;\n    }\n\n    if (w <= SubRectMaxWidth)\n      sw = w;\n    else\n      sw = SubRectMaxWidth;\n\n    sh = SubRectMaxArea / sw;\n\n    for (sr.tl.y = rect->tl.y; sr.tl.y < rect->br.y; sr.tl.y += sh) {\n      sr.br.y = sr.tl.y + sh;\n      if (sr.br.y > rect->br.y)\n        sr.br.y = rect->br.y;\n\n      for (sr.tl.x = rect->tl.x; sr.tl.x < rect->br.x; sr.tl.x += sw) {\n        sr.br.x = sr.tl.x + sw;\n        if (sr.br.x > rect->br.x)\n          sr.br.x = rect->br.x;\n\n        writeSubRect(sr, pb);\n      }\n    }\n  }\n}\n\nvoid EncodeManager::writeSubRect(const core::Rect& rect,\n                                 const PixelBuffer* pb)\n{\n  PixelBuffer *ppb;\n\n  Encoder *encoder;\n\n  struct RectInfo info;\n  unsigned int divisor, maxColours;\n\n  bool useRLE;\n  EncoderType type;\n\n  // FIXME: This is roughly the algorithm previously used by the Tight\n  //        encoder. It seems a bit backwards though, that higher\n  //        compression setting means spending less effort in building\n  //        a palette. It might be that they figured the increase in\n  //        zlib setting compensated for the loss.\n  if (conn->client.compressLevel == -1)\n    divisor = 2 * 8;\n  else\n    divisor = conn->client.compressLevel * 8;\n  if (divisor < 4)\n    divisor = 4;\n\n  maxColours = rect.area()/divisor;\n\n  // Special exception inherited from the Tight encoder\n  if ((activeEncoders[encoderFullColour] == encoderTightJPEG) ||\n      (activeEncoders[encoderFullColour] == encoderJPEG)) {\n    if ((conn->client.compressLevel != -1) && (conn->client.compressLevel < 2))\n      maxColours = 24;\n    else\n      maxColours = 96;\n  }\n\n  if (maxColours < 2)\n    maxColours = 2;\n\n  encoder = encoders[activeEncoders[encoderIndexedRLE]];\n  if (maxColours > encoder->maxPaletteSize)\n    maxColours = encoder->maxPaletteSize;\n  encoder = encoders[activeEncoders[encoderIndexed]];\n  if (maxColours > encoder->maxPaletteSize)\n    maxColours = encoder->maxPaletteSize;\n\n  ppb = preparePixelBuffer(rect, pb, true);\n\n  if (!analyseRect(ppb, &info, maxColours))\n    info.palette.clear();\n\n  // Different encoders might have different RLE overhead, but\n  // here we do a guess at RLE being the better choice if reduces\n  // the pixel count by 50%.\n  useRLE = info.rleRuns <= (rect.area() * 2);\n\n  switch (info.palette.size()) {\n  case 0:\n    type = encoderFullColour;\n    break;\n  case 1:\n    type = encoderSolid;\n    break;\n  case 2:\n    if (useRLE)\n      type = encoderBitmapRLE;\n    else\n      type = encoderBitmap;\n    break;\n  default:\n    if (useRLE)\n      type = encoderIndexedRLE;\n    else\n      type = encoderIndexed;\n  }\n\n  encoder = startRect(rect, type);\n\n  if (encoder->flags & EncoderUseNativePF)\n    ppb = preparePixelBuffer(rect, pb, false);\n\n  encoder->writeRect(ppb, info.palette);\n\n  endRect();\n}\n\nbool EncodeManager::checkSolidTile(const core::Rect& r,\n                                   const uint8_t* colourValue,\n                                   const PixelBuffer *pb)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  buffer = pb->getBuffer(r, &stride);\n\n  switch (pb->getPF().bpp) {\n  case 32:\n    return checkSolidTile(r.width(), r.height(),\n                          (const uint32_t*)buffer, stride,\n                          *(const uint32_t*)colourValue);\n  case 16:\n    return checkSolidTile(r.width(), r.height(),\n                          (const uint16_t*)buffer, stride,\n                          *(const uint16_t*)colourValue);\n  default:\n    return checkSolidTile(r.width(), r.height(),\n                          (const uint8_t*)buffer, stride,\n                          *(const uint8_t*)colourValue);\n  }\n}\n\nvoid EncodeManager::extendSolidAreaByBlock(const core::Rect& r,\n                                           const uint8_t* colourValue,\n                                           const PixelBuffer* pb,\n                                           core::Rect* er)\n{\n  int dx, dy, dw, dh;\n  int w_prev;\n  core::Rect sr;\n  int w_best = 0, h_best = 0;\n\n  w_prev = r.width();\n\n  // We search width first, back off when we hit a different colour,\n  // and restart with a larger height. We keep track of the\n  // width/height combination that gives us the largest area.\n  for (dy = r.tl.y; dy < r.br.y; dy += SolidSearchBlock) {\n\n    dh = SolidSearchBlock;\n    if (dy + dh > r.br.y)\n      dh = r.br.y - dy;\n\n    // We test one block here outside the x loop in order to break\n    // the y loop right away.\n    dw = SolidSearchBlock;\n    if (dw > w_prev)\n      dw = w_prev;\n\n    sr.setXYWH(r.tl.x, dy, dw, dh);\n    if (!checkSolidTile(sr, colourValue, pb))\n      break;\n\n    for (dx = r.tl.x + dw; dx < r.tl.x + w_prev;) {\n\n      dw = SolidSearchBlock;\n      if (dx + dw > r.tl.x + w_prev)\n        dw = r.tl.x + w_prev - dx;\n\n      sr.setXYWH(dx, dy, dw, dh);\n      if (!checkSolidTile(sr, colourValue, pb))\n        break;\n\n      dx += dw;\n    }\n\n    w_prev = dx - r.tl.x;\n    if (w_prev * (dy + dh - r.tl.y) > w_best * h_best) {\n      w_best = w_prev;\n      h_best = dy + dh - r.tl.y;\n    }\n  }\n\n  er->tl.x = r.tl.x;\n  er->tl.y = r.tl.y;\n  er->br.x = er->tl.x + w_best;\n  er->br.y = er->tl.y + h_best;\n}\n\nvoid EncodeManager::extendSolidAreaByPixel(const core::Rect& r,\n                                           const core::Rect& sr,\n                                           const uint8_t* colourValue,\n                                           const PixelBuffer* pb,\n                                           core::Rect* er)\n{\n  int cx, cy;\n  core::Rect tr;\n\n  // Try to extend the area upwards.\n  for (cy = sr.tl.y - 1; cy >= r.tl.y; cy--) {\n    tr.setXYWH(sr.tl.x, cy, sr.width(), 1);\n    if (!checkSolidTile(tr, colourValue, pb))\n      break;\n  }\n  er->tl.y = cy + 1;\n\n  // ... downwards.\n  for (cy = sr.br.y; cy < r.br.y; cy++) {\n    tr.setXYWH(sr.tl.x, cy, sr.width(), 1);\n    if (!checkSolidTile(tr, colourValue, pb))\n      break;\n  }\n  er->br.y = cy;\n\n  // ... to the left.\n  for (cx = sr.tl.x - 1; cx >= r.tl.x; cx--) {\n    tr.setXYWH(cx, er->tl.y, 1, er->height());\n    if (!checkSolidTile(tr, colourValue, pb))\n      break;\n  }\n  er->tl.x = cx + 1;\n\n  // ... to the right.\n  for (cx = sr.br.x; cx < r.br.x; cx++) {\n    tr.setXYWH(cx, er->tl.y, 1, er->height());\n    if (!checkSolidTile(tr, colourValue, pb))\n      break;\n  }\n  er->br.x = cx;\n}\n\nPixelBuffer* EncodeManager::preparePixelBuffer(const core::Rect& rect,\n                                               const PixelBuffer *pb,\n                                               bool convert)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  // Do wo need to convert the data?\n  if (convert && conn->client.pf() != pb->getPF()) {\n    convertedPixelBuffer.setPF(conn->client.pf());\n    convertedPixelBuffer.setSize(rect.width(), rect.height());\n\n    buffer = pb->getBuffer(rect, &stride);\n    convertedPixelBuffer.imageRect(pb->getPF(),\n                                   convertedPixelBuffer.getRect(),\n                                   buffer, stride);\n\n    return &convertedPixelBuffer;\n  }\n\n  // Otherwise we still need to shift the coordinates. We have our own\n  // abusive subclass of FullFramePixelBuffer for this.\n\n  buffer = pb->getBuffer(rect, &stride);\n\n  offsetPixelBuffer.update(pb->getPF(), rect.width(), rect.height(),\n                           buffer, stride);\n\n  return &offsetPixelBuffer;\n}\n\nbool EncodeManager::analyseRect(const PixelBuffer *pb,\n                                struct RectInfo *info, int maxColours)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  buffer = pb->getBuffer(pb->getRect(), &stride);\n\n  switch (pb->getPF().bpp) {\n  case 32:\n    return analyseRect(pb->width(), pb->height(),\n                       (const uint32_t*)buffer, stride,\n                       info, maxColours);\n  case 16:\n    return analyseRect(pb->width(), pb->height(),\n                       (const uint16_t*)buffer, stride,\n                       info, maxColours);\n  default:\n    return analyseRect(pb->width(), pb->height(),\n                       (const uint8_t*)buffer, stride,\n                       info, maxColours);\n  }\n}\n\nvoid EncodeManager::OffsetPixelBuffer::update(const PixelFormat& pf,\n                                              int width, int height,\n                                              const uint8_t* data_,\n                                              int stride_)\n{\n  format = pf;\n  // Forced cast. We never write anything though, so it should be safe.\n  setBuffer(width, height, (uint8_t*)data_, stride_);\n}\n\nuint8_t* EncodeManager::OffsetPixelBuffer::getBufferRW(const core::Rect& /*r*/, int* /*stride*/)\n{\n  throw std::logic_error(\"Invalid write attempt to OffsetPixelBuffer\");\n}\n\ntemplate<class T>\ninline bool EncodeManager::checkSolidTile(int width, int height,\n                                          const T* buffer, int stride,\n                                          const T colourValue)\n{\n  int pad;\n\n  pad = stride - width;\n\n  while (height--) {\n    int width_ = width;\n    while (width_--) {\n      if (*buffer != colourValue)\n        return false;\n      buffer++;\n    }\n    buffer += pad;\n  }\n\n  return true;\n}\n\ntemplate<class T>\ninline bool EncodeManager::analyseRect(int width, int height,\n                                       const T* buffer, int stride,\n                                       struct RectInfo *info, int maxColours)\n{\n  int pad;\n\n  T colour;\n  int count;\n\n  info->rleRuns = 0;\n  info->palette.clear();\n\n  pad = stride - width;\n\n  // For efficiency, we only update the palette on changes in colour\n  colour = buffer[0];\n  count = 0;\n  while (height--) {\n    int w_ = width;\n    while (w_--) {\n      if (*buffer != colour) {\n        if (!info->palette.insert(colour, count))\n          return false;\n        if (info->palette.size() > maxColours)\n          return false;\n\n        // FIXME: This doesn't account for switching lines\n        info->rleRuns++;\n\n        colour = *buffer;\n        count = 0;\n      }\n      buffer++;\n      count++;\n    }\n    buffer += pad;\n  }\n\n  // Make sure the final pixels also get counted\n  if (!info->palette.insert(colour, count))\n    return false;\n  if (info->palette.size() > maxColours)\n    return false;\n\n  return true;\n}\n"
  },
  {
    "path": "common/rfb/EncodeManager.h",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_ENCODEMANAGER_H__\n#define __RFB_ENCODEMANAGER_H__\n\n#include <vector>\n\n#include <stdint.h>\n\n#include <core/Region.h>\n#include <core/Timer.h>\n\n#include <rfb/PixelBuffer.h>\n\nnamespace rfb {\n\n  class SConnection;\n  class Encoder;\n  class UpdateInfo;\n  class PixelBuffer;\n  class RenderedCursor;\n\n  struct RectInfo;\n\n  class EncodeManager : public core::Timer::Callback {\n  public:\n    EncodeManager(SConnection* conn);\n    ~EncodeManager();\n\n    void logStats();\n\n    // Hack to let ConnParams calculate the client's preferred encoding\n    static bool supported(int encoding);\n\n    bool needsLosslessRefresh(const core::Region& req);\n    int getNextLosslessRefresh(const core::Region& req);\n\n    void pruneLosslessRefresh(const core::Region& limits);\n\n    void forceRefresh(const core::Region& req);\n\n    void writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb,\n                     const RenderedCursor* renderedCursor);\n\n    void writeLosslessRefresh(const core::Region& req,\n                              const PixelBuffer* pb,\n                              const RenderedCursor* renderedCursor,\n                              size_t maxUpdateSize);\n\n  protected:\n    void handleTimeout(core::Timer* t) override;\n\n    void doUpdate(bool allowLossy, const core::Region& changed,\n                  const core::Region& copied,\n                  const core::Point& copy_delta,\n                  const PixelBuffer* pb,\n                  const RenderedCursor* renderedCursor);\n    void prepareEncoders(bool allowLossy);\n\n    core::Region getLosslessRefresh(const core::Region& req,\n                                    size_t maxUpdateSize);\n\n    int computeNumRects(const core::Region& changed);\n\n    Encoder* startRect(const core::Rect& rect, int type);\n    void endRect();\n\n    void writeCopyRects(const core::Region& copied,\n                        const core::Point& delta);\n    void writeSolidRects(core::Region* changed, const PixelBuffer* pb);\n    void findSolidRect(const core::Rect& rect, core::Region* changed,\n                       const PixelBuffer* pb);\n    void writeRects(const core::Region& changed, const PixelBuffer* pb);\n\n    void writeSubRect(const core::Rect& rect, const PixelBuffer* pb);\n\n    bool checkSolidTile(const core::Rect& r, const uint8_t* colourValue,\n                        const PixelBuffer *pb);\n    void extendSolidAreaByBlock(const core::Rect& r,\n                                const uint8_t* colourValue,\n                                const PixelBuffer* pb, core::Rect* er);\n    void extendSolidAreaByPixel(const core::Rect& r,\n                                const core::Rect& sr,\n                                const uint8_t* colourValue,\n                                const PixelBuffer* pb, core::Rect* er);\n\n    PixelBuffer* preparePixelBuffer(const core::Rect& rect,\n                                    const PixelBuffer* pb, bool convert);\n\n    bool analyseRect(const PixelBuffer *pb,\n                     struct RectInfo *info, int maxColours);\n\n  protected:\n    // Templated, optimised methods\n    template<class T>\n    inline bool checkSolidTile(int width, int height,\n                               const T* buffer, int stride,\n                               const T colourValue);\n    template<class T>\n    inline bool analyseRect(int width, int height,\n                            const T* buffer, int stride,\n                            struct RectInfo *info, int maxColours);\n\n  protected:\n    SConnection *conn;\n\n    std::vector<Encoder*> encoders;\n    std::vector<int> activeEncoders;\n\n    core::Region lossyRegion;\n    core::Region recentlyChangedRegion;\n    core::Region pendingRefreshRegion;\n\n    core::Timer recentChangeTimer;\n\n    struct EncoderStats {\n      unsigned rects;\n      unsigned long long bytes;\n      unsigned long long pixels;\n      unsigned long long equivalent;\n    };\n    typedef std::vector< std::vector<struct EncoderStats> > StatsVector;\n\n    unsigned updates;\n    EncoderStats copyStats;\n    StatsVector stats;\n    int activeType;\n    int beforeLength;\n\n    class OffsetPixelBuffer : public FullFramePixelBuffer {\n    public:\n      OffsetPixelBuffer() {}\n      virtual ~OffsetPixelBuffer() {}\n\n      void update(const PixelFormat& pf, int width, int height,\n                  const uint8_t* data_, int stride);\n\n    private:\n      uint8_t* getBufferRW(const core::Rect& r, int* stride) override;\n    };\n\n    OffsetPixelBuffer offsetPixelBuffer;\n    ManagedPixelBuffer convertedPixelBuffer;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/Encoder.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rfb/Encoder.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/Palette.h>\n\nusing namespace rfb;\n\nEncoder::Encoder(SConnection *conn_, int encoding_,\n                 enum EncoderFlags flags_,\n                 unsigned int maxPaletteSize_, int losslessQuality_) :\n  encoding(encoding_), flags(flags_),\n  maxPaletteSize(maxPaletteSize_), losslessQuality(losslessQuality_),\n  conn(conn_)\n{\n}\n\nEncoder::~Encoder()\n{\n}\n\nvoid Encoder::writeSolidRect(int width, int height,\n                             const PixelFormat& pf, const uint8_t* colour)\n{\n  ManagedPixelBuffer buffer(pf, width, height);\n\n  Palette palette;\n  uint32_t palcol;\n\n  buffer.fillRect(buffer.getRect(), colour);\n\n  palcol = 0;\n  memcpy(&palcol, colour, pf.bpp/8);\n  palette.insert(palcol, 1);\n\n  writeRect(&buffer, palette);\n}\n\nvoid Encoder::writeSolidRect(const PixelBuffer* pb, const Palette& palette)\n{\n  uint32_t col32;\n  uint16_t col16;\n  uint8_t col8;\n\n  uint8_t* buffer;\n\n  assert(palette.size() == 1);\n\n  // The Palette relies on implicit up and down conversion\n  switch (pb->getPF().bpp) {\n  case 32:\n    col32 = (uint32_t)palette.getColour(0);\n    buffer = (uint8_t*)&col32;\n    break;\n  case 16:\n    col16 = (uint16_t)palette.getColour(0);\n    buffer = (uint8_t*)&col16;\n    break;\n  default:\n    col8 = (uint8_t)palette.getColour(0);\n    buffer = (uint8_t*)&col8;\n    break;\n  }\n\n  writeSolidRect(pb->width(), pb->height(), pb->getPF(), buffer);\n}\n"
  },
  {
    "path": "common/rfb/Encoder.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_ENCODER_H__\n#define __RFB_ENCODER_H__\n\n#include <stdint.h>\n\nnamespace rfb {\n  class SConnection;\n  class PixelBuffer;\n  class Palette;\n  class PixelFormat;\n\n  enum EncoderFlags {\n    // A constant for encoders that don't need anything special\n    EncoderPlain = 0,\n    // Give us the raw frame buffer, and not something converted to\n    // the what the client is asking for.\n    EncoderUseNativePF = 1 << 0,\n    // Encoder does not encode pixels perfectly accurate\n    EncoderLossy = 1 << 1,\n  };\n\n  class Encoder {\n  public:\n    Encoder(SConnection* conn, int encoding,\n            enum EncoderFlags flags, unsigned int maxPaletteSize=-1,\n            int losslessQuality=-1);\n    virtual ~Encoder();\n\n    // isSupported() should return a boolean indicating if this encoder\n    // is okay to use with the current connection. This usually involves\n    // checking the list of encodings in the connection parameters.\n    virtual bool isSupported()=0;\n\n    virtual void setCompressLevel(int /*level*/) {};\n    virtual void setQualityLevel(int /*level*/) {};\n    virtual void setFineQualityLevel(int /*quality*/,\n                                     int /*subsampling*/) {};\n\n    virtual int getCompressLevel() { return -1; };\n    virtual int getQualityLevel() { return -1; };\n\n    // writeRect() is the main interface that encodes the given rectangle\n    // with data from the PixelBuffer onto the SConnection given at\n    // encoder creation.\n    //\n    // The PixelBuffer will be in the PixelFormat specified in ConnParams\n    // unless the flag UseNativePF is specified. In that case the\n    // PixelBuffer will remain in its native format and encoder will have\n    // to handle any conversion itself.\n    //\n    // The Palette will always be in the PixelFormat specified in\n    // ConnParams. An empty palette indicates a large number of colours,\n    // but could still be less than maxPaletteSize.\n    virtual void writeRect(const PixelBuffer* pb, const Palette& palette)=0;\n\n    // writeSolidRect() is a short cut in order to encode single colour\n    // rectangles efficiently without having to create a fake single\n    // colour PixelBuffer. The colour argument follows the same semantics\n    // as the PixelBuffer for writeRect().\n    //\n    // Note that there is a default implementation that can be called\n    // using Encoder::writeSolidRect() in the event that there is no\n    // efficient short cut.\n    virtual void writeSolidRect(int width, int height,\n                                const PixelFormat& pf,\n                                const uint8_t* colour)=0;\n\n  protected:\n    // Helper method for redirecting a single colour palette to the\n    // short cut method.\n    void writeSolidRect(const PixelBuffer* pb, const Palette& palette);\n\n  public:\n    const int encoding;\n    const enum EncoderFlags flags;\n\n    // Maximum size of the palette per rect\n    const unsigned int maxPaletteSize;\n\n    // Minimum level where the quality loss will not be noticed by\n    // most users (only relevant with EncoderLossy flag)\n    const int losslessQuality;\n\n  protected:\n    SConnection* conn;\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/Exception.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_EXCEPTION_H__\n#define __RFB_EXCEPTION_H__\n\n#include <stdexcept>\n\nnamespace rfb {\n  class protocol_error : public std::runtime_error {\n  public:\n    protocol_error(const char* what_arg) noexcept : std::runtime_error(what_arg) {}\n    protocol_error(const std::string& what_arg) noexcept : std::runtime_error(what_arg) {}\n  };\n\n  class auth_error : public std::runtime_error {\n  public:\n    auth_error(const char* reason) noexcept : std::runtime_error(reason) {}\n    auth_error(std::string& reason) noexcept : std::runtime_error(reason) {}\n  };\n\n  class auth_cancelled : public std::runtime_error {\n  public:\n    auth_cancelled() noexcept\n      : std::runtime_error(\"Authentication cancelled\") {}\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/H264Decoder.cxx",
    "content": "/* Copyright (C) 2021 Vladimir Sukhonosov <xornet@xornet.org>\n * Copyright (C) 2021 Martins Mozeiko <martins.mozeiko@gmail.com>\n * All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#define MAX_H264_INSTANCES 64\n\n#include <deque>\n\n#include <rdr/MemInStream.h>\n#include <rdr/InStream.h>\n#include <rdr/OutStream.h>\n#include <rfb/H264Decoder.h>\n#include <rfb/H264DecoderContext.h>\n\nusing namespace rfb;\n\nenum rectFlags {\n  resetContext       = 0x1,\n  resetAllContexts   = 0x2,\n};\n\nH264Decoder::H264Decoder() : Decoder(DecoderOrdered)\n{\n}\n\nH264Decoder::~H264Decoder()\n{\n  resetContexts();\n}\n\nvoid H264Decoder::resetContexts()\n{\n  for (H264DecoderContext* context : contexts)\n    delete context;\n  contexts.clear();\n}\n\nH264DecoderContext* H264Decoder::findContext(const core::Rect& r)\n{\n  for (H264DecoderContext* context : contexts)\n    if (context->isEqualRect(r))\n      return context;\n  return nullptr;\n}\n\nbool H264Decoder::readRect(const core::Rect& /*r*/,\n                           rdr::InStream* is,\n                           const ServerParams& /*server*/,\n                           rdr::OutStream* os)\n{\n  uint32_t len;\n\n  if (!is->hasData(8))\n    return false;\n\n  is->setRestorePoint();\n\n  len = is->readU32();\n  uint32_t reset = is->readU32();\n\n  if (!is->hasDataOrRestore(len))\n    return false;\n\n  is->clearRestorePoint();\n\n  os->writeU32(len);\n  os->writeU32(reset);\n  os->copyBytes(is, len);\n\n  return true;\n}\n\nvoid H264Decoder::decodeRect(const core::Rect& r, const uint8_t* buffer,\n                             size_t buflen,\n                             const ServerParams& /*server*/,\n                             ModifiablePixelBuffer* pb)\n{\n  rdr::MemInStream is(buffer, buflen);\n  uint32_t len = is.readU32();\n  uint32_t reset = is.readU32();\n\n  H264DecoderContext* ctx = nullptr;\n  if (reset & resetAllContexts)\n  {\n    resetContexts();\n    if (!len)\n      return;\n    reset &= ~(resetContext | resetAllContexts);\n  } else {\n    ctx = findContext(r);\n  }\n\n  if (ctx && (reset & resetContext)) {\n    contexts.remove(ctx);\n    delete ctx;\n    ctx = nullptr;\n  }\n\n  if (!ctx)\n  {\n    if (contexts.size() >= MAX_H264_INSTANCES)\n    {\n      H264DecoderContext* excess_ctx = contexts.front();\n      delete excess_ctx;\n      contexts.pop_front();\n    }\n    ctx = H264DecoderContext::createContext(r);\n    if (!ctx)\n      throw std::runtime_error(\"H264Decoder: Context not be created\");\n    contexts.push_back(ctx);\n  }\n\n  if (!len)\n    return;\n\n  ctx->decode(is.getptr(len), len, pb);\n}\n"
  },
  {
    "path": "common/rfb/H264Decoder.h",
    "content": "/* Copyright (C) 2021 Vladimir Sukhonosov <xornet@xornet.org>\n * Copyright (C) 2021 Martins Mozeiko <martins.mozeiko@gmail.com>\n * All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_H264DECODER_H__\n#define __RFB_H264DECODER_H__\n\n#include <list>\n\n#include <rfb/Decoder.h>\n\nnamespace rfb {\n  class H264DecoderContext;\n\n  class H264Decoder : public Decoder {\n  public:\n    H264Decoder();\n    virtual ~H264Decoder();\n    bool readRect(const core::Rect& r, rdr::InStream* is,\n                  const ServerParams& server,\n                  rdr::OutStream* os) override;\n    void decodeRect(const core::Rect& r, const uint8_t* buffer,\n                    size_t buflen, const ServerParams& server,\n                    ModifiablePixelBuffer* pb) override;\n\n  private:\n    void resetContexts();\n    H264DecoderContext* findContext(const core::Rect& r);\n\n    std::list<H264DecoderContext*> contexts;\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/H264DecoderContext.cxx",
    "content": "/* Copyright (C) 2021 Vladimir Sukhonosov <xornet@xornet.org>\n * Copyright (C) 2021 Martins Mozeiko <martins.mozeiko@gmail.com>\n * All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rfb/H264DecoderContext.h>\n\n#ifdef H264_LIBAV\n#include <rfb/H264LibavDecoderContext.h>\n#define H264DecoderContextType H264LibavDecoderContext\n#elif H264_WIN\n#include <rfb/H264WinDecoderContext.h>\n#define H264DecoderContextType H264WinDecoderContext\n#endif\n\nusing namespace rfb;\n\nH264DecoderContext *H264DecoderContext::createContext(const core::Rect &r)\n{\n  return new H264DecoderContextType(r);\n}\n\nH264DecoderContext::~H264DecoderContext()\n{\n}\n"
  },
  {
    "path": "common/rfb/H264DecoderContext.h",
    "content": "/* Copyright (C) 2021 Vladimir Sukhonosov <xornet@xornet.org>\n * Copyright (C) 2021 Martins Mozeiko <martins.mozeiko@gmail.com>\n * All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_H264DECODERCONTEXT_H__\n#define __RFB_H264DECODERCONTEXT_H__\n\n#include <stdint.h>\n\n#include <core/Rect.h>\n\nnamespace rfb {\n\n  class ModifiablePixelBuffer;\n\n  class H264DecoderContext {\n    public:\n      static H264DecoderContext* createContext(const core::Rect& r);\n\n      virtual ~H264DecoderContext() = 0;\n\n      virtual void decode(const uint8_t* /*h264_buffer*/,\n                          uint32_t /*len*/,\n                          ModifiablePixelBuffer* /*pb*/) {}\n\n      inline bool isEqualRect(const core::Rect &r) const { return r == rect; }\n\n    protected:\n      core::Rect rect;\n\n      H264DecoderContext(const core::Rect &r) : rect(r) {}\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/H264LibavDecoderContext.cxx",
    "content": "/* Copyright (C) 2021 Vladimir Sukhonosov <xornet@xornet.org>\n * Copyright (C) 2021 Martins Mozeiko <martins.mozeiko@gmail.com>\n * All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <new>\n#include <stdexcept>\n\nextern \"C\" {\n#include <libavutil/imgutils.h>\n#include <libavcodec/version.h>\n}\n#if LIBAVCODEC_VERSION_MAJOR > 57 || LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR >= 37\n#define FFMPEG_DECODE_VIDEO2_DEPRECATED\n#endif\n#if LIBAVCODEC_VERSION_MAJOR >= 58\n#define FFMPEG_INIT_PACKET_DEPRECATED\n#endif\n\n#include <rfb/PixelBuffer.h>\n#include <rfb/H264LibavDecoderContext.h>\n\nusing namespace rfb;\n\nH264LibavDecoderContext::H264LibavDecoderContext(const core::Rect& r)\n  : H264DecoderContext(r)\n{\n  sws = nullptr;\n  h264WorkBuffer = nullptr;\n  h264WorkBufferLength = 0;\n\n  const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);\n  if (!codec)\n    throw std::runtime_error(\"Codec not found\");\n\n  parser = av_parser_init(codec->id);\n  if (!parser)\n    throw std::runtime_error(\"Could not create H264 parser\");\n\n  avctx = avcodec_alloc_context3(codec);\n  if (!avctx)\n  {\n    av_parser_close(parser);\n    throw std::runtime_error(\"Could not allocate video codec context\");\n  }\n\n  frame = av_frame_alloc();\n  if (!frame)\n  {\n    av_parser_close(parser);\n    avcodec_free_context(&avctx);\n    throw std::runtime_error(\"Could not allocate video frame\");\n  }\n\n  if (avcodec_open2(avctx, codec, nullptr) < 0)\n  {\n    av_parser_close(parser);\n    avcodec_free_context(&avctx);\n    av_frame_free(&frame);\n    throw std::runtime_error(\"Could not open video codec\");\n  }\n}\n\nH264LibavDecoderContext::~H264LibavDecoderContext()\n{\n  av_parser_close(parser);\n  avcodec_free_context(&avctx);\n  av_frame_free(&rgbFrame);\n  av_frame_free(&frame);\n  sws_freeContext(sws);\n  free(h264WorkBuffer);\n}\n\n// We need to reallocate buffer because AVPacket uses non-const pointer.\n// We don't want to const_cast our buffer somewhere. So we would rather to maintain context's own buffer\n// Also avcodec requires a right padded buffer\nuint8_t* H264LibavDecoderContext::makeH264WorkBuffer(const uint8_t* buffer, uint32_t len)\n{\n  uint32_t reserve_len = len + len % AV_INPUT_BUFFER_PADDING_SIZE;\n\n  if (!h264WorkBuffer || reserve_len > h264WorkBufferLength)\n  {\n    h264WorkBuffer = (uint8_t*)realloc(h264WorkBuffer, reserve_len);\n    if (h264WorkBuffer == nullptr) {\n      throw std::bad_alloc();\n    }\n    h264WorkBufferLength = reserve_len;\n  }\n\n  memcpy(h264WorkBuffer, buffer, len);\n  memset(h264WorkBuffer + len, 0, h264WorkBufferLength - len);\n  return h264WorkBuffer;\n}\n\nvoid H264LibavDecoderContext::decode(const uint8_t* h264_in_buffer,\n                                     uint32_t len,\n                                     ModifiablePixelBuffer* pb) {\n  uint8_t* h264_work_buffer = makeH264WorkBuffer(h264_in_buffer, len);\n\n#ifdef FFMPEG_INIT_PACKET_DEPRECATED\n  AVPacket *packet = av_packet_alloc();\n#else\n  AVPacket *packet = new AVPacket();\n  av_init_packet(packet);\n#endif\n\n  int ret;\n  int frames_received = 0;\n  while (len)\n  {\n    ret = av_parser_parse2(parser, avctx, &packet->data, &packet->size, h264_work_buffer, len, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);\n    // Silently ignore errors, hoping its a temporary encoding glitch\n    if (ret < 0)\n      break;\n    // We need to slap on tv to make it work here (don't ask me why)\n    if (!packet->size && len == static_cast<uint32_t>(ret))\n      ret = av_parser_parse2(parser, avctx, &packet->data, &packet->size, h264_work_buffer, len, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);\n    // Silently ignore errors, hoping its a temporary encoding glitch\n    if (ret < 0)\n      break;\n    h264_work_buffer += ret;\n    len -= ret;\n\n    if (!ret)\n    {\n      packet->size = len;\n      packet->data = h264_work_buffer;\n      len = 0;\n    }\n\n    if (!packet->size)\n      continue;\n\n#ifndef FFMPEG_DECODE_VIDEO2_DEPRECATED\n    int got_frame;\n    ret = avcodec_decode_video2(avctx, frame, &got_frame, packet);\n    // Silently ignore errors, hoping its a temporary encoding glitch\n    if (ret < 0 || !got_frame)\n      break;\n#else\n    ret = avcodec_send_packet(avctx, packet);\n    // Silently ignore errors, hoping its a temporary encoding glitch\n    if (ret < 0)\n      break;\n\n    ret = avcodec_receive_frame(avctx, frame);\n    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)\n      break;\n    // Silently ignore errors, hoping its a temporary encoding glitch\n    if (ret < 0)\n      break;\n#endif\n    frames_received++;\n  }\n\n#ifdef FFMPEG_INIT_PACKET_DEPRECATED\n  packet->size = 0;\n  packet->data = nullptr;\n  av_packet_free(&packet);\n#else\n  delete packet;\n#endif\n\n  if (!frames_received)\n    return;\n\n  if (!frame->height)\n    return;\n\n  sws = sws_getCachedContext(sws, frame->width, frame->height, avctx->pix_fmt,\n                             frame->width, frame->height, AV_PIX_FMT_RGB32,\n                             SWS_POINT, nullptr, nullptr, nullptr);\n\n  int inFull, outFull, brightness, contrast, saturation;\n  const int* inTable;\n  const int* outTable;\n\n  sws_getColorspaceDetails(sws, (int**)&inTable, &inFull, (int**)&outTable,\n      &outFull, &brightness, &contrast, &saturation);\n  if (frame->colorspace != AVCOL_SPC_UNSPECIFIED) {\n    inTable = sws_getCoefficients(frame->colorspace);\n  }\n  if (frame->color_range != AVCOL_RANGE_UNSPECIFIED) {\n    inFull = frame->color_range == AVCOL_RANGE_JPEG;\n  }\n  sws_setColorspaceDetails(sws, inTable, inFull, outTable, outFull, brightness,\n      contrast, saturation);\n\n  if (rgbFrame && (rgbFrame->width != frame->width || rgbFrame->height != frame->height)) {\n    av_frame_free(&rgbFrame);\n\n  }\n\n  if (!rgbFrame) {\n    rgbFrame = av_frame_alloc();\n    // TODO: Can we really assume that the pixel format will always be RGB32?\n    rgbFrame->format = AV_PIX_FMT_RGB32;\n    rgbFrame->width = frame->width;\n    rgbFrame->height = frame->height;\n    av_frame_get_buffer(rgbFrame, 0);\n  }\n\n  sws_scale(sws, frame->data, frame->linesize, 0, frame->height, rgbFrame->data,\n            rgbFrame->linesize);\n\n  pb->imageRect(rect, rgbFrame->data[0], rgbFrame->linesize[0] / 4);\n}\n"
  },
  {
    "path": "common/rfb/H264LibavDecoderContext.h",
    "content": "/* Copyright (C) 2021 Vladimir Sukhonosov <xornet@xornet.org>\n * Copyright (C) 2021 Martins Mozeiko <martins.mozeiko@gmail.com>\n * All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_H264LIBAVDECODER_H__\n#define __RFB_H264LIBAVDECODER_H__\n\nextern \"C\" {\n#include <libavcodec/avcodec.h>\n#include <libswscale/swscale.h>\n}\n\n#include <rfb/H264DecoderContext.h>\n\nnamespace rfb {\n  class H264LibavDecoderContext : public H264DecoderContext {\n    public:\n      H264LibavDecoderContext(const core::Rect &r);\n      ~H264LibavDecoderContext();\n\n      void decode(const uint8_t* h264_buffer, uint32_t len,\n                  ModifiablePixelBuffer* pb) override;\n\n    private:\n      uint8_t* makeH264WorkBuffer(const uint8_t* buffer, uint32_t len);\n\n      AVCodecContext *avctx;\n      AVCodecParserContext *parser;\n      AVFrame* frame;\n      AVFrame* rgbFrame = nullptr;\n      SwsContext* sws;\n      uint8_t* h264WorkBuffer;\n      uint32_t h264WorkBufferLength;\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/H264WinDecoderContext.cxx",
    "content": "/* Copyright (C) 2021 Vladimir Sukhonosov <xornet@xornet.org>\n * Copyright (C) 2021 Martins Mozeiko <martins.mozeiko@gmail.com>\n * All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdexcept>\n\n#include <mfapi.h>\n#include <mferror.h>\n#include <wmcodecdsp.h>\n#define SAFE_RELEASE(obj) if (obj) { obj->Release(); obj = nullptr; }\n\n#include <rfb/PixelBuffer.h>\n#include <rfb/H264WinDecoderContext.h>\n\nusing namespace rfb;\n\n// Older MinGW lacks this definition\n#ifndef HAVE_VIDEO_PROCESSOR_MFT\nstatic GUID CLSID_VideoProcessorMFT = { 0x88753b26, 0x5b24, 0x49bd, { 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82 } };\n#endif\n\nH264WinDecoderContext::H264WinDecoderContext(const core::Rect &r)\n  : H264DecoderContext(r)\n{\n  if (FAILED(MFStartup(MF_VERSION, MFSTARTUP_LITE)))\n    throw std::runtime_error(\"Could not initialize MediaFoundation\");\n\n  if (FAILED(CoCreateInstance(CLSID_CMSH264DecoderMFT, nullptr, CLSCTX_INPROC_SERVER, IID_IMFTransform, (LPVOID*)&decoder)))\n    throw std::runtime_error(\"MediaFoundation H264 codec not found\");\n\n  if (FAILED(CoCreateInstance(CLSID_VideoProcessorMFT, nullptr, CLSCTX_INPROC_SERVER, IID_IMFTransform, (LPVOID*)&converter)))\n  {\n    if (FAILED(CoCreateInstance(CLSID_CColorConvertDMO, nullptr, CLSCTX_INPROC_SERVER, IID_IMFTransform, (LPVOID*)&converter)))\n    {\n      decoder->Release();\n      throw std::runtime_error(\"MediaFoundation H264 codec not found\");\n    }\n  }\n\n  // if possible, enable low-latency decoding (Windows 8 and up)\n  IMFAttributes* attributes;\n  if (SUCCEEDED(decoder->GetAttributes(&attributes)))\n  {\n    GUID MF_LOW_LATENCY = { 0x9c27891a, 0xed7a, 0x40e1, { 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee } };\n    attributes->SetUINT32(MF_LOW_LATENCY, TRUE);\n    attributes->Release();\n  }\n\n  // set decoder input type\n  IMFMediaType* input_type;\n  if (FAILED(MFCreateMediaType(&input_type)))\n  {\n    decoder->Release();\n    converter->Release();\n    throw std::runtime_error(\"Could not create MF MediaType\");\n  }\n  input_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);\n  input_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);\n  decoder->SetInputType(0, input_type, 0);\n  input_type->Release();\n\n  // set decoder output type (NV12)\n  DWORD output_index = 0;\n  IMFMediaType* output_type = nullptr;\n  while (SUCCEEDED(decoder->GetOutputAvailableType(0, output_index++, &output_type)))\n  {\n    GUID subtype;\n    if (SUCCEEDED(output_type->GetGUID(MF_MT_SUBTYPE, &subtype)) && subtype == MFVideoFormat_NV12)\n    {\n      decoder->SetOutputType(0, output_type, 0);\n      output_type->Release();\n      break;\n    }\n    output_type->Release();\n  }\n\n  if (FAILED(decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0)))\n  {\n    decoder->Release();\n    converter->Release();\n    input_type->Release();\n    throw std::runtime_error(\"Could not start H264 decoder\");\n  }\n\n  MFT_OUTPUT_STREAM_INFO info;\n  decoder->GetOutputStreamInfo(0, &info);\n\n  if (FAILED(MFCreateSample(&input_sample)) ||\n      FAILED(MFCreateSample(&decoded_sample)) ||\n      FAILED(MFCreateSample(&converted_sample)) ||\n      FAILED(MFCreateMemoryBuffer(4 * 1024 * 1024, &input_buffer)) ||\n      FAILED(MFCreateMemoryBuffer(info.cbSize, &decoded_buffer)))\n  {\n    decoder->Release();\n    converter->Release();\n    input_type->Release();\n    SAFE_RELEASE(input_sample);\n    SAFE_RELEASE(decoded_sample);\n    SAFE_RELEASE(converted_sample);\n    SAFE_RELEASE(input_buffer);\n    SAFE_RELEASE(decoded_buffer);\n    throw std::runtime_error(\"Could not allocate media samples/buffers\");\n  }\n\n  input_sample->AddBuffer(input_buffer);\n  decoded_sample->AddBuffer(decoded_buffer);\n}\n\nH264WinDecoderContext::~H264WinDecoderContext() {\n  SAFE_RELEASE(decoder)\n  SAFE_RELEASE(converter)\n  SAFE_RELEASE(input_sample)\n  SAFE_RELEASE(decoded_sample)\n  SAFE_RELEASE(converted_sample)\n  SAFE_RELEASE(input_buffer)\n  SAFE_RELEASE(decoded_buffer)\n  SAFE_RELEASE(converted_buffer)\n  MFShutdown();\n}\n\nvoid H264WinDecoderContext::decode(const uint8_t* h264_buffer,\n                                   uint32_t len,\n                                   ModifiablePixelBuffer* pb) {\n  if (FAILED(input_buffer->SetCurrentLength(len)))\n  {\n    input_buffer->Release();\n    if (FAILED(MFCreateMemoryBuffer(len, &input_buffer)))\n      throw std::runtime_error(\"Could not allocate media buffer\");\n    input_buffer->SetCurrentLength(len);\n    input_sample->RemoveAllBuffers();\n    input_sample->AddBuffer(input_buffer);\n  }\n\n  BYTE* locked;\n  input_buffer->Lock(&locked, nullptr, nullptr);\n  memcpy(locked, h264_buffer, len);\n  input_buffer->Unlock();\n\n  // extract actual size, including possible cropping\n  ParseSPS(h264_buffer, len);\n\n  if (FAILED(decoder->ProcessInput(0, input_sample, 0)))\n  {\n    // Silently ignore errors, hoping its a temporary encoding glitch\n    return;\n  }\n\n  bool decoded = false;\n\n  // try to retrieve all decoded output, as input can submit multiple h264 packets in one buffer\n  for (;;)\n  {\n    DWORD curlen;\n    decoded_buffer->GetCurrentLength(&curlen);\n    decoded_buffer->SetCurrentLength(0);\n\n    MFT_OUTPUT_DATA_BUFFER decoded_data;\n    decoded_data.dwStreamID = 0;\n    decoded_data.pSample = decoded_sample;\n    decoded_data.dwStatus = 0;\n    decoded_data.pEvents = nullptr;\n\n    DWORD status;\n    HRESULT hr = decoder->ProcessOutput(0, 1, &decoded_data, &status);\n    SAFE_RELEASE(decoded_data.pEvents)\n\n    if (SUCCEEDED(hr))\n    {\n      // successfully decoded next frame\n      // but do not exit loop, try again if there is next frame\n      decoded = true;\n    }\n    else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)\n    {\n      // no more frames to decode\n      if (decoded)\n      {\n        // restore previous buffer length for converter\n        decoded_buffer->SetCurrentLength(curlen);\n      }\n      break;\n    }\n    else if (hr == MF_E_TRANSFORM_STREAM_CHANGE)\n    {\n      // something changed (resolution, framerate, h264 properties...)\n      // need to setup output type and try decoding again\n\n      DWORD output_index = 0;\n      IMFMediaType* output_type = nullptr;\n      while (SUCCEEDED(decoder->GetOutputAvailableType(0, output_index++, &output_type)))\n      {\n        GUID subtype;\n        if (SUCCEEDED(output_type->GetGUID(MF_MT_SUBTYPE, &subtype)) && subtype == MFVideoFormat_NV12)\n        {\n          decoder->SetOutputType(0, output_type, 0);\n          break;\n        }\n        output_type->Release();\n        output_type = nullptr;\n      }\n\n      // reinitialize output type (NV12) that now has correct properties (width/height/framerate)\n      decoder->SetOutputType(0, output_type, 0);\n\n      UINT32 width, height;\n      if FAILED(MFGetAttributeSize(output_type, MF_MT_FRAME_SIZE, &width, &height))\n      {\n          // Silently ignore errors, hoping its a temporary encoding glitch\n          output_type->Release();\n          break;\n      }\n\n      // if MFT reports different width or height than calculated cropped width/height\n      if (crop_width != 0 && crop_height != 0 && (width != crop_width || height != crop_height))\n      {\n          // create NV12/RGB image with full size as we'll do manual cropping\n          width = full_width;\n          height = full_height;\n      }\n      else\n      {\n          // no manual cropping necessary\n          offset_x = offset_y = 0;\n          crop_width = width;\n          crop_height = height;\n      }\n\n      // input type to converter, BGRX pixel format\n      IMFMediaType* converted_type;\n      if (FAILED(MFCreateMediaType(&converted_type)))\n      {\n        // Silently ignore errors, hoping its a temporary encoding glitch\n      }\n      else\n      {\n        converted_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);\n        converted_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);\n        converted_type->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);\n        MFSetAttributeSize(converted_type, MF_MT_FRAME_SIZE, full_width, full_height);\n        MFGetStrideForBitmapInfoHeader(MFVideoFormat_RGB32.Data1, full_width, &stride);\n        // bottom-up\n        stride = -stride;\n        converted_type->SetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32)stride);\n\n        // setup NV12 -> BGRX converter\n        converter->SetOutputType(0, converted_type, 0);\n        converter->SetInputType(0, output_type, 0);\n        converted_type->Release();\n\n        // create converter output buffer\n\n        MFT_OUTPUT_STREAM_INFO info;\n        converter->GetOutputStreamInfo(0, &info);\n\n        if (FAILED(MFCreateMemoryBuffer(info.cbSize, &converted_buffer)))\n        {\n          // Silently ignore errors, hoping its a temporary encoding glitch\n        }\n        else\n        {\n          converted_sample->AddBuffer(converted_buffer);\n        }\n      }\n      output_type->Release();\n    }\n  }\n\n  // we care only about final image\n  // we ignore previous images if decoded multiple in a row\n  if (decoded)\n  {\n    if (FAILED(converter->ProcessInput(0, decoded_sample, 0)))\n    {\n      // Silently ignore errors, hoping its a temporary encoding glitch\n      return;\n    }\n\n    MFT_OUTPUT_DATA_BUFFER converted_data;\n    converted_data.dwStreamID = 0;\n    converted_data.pSample = converted_sample;\n    converted_data.dwStatus = 0;\n    converted_data.pEvents = nullptr;\n\n    DWORD status;\n    HRESULT hr = converter->ProcessOutput(0, 1, &converted_data, &status);\n    SAFE_RELEASE(converted_data.pEvents)\n\n    if (FAILED(hr))\n    {\n      // Silently ignore errors, hoping its a temporary encoding glitch\n    }\n    else\n    {\n      BYTE* out;\n      DWORD buflen;\n      converted_buffer->Lock(&out, nullptr, &buflen);\n      pb->imageRect(rect, out + offset_y * stride + offset_x * 4, (int)stride / 4);\n      converted_buffer->Unlock();\n    }\n  }\n}\n\n// \"7.3.2.1.1 Sequence parameter set data syntax\" on page 66 of https://www.itu.int/rec/T-REC-H.264-202108-I/en\nvoid H264WinDecoderContext::ParseSPS(const uint8_t* buffer, int length)\n{\n#define EXPECT(cond) if (!(cond)) return;\n\n#define GET_BIT(bit) do {            \\\n    if (available == 0)              \\\n    {                                \\\n        if (length == 0) return;     \\\n        byte_ = *buffer++;            \\\n        length--;                    \\\n        available = 8;               \\\n    }                                \\\n    bit = (byte_ >> --available) & 1; \\\n} while (0)\n\n#define GET_BITS(n, var) do {      \\\n    var = 0;                       \\\n    for (int b = n-1; b >= 0; b--) \\\n    {                              \\\n        unsigned bit;              \\\n        GET_BIT(bit);              \\\n        var |= bit << b;           \\\n    }                              \\\n} while (0)\n\n// \"9.1 Parsing process for Exp-Golomb codes\" on page 231\n\n#define GET_UE(var) do {                   \\\n    int zeroes = -1;                       \\\n    for (unsigned bit = 0; !bit; zeroes++) \\\n        GET_BIT(bit);                      \\\n    GET_BITS(zeroes, var);                 \\\n    var += (1U << zeroes) - 1;             \\\n} while(0)\n\n#define SKIP_UE() do { \\\n    unsigned var;      \\\n    GET_UE(var);       \\\n} while (0)\n\n#define SKIP_BITS(bits) do { \\\n    unsigned var;            \\\n    GET_BITS(bits, var);     \\\n} while (0)\n\n    // check for NAL header\n    EXPECT((length >= 3 && buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 1) ||\n           (length >= 4 && buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0 && buffer[3] == 1));\n    length -= 4 - buffer[2];\n    buffer += 4 - buffer[2];\n\n    // NAL unit type\n    EXPECT(length > 1);\n    uint8_t type = buffer[0];\n    EXPECT((type & 0x80) == 0); // forbidden zero bit\n    EXPECT((type & 0x1f) == 7); // SPS NAL unit type\n    buffer++;\n    length--;\n\n    int available = 0;\n    uint8_t byte_ = 0;\n\n    unsigned profile_idc;\n    unsigned seq_parameter_set_id;\n\n    GET_BITS(8, profile_idc);\n    SKIP_BITS(6); // constraint_set0..5_flag\n    SKIP_BITS(2); // reserved_zero_2bits\n    SKIP_BITS(8); // level_idc\n    GET_UE(seq_parameter_set_id);\n\n    unsigned chroma_format_idc = 1;\n    if (profile_idc == 100 || profile_idc == 110 ||\n        profile_idc == 122 || profile_idc == 244 ||\n        profile_idc == 44 || profile_idc == 83 ||\n        profile_idc == 86 || profile_idc == 118 ||\n        profile_idc == 128 || profile_idc == 138 ||\n        profile_idc == 139 || profile_idc == 134 ||\n        profile_idc == 135)\n    {\n        GET_UE(chroma_format_idc);\n        if (chroma_format_idc == 3)\n        {\n            SKIP_BITS(1); // separate_colour_plane_flag\n        }\n        SKIP_UE(); // bit_depth_luma_minus8\n        SKIP_UE(); // bit_depth_chroma_minus8;\n        SKIP_BITS(1); // qpprime_y_zero_transform_bypass_flag\n        unsigned seq_scaling_matrix_present_flag;\n        GET_BITS(1, seq_scaling_matrix_present_flag);\n        if (seq_scaling_matrix_present_flag)\n        {\n            for (int i = 0; i < (chroma_format_idc != 3 ? 8 : 12); i++)\n            {\n                int seq_scaling_list_present_flag;\n                GET_BITS(1, seq_scaling_list_present_flag);\n                for (int j = 0; j < (seq_scaling_list_present_flag ? 16 : 64); j++)\n                {\n                    SKIP_UE(); // delta_scale;\n                }\n            }\n        }\n    }\n\n    unsigned log2_max_frame_num_minus4;\n    GET_UE(log2_max_frame_num_minus4); // log2_max_frame_num_minus4\n    unsigned pic_order_cnt_type;\n    GET_UE(pic_order_cnt_type);\n    if (pic_order_cnt_type == 0)\n    {\n        SKIP_UE(); // log2_max_pic_order_cnt_lsb_minus4\n    }\n    else if (pic_order_cnt_type == 1)\n    {\n        SKIP_BITS(1); // delta_pic_order_always_zero_flag\n        SKIP_UE(); // offset_for_non_ref_pic\n        SKIP_UE(); // offset_for_top_to_bottom_field\n        unsigned num_ref_frames_in_pic_order_cnt_cycle;\n        GET_UE(num_ref_frames_in_pic_order_cnt_cycle);\n        for (unsigned i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++)\n        {\n            SKIP_UE(); // offset_for_ref_frame\n        }\n    }\n    SKIP_UE(); // max_num_ref_frames\n    SKIP_BITS(1); // gaps_in_frame_num_value_allowed_flag\n    unsigned pic_width_in_mbs_minus1;\n    GET_UE(pic_width_in_mbs_minus1);\n    unsigned pic_height_in_map_units_minus1;\n    GET_UE(pic_height_in_map_units_minus1);\n    unsigned frame_mbs_only_flag;\n    GET_BITS(1, frame_mbs_only_flag);\n    if (!frame_mbs_only_flag)\n    {\n        SKIP_BITS(1); // mb_adaptive_frame_field_flag\n    }\n    SKIP_BITS(1); // direct_8x8_inference_flag\n    unsigned frame_cropping_flag;\n    GET_BITS(1, frame_cropping_flag);\n\n    unsigned frame_crop_left_offset = 0;\n    unsigned frame_crop_right_offset = 0;\n    unsigned frame_crop_top_offset = 0;\n    unsigned frame_crop_bottom_offset = 0;\n    if (frame_cropping_flag)\n    {\n        GET_UE(frame_crop_left_offset);\n        GET_UE(frame_crop_right_offset);\n        GET_UE(frame_crop_top_offset);\n        GET_UE(frame_crop_bottom_offset);\n    }\n    // ignore rest of bits\n\n    full_width = 16 * (pic_width_in_mbs_minus1 + 1);\n    full_height = 16 * (pic_height_in_map_units_minus1 + 1) * (2 - frame_mbs_only_flag);\n\n    // \"6.2 Source, decoded, and output picture formats\" on page 44\n    unsigned sub_width_c = (chroma_format_idc  == 1 || chroma_format_idc == 2) ? 2 : 1;\n    unsigned sub_height_c = (chroma_format_idc == 1) ? 2 : 1;\n\n    // page 101\n    unsigned crop_unit_x = chroma_format_idc == 0 ? 1 : sub_width_c;\n    unsigned crop_unit_y = chroma_format_idc == 0 ? 2 - frame_mbs_only_flag : sub_height_c * (2 - frame_mbs_only_flag);\n    crop_width = full_width - crop_unit_x * (frame_crop_right_offset + frame_crop_left_offset);\n    crop_height = full_height - crop_unit_y * (frame_crop_top_offset + frame_crop_bottom_offset);\n\n    offset_x = frame_crop_left_offset;\n    offset_y = frame_crop_bottom_offset;\n\n#undef SKIP_BITS\n#undef SKIP_UE\n#undef GET_BITS\n#undef GET_BIT\n#undef GET_UE\n#undef EXPECT\n}\n"
  },
  {
    "path": "common/rfb/H264WinDecoderContext.h",
    "content": "/* Copyright (C) 2021 Vladimir Sukhonosov <xornet@xornet.org>\n * Copyright (C) 2021 Martins Mozeiko <martins.mozeiko@gmail.com>\n * All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_H264WINDECODER_H__\n#define __RFB_H264WINDECODER_H__\n\n#include <windows.h>\n#include <mfidl.h>\n#include <mftransform.h>\n\n#include <rfb/H264DecoderContext.h>\n\nnamespace rfb {\n  class H264WinDecoderContext : public H264DecoderContext {\n    public:\n      H264WinDecoderContext(const core::Rect &r);\n      ~H264WinDecoderContext();\n\n      void decode(const uint8_t* h264_buffer, uint32_t len,\n                  ModifiablePixelBuffer* pb) override;\n\n    private:\n      LONG stride;\n      uint32_t full_width = 0;\n      uint32_t full_height = 0;\n      uint32_t crop_width = 0;\n      uint32_t crop_height = 0;\n      uint32_t offset_x = 0;\n      uint32_t offset_y = 0;\n      IMFTransform *decoder = nullptr;\n      IMFTransform *converter = nullptr;\n      IMFSample *input_sample = nullptr;\n      IMFSample *decoded_sample = nullptr;\n      IMFSample *converted_sample = nullptr;\n      IMFMediaBuffer *input_buffer = nullptr;\n      IMFMediaBuffer *decoded_buffer = nullptr;\n      IMFMediaBuffer *converted_buffer = nullptr;\n\n      void ParseSPS(const uint8_t* buffer, int length);\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/HextileDecoder.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <algorithm>\n\n#include <rdr/InStream.h>\n#include <rdr/MemInStream.h>\n#include <rdr/OutStream.h>\n\n#include <rfb/Exception.h>\n#include <rfb/ServerParams.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/HextileDecoder.h>\n#include <rfb/hextileConstants.h>\n\nusing namespace rfb;\n\nHextileDecoder::HextileDecoder()\n  : Decoder(DecoderPlain), readTile(0, 0)\n{\n}\n\nHextileDecoder::~HextileDecoder()\n{\n}\n\nbool HextileDecoder::readRect(const core::Rect& r, rdr::InStream* is,\n                              const ServerParams& server, rdr::OutStream* os)\n{\n  size_t bytesPerPixel;\n\n  bytesPerPixel = server.pf().bpp/8;\n\n  for (; readTile.y < r.height(); readTile.y += 16) {\n    int height;\n\n    height = std::min(r.height() - readTile.y, 16);\n\n    for (; readTile.x < r.width(); readTile.x += 16) {\n      int width;\n\n      uint8_t tileType;\n      uint8_t bg[4], fg[4];\n      uint8_t nSubrects;\n\n      width = std::min(r.width() - readTile.x, 16);\n\n      if (!is->hasData(1))\n        return false;\n\n      is->setRestorePoint();\n\n      tileType = is->readU8();\n\n      if (tileType & hextileRaw) {\n        if (!is->hasDataOrRestore(width * height * bytesPerPixel))\n          return false;\n        os->writeU8(tileType);\n        os->copyBytes(is, width * height * bytesPerPixel);\n        is->clearRestorePoint();\n        continue;\n      }\n\n      if (tileType & hextileBgSpecified) {\n        if (!is->hasDataOrRestore(bytesPerPixel))\n          return false;\n        is->readBytes(bg, bytesPerPixel);\n      }\n\n      if (tileType & hextileFgSpecified) {\n        if (!is->hasDataOrRestore(bytesPerPixel))\n          return false;\n        is->readBytes(fg, bytesPerPixel);\n      }\n\n      nSubrects = 0;\n      if (tileType & hextileAnySubrects) {\n        if (!is->hasDataOrRestore(1))\n          return false;\n\n        nSubrects = is->readU8();\n\n        if (tileType & hextileSubrectsColoured) {\n          if (!is->hasDataOrRestore(nSubrects * (bytesPerPixel + 2)))\n            return false;\n        } else {\n          if (!is->hasDataOrRestore(nSubrects * 2))\n            return false;\n        }\n      }\n\n      os->writeU8(tileType);\n      if (tileType & hextileBgSpecified)\n        os->writeBytes(bg, bytesPerPixel);\n      if (tileType & hextileFgSpecified)\n        os->writeBytes(fg, bytesPerPixel);\n      if (tileType & hextileAnySubrects) {\n        os->writeU8(nSubrects);\n        if (tileType & hextileSubrectsColoured)\n          os->copyBytes(is, nSubrects * (bytesPerPixel + 2));\n        else\n          os->copyBytes(is, nSubrects * 2);\n      }\n\n      is->clearRestorePoint();\n    }\n\n    readTile.x = 0;\n  }\n\n  readTile.y = 0;\n\n  return true;\n}\n\nvoid HextileDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,\n                                size_t buflen, const ServerParams& server,\n                                ModifiablePixelBuffer* pb)\n{\n  rdr::MemInStream is(buffer, buflen);\n  const PixelFormat& pf = server.pf();\n  switch (pf.bpp) {\n  case 8:  hextileDecode<uint8_t >(r, &is, pf, pb); break;\n  case 16: hextileDecode<uint16_t>(r, &is, pf, pb); break;\n  case 32: hextileDecode<uint32_t>(r, &is, pf, pb); break;\n  }\n}\n\ntemplate<class T>\ninline T HextileDecoder::readPixel(rdr::InStream* is)\n{\n  if (sizeof(T) == 1)\n    return is->readOpaque8();\n  if (sizeof(T) == 2)\n    return is->readOpaque16();\n  if (sizeof(T) == 4)\n    return is->readOpaque32();\n}\n\ntemplate<class T>\nvoid HextileDecoder::hextileDecode(const core::Rect& r, rdr::InStream* is,\n                                   const PixelFormat& pf,\n                                   ModifiablePixelBuffer* pb)\n{\n  core::Rect t;\n  T bg = 0;\n  T fg = 0;\n  T buf[16 * 16];\n\n  for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {\n\n    t.br.y = std::min(r.br.y, t.tl.y + 16);\n\n    for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {\n\n      t.br.x = std::min(r.br.x, t.tl.x + 16);\n\n      int tileType = is->readU8();\n\n      if (tileType & hextileRaw) {\n        is->readBytes((uint8_t*)buf, t.area() * sizeof(T));\n        pb->imageRect(pf, t, buf);\n        continue;\n      }\n\n      if (tileType & hextileBgSpecified)\n        bg = readPixel<T>(is);\n\n      int len = t.area();\n      T* ptr = buf;\n      while (len-- > 0) *ptr++ = bg;\n\n      if (tileType & hextileFgSpecified)\n        fg = readPixel<T>(is);\n\n      if (tileType & hextileAnySubrects) {\n        int nSubrects = is->readU8();\n\n        for (int i = 0; i < nSubrects; i++) {\n\n          if (tileType & hextileSubrectsColoured)\n            fg = readPixel<T>(is);\n\n          int xy = is->readU8();\n          int wh = is->readU8();\n\n          int x = ((xy >> 4) & 15);\n          int y = (xy & 15);\n          int w = ((wh >> 4) & 15) + 1;\n          int h = (wh & 15) + 1;\n          if (x + w > 16 || y + h > 16) {\n            throw protocol_error(\"HEXTILE_DECODE: Hextile out of bounds\");\n          }\n          ptr = buf + y * t.width() + x;\n          int rowAdd = t.width() - w;\n          while (h-- > 0) {\n            len = w;\n            while (len-- > 0) *ptr++ = fg;\n            ptr += rowAdd;\n          }\n        }\n      }\n      pb->imageRect(pf, t, buf);\n    }\n  }\n}\n"
  },
  {
    "path": "common/rfb/HextileDecoder.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_HEXTILEDECODER_H__\n#define __RFB_HEXTILEDECODER_H__\n\n#include <rfb/Decoder.h>\n\nnamespace rfb {\n\n  class PixelFormat;\n\n  class HextileDecoder : public Decoder {\n  public:\n    HextileDecoder();\n    virtual ~HextileDecoder();\n    bool readRect(const core::Rect& r, rdr::InStream* is,\n                  const ServerParams& server,\n                  rdr::OutStream* os) override;\n    void decodeRect(const core::Rect& r, const uint8_t* buffer,\n                    size_t buflen, const ServerParams& server,\n                    ModifiablePixelBuffer* pb) override;\n  private:\n    template<class T>\n    inline T readPixel(rdr::InStream* is);\n    template<class T>\n    void hextileDecode(const core::Rect& r, rdr::InStream* is,\n                       const PixelFormat& pf,\n                       ModifiablePixelBuffer* pb);\n\n  private:\n    core::Point readTile;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/HextileEncoder.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2005 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <algorithm>\n\n#include <core/Configuration.h>\n\n#include <rdr/OutStream.h>\n\n#include <rfb/encodings.h>\n#include <rfb/SConnection.h>\n#include <rfb/HextileEncoder.h>\n#include <rfb/Palette.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/hextileConstants.h>\n\nusing namespace rfb;\n\ncore::BoolParameter improvedHextile(\"ImprovedHextile\",\n                                    \"Use improved compression \"\n                                    \"algorithm for Hextile encoding \"\n                                    \"which achieves better compression \"\n                                    \"ratios by the cost of using more \"\n                                    \"CPU time\",\n                                    true);\n\nHextileEncoder::HextileEncoder(SConnection* conn_) :\n  Encoder(conn_, encodingHextile, EncoderPlain)\n{\n}\n\nHextileEncoder::~HextileEncoder()\n{\n}\n\nbool HextileEncoder::isSupported()\n{\n  return conn->client.supportsEncoding(encodingHextile);\n}\n\nvoid HextileEncoder::writeRect(const PixelBuffer* pb,\n                               const Palette& /*palette*/)\n{\n  rdr::OutStream* os = conn->getOutStream();\n  switch (pb->getPF().bpp) {\n  case 8:\n    if (improvedHextile) {\n      hextileEncodeBetter<uint8_t>(os, pb);\n    } else {\n      hextileEncode<uint8_t>(os, pb);\n    }\n    break;\n  case 16:\n    if (improvedHextile) {\n      hextileEncodeBetter<uint16_t>(os, pb);\n    } else {\n      hextileEncode<uint16_t>(os, pb);\n    }\n    break;\n  case 32:\n    if (improvedHextile) {\n      hextileEncodeBetter<uint32_t>(os, pb);\n    } else {\n      hextileEncode<uint32_t>(os, pb);\n    }\n    break;\n  }\n}\n\nvoid HextileEncoder::writeSolidRect(int width, int height,\n                                    const PixelFormat& pf,\n                                    const uint8_t* colour)\n{\n  rdr::OutStream* os;\n  int tiles;\n\n  os = conn->getOutStream();\n\n  tiles = ((width + 15)/16) * ((height + 15)/16);\n\n  os->writeU8(hextileBgSpecified);\n  os->writeBytes(colour, pf.bpp/8);\n  tiles--;\n\n  while (tiles--)\n      os->writeU8(0);\n}\n\ntemplate<class T>\ninline void HextileEncoder::writePixel(rdr::OutStream* os, T pixel)\n{\n  if (sizeof(T) == 1)\n    os->writeOpaque8(pixel);\n  else if (sizeof(T) == 2)\n    os->writeOpaque16(pixel);\n  else if (sizeof(T) == 4)\n    os->writeOpaque32(pixel);\n}\n\ntemplate<class T>\nvoid HextileEncoder::hextileEncode(rdr::OutStream* os,\n                                   const PixelBuffer* pb)\n{\n  core::Rect t;\n  T buf[256];\n  T oldBg = 0, oldFg = 0;\n  bool oldBgValid = false;\n  bool oldFgValid = false;\n  uint8_t encoded[256*sizeof(T)];\n\n  for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {\n\n    t.br.y = std::min(pb->height(), t.tl.y + 16);\n\n    for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {\n\n      t.br.x = std::min(pb->width(), t.tl.x + 16);\n\n      pb->getImage(buf, t);\n\n      T bg = 0, fg = 0;\n      int tileType = testTileType(buf, t.width(), t.height(), &bg, &fg);\n\n      if (!oldBgValid || oldBg != bg) {\n        tileType |= hextileBgSpecified;\n        oldBg = bg;\n        oldBgValid = true;\n      }\n\n      int encodedLen = 0;\n\n      if (tileType & hextileAnySubrects) {\n\n        if (tileType & hextileSubrectsColoured) {\n          oldFgValid = false;\n        } else {\n          if (!oldFgValid || oldFg != fg) {\n            tileType |= hextileFgSpecified;\n            oldFg = fg;\n            oldFgValid = true;\n          }\n        }\n\n        encodedLen = hextileEncodeTile(buf, t.width(), t.height(),\n                                       tileType, encoded, bg);\n\n        if (encodedLen < 0) {\n          pb->getImage(buf, t);\n          os->writeU8(hextileRaw);\n          os->writeBytes((const uint8_t*)buf,\n                         t.width() * t.height() * sizeof(T));\n          oldBgValid = oldFgValid = false;\n          continue;\n        }\n      }\n\n      os->writeU8(tileType);\n      if (tileType & hextileBgSpecified) writePixel(os, bg);\n      if (tileType & hextileFgSpecified) writePixel(os, fg);\n      if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen);\n    }\n  }\n}\n\ntemplate<class T>\nint HextileEncoder::hextileEncodeTile(T* data, int w, int h,\n                                      int tileType, uint8_t* encoded,\n                                      T bg)\n{\n  uint8_t* nSubrectsPtr = encoded;\n  *nSubrectsPtr = 0;\n  encoded++;\n\n  for (int y = 0; y < h; y++)\n  {\n    int x = 0;\n    while (x < w) {\n      if (*data == bg) {\n        x++;\n        data++;\n        continue;\n      }\n\n      // Find horizontal subrect first\n      T* ptr = data+1;\n      T* eol = data+w-x;\n      while (ptr < eol && *ptr == *data) ptr++;\n      int sw = ptr - data;\n\n      ptr = data + w;\n      int sh = 1;\n      while (sh < h-y) {\n        eol = ptr + sw;\n        while (ptr < eol)\n          if (*ptr++ != *data) goto endOfSubrect;\n        ptr += w - sw;\n        sh++;\n      }\n    endOfSubrect:\n\n      (*nSubrectsPtr)++;\n\n      if (tileType & hextileSubrectsColoured) {\n        if (encoded - nSubrectsPtr + sizeof(T) > w*h*sizeof(T))\n          return -1;\n\n        if (sizeof(T) == 1) {\n          *encoded++ = *data;\n        } else if (sizeof(T) == 2) {\n          *encoded++ = ((uint8_t*)data)[0];\n          *encoded++ = ((uint8_t*)data)[1];\n        } else if (sizeof(T) == 4) {\n          *encoded++ = ((uint8_t*)data)[0];\n          *encoded++ = ((uint8_t*)data)[1];\n          *encoded++ = ((uint8_t*)data)[2];\n          *encoded++ = ((uint8_t*)data)[3];\n        }\n      }\n\n      if ((size_t)(encoded - nSubrectsPtr + 2) > w*h*sizeof(T))\n        return -1;\n      *encoded++ = (x << 4) | y;\n      *encoded++ = ((sw-1) << 4) | (sh-1);\n\n      ptr = data+w;\n      T* eor = data+w*sh;\n      while (ptr < eor) {\n        eol = ptr + sw;\n        while (ptr < eol) *ptr++ = bg;\n        ptr += w - sw;\n      }\n      x += sw;\n      data += sw;\n    }\n  }\n  return encoded - nSubrectsPtr;\n}\n\ntemplate<class T>\nint HextileEncoder::testTileType(T* data, int w, int h, T* bg, T* fg)\n{\n  T pix1 = *data;\n  T* end = data + w * h;\n\n  T* ptr = data + 1;\n  while (ptr < end && *ptr == pix1)\n    ptr++;\n\n  if (ptr == end) {\n    *bg = pix1;\n    return 0;                   // solid-color tile\n  }\n\n  int count1 = ptr - data;\n  int count2 = 1;\n  T pix2 = *ptr++;\n  int tileType = hextileAnySubrects;\n\n  for (; ptr < end; ptr++) {\n    if (*ptr == pix1) {\n      count1++;\n    } else if (*ptr == pix2) {\n      count2++;\n    } else {\n      tileType |= hextileSubrectsColoured;\n      break;\n    }\n  }\n\n  if (count1 >= count2) {\n    *bg = pix1; *fg = pix2;\n  } else {\n    *bg = pix2; *fg = pix1;\n  }\n  return tileType;\n}\n\n//\n// This class analyzes a separate tile and encodes its subrectangles.\n//\n\ntemplate<class T>\nclass HextileTile {\n\n public:\n\n  HextileTile ();\n\n  //\n  // Initialize existing object instance with new tile data.\n  //\n  void newTile(const T *src, int w, int h);\n\n  //\n  // Flags can include: hextileRaw, hextileAnySubrects and\n  // hextileSubrectsColoured. Note that if hextileRaw is set, other\n  // flags make no sense. Also, hextileSubrectsColoured is meaningful\n  // only when hextileAnySubrects is set as well.\n  //\n  int getFlags() const { return m_flags; }\n\n  //\n  // Returns the size of encoded subrects data, including subrect count.\n  // The size is zero if flags do not include hextileAnySubrects.\n  //\n  size_t getSize() const { return m_size; }\n\n  //\n  // Return optimal background.\n  //\n  int getBackground() const { return m_background; }\n\n  //\n  // Return foreground if flags include hextileSubrectsColoured.\n  //\n  int getForeground() const { return m_foreground; }\n\n  //\n  // Encode subrects. This function may be called only if\n  // hextileAnySubrects bit is set in flags. The buffer size should be\n  // big enough to store at least the number of bytes returned by the\n  // getSize() method.\n  //\n  void encode(uint8_t* dst) const;\n\n protected:\n\n  //\n  // Analyze the tile pixels, fill in all the data fields.\n  //\n  void analyze();\n\n  const T *m_tile;\n  int m_width;\n  int m_height;\n\n  size_t m_size;\n  int m_flags;\n  T m_background;\n  T m_foreground;\n\n  int m_numSubrects;\n  uint8_t m_coords[256 * 2];\n  T m_colors[256];\n\n private:\n\n  bool m_processed[16][16];\n  Palette m_pal;\n};\n\ntemplate<class T>\nHextileTile<T>::HextileTile()\n  : m_tile(nullptr), m_width(0), m_height(0),\n    m_size(0), m_flags(0), m_background(0), m_foreground(0),\n    m_numSubrects(0)\n{\n}\n\ntemplate<class T>\nvoid HextileTile<T>::newTile(const T *src, int w, int h)\n{\n  m_tile = src;\n  m_width = w;\n  m_height = h;\n\n  analyze();\n}\n\ntemplate<class T>\nvoid HextileTile<T>::analyze()\n{\n  assert(m_tile && m_width && m_height);\n\n  const T *ptr = m_tile;\n  const T *end = &m_tile[m_width * m_height];\n  T color = *ptr++;\n  while (ptr != end && *ptr == color)\n    ptr++;\n\n  // Handle solid tile\n  if (ptr == end) {\n    m_background = m_tile[0];\n    m_flags = 0;\n    m_size = 0;\n    return;\n  }\n\n  // Compute number of complete rows of the same color, at the top\n  int y = (ptr - m_tile) / m_width;\n\n  T *colorsPtr = m_colors;\n  uint8_t *coordsPtr = m_coords;\n  m_pal.clear();\n  m_numSubrects = 0;\n\n  // Have we found the first subrect already?\n  if (y > 0) {\n    *colorsPtr++ = color;\n    *coordsPtr++ = 0;\n    *coordsPtr++ = (uint8_t)(((m_width - 1) << 4) | ((y - 1) & 0x0F));\n    m_pal.insert(color, 1);\n    m_numSubrects++;\n  }\n\n  memset(m_processed, 0, 16 * 16 * sizeof(bool));\n\n  int x, sx, sy, sw, sh, max_x;\n\n  for (; y < m_height; y++) {\n    for (x = 0; x < m_width; x++) {\n      // Skip pixels that were processed earlier\n      if (m_processed[y][x]) {\n        continue;\n      }\n      // Determine dimensions of the horizontal subrect\n      color = m_tile[y * m_width + x];\n      for (sx = x + 1; sx < m_width; sx++) {\n        if (m_tile[y * m_width + sx] != color)\n          break;\n      }\n      sw = sx - x;\n      max_x = sx;\n      for (sy = y + 1; sy < m_height; sy++) {\n        for (sx = x; sx < max_x; sx++) {\n          if (m_tile[sy * m_width + sx] != color)\n            goto done;\n        }\n      }\n    done:\n      sh = sy - y;\n\n      // Save properties of this subrect\n      *colorsPtr++ = color;\n      *coordsPtr++ = (uint8_t)((x << 4) | (y & 0x0F));\n      *coordsPtr++ = (uint8_t)(((sw - 1) << 4) | ((sh - 1) & 0x0F));\n\n      if (!m_pal.insert(color, 1) ||\n          ((size_t)m_pal.size() > (48 + 2 * sizeof(T)*8))) {\n        // Handle palette overflow\n        m_flags = hextileRaw;\n        m_size = 0;\n        return;\n      }\n\n      m_numSubrects++;\n\n      // Mark pixels of this subrect as processed, below this row\n      for (sy = y + 1; sy < y + sh; sy++) {\n        for (sx = x; sx < x + sw; sx++)\n          m_processed[sy][sx] = true;\n      }\n\n      // Skip processed pixels of this row\n      x += (sw - 1);\n    }\n  }\n\n  // Save number of colors in this tile (should be no less than 2)\n  int numColors = m_pal.size();\n  assert(numColors >= 2);\n\n  m_background = (T)m_pal.getColour(0);\n  m_flags = hextileAnySubrects;\n  int numSubrects = m_numSubrects - m_pal.getCount(0);\n\n  if (numColors == 2) {\n    // Monochrome tile\n    m_foreground = (T)m_pal.getColour(1);\n    m_size = 1 + 2 * numSubrects;\n  } else {\n    // Colored tile\n    m_flags |= hextileSubrectsColoured;\n    m_size = 1 + (2 + sizeof(T)) * numSubrects;\n  }\n}\n\ntemplate<class T>\nvoid HextileTile<T>::encode(uint8_t *dst) const\n{\n  assert(m_numSubrects && (m_flags & hextileAnySubrects));\n\n  // Zero subrects counter\n  uint8_t *numSubrectsPtr = dst;\n  *dst++ = 0;\n\n  for (int i = 0; i < m_numSubrects; i++) {\n    if (m_colors[i] == m_background)\n      continue;\n\n    if (m_flags & hextileSubrectsColoured) {\n      if (sizeof(T) == 1) {\n        *dst++ = m_colors[i];\n      } else if (sizeof(T) == 2) {\n        *dst++ = ((uint8_t*)&m_colors[i])[0];\n        *dst++ = ((uint8_t*)&m_colors[i])[1];\n      } else if (sizeof(T) == 4) {\n        *dst++ = ((uint8_t*)&m_colors[i])[0];\n        *dst++ = ((uint8_t*)&m_colors[i])[1];\n        *dst++ = ((uint8_t*)&m_colors[i])[2];\n        *dst++ = ((uint8_t*)&m_colors[i])[3];\n      }\n    }\n    *dst++ = m_coords[i * 2];\n    *dst++ = m_coords[i * 2 + 1];\n\n    (*numSubrectsPtr)++;\n  }\n\n  assert((size_t)(dst - numSubrectsPtr) == m_size);\n}\n\n//\n// Main encoding function.\n//\n\ntemplate<class T>\nvoid HextileEncoder::hextileEncodeBetter(rdr::OutStream* os,\n                                         const PixelBuffer* pb)\n{\n  core::Rect t;\n  T buf[256];\n  T oldBg = 0, oldFg = 0;\n  bool oldBgValid = false;\n  bool oldFgValid = false;\n  uint8_t encoded[256*sizeof(T)];\n\n  HextileTile<T> tile;\n\n  for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {\n\n    t.br.y = std::min(pb->height(), t.tl.y + 16);\n\n    for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {\n\n      t.br.x = std::min(pb->width(), t.tl.x + 16);\n\n      pb->getImage(buf, t);\n\n      tile.newTile(buf, t.width(), t.height());\n      int tileType = tile.getFlags();\n      size_t encodedLen = tile.getSize();\n\n      if ( (tileType & hextileRaw) != 0 ||\n           encodedLen >= t.width() * t.height() * sizeof(T)) {\n        os->writeU8(hextileRaw);\n        os->writeBytes((const uint8_t*)buf,\n                       t.width() * t.height() * sizeof(T));\n        oldBgValid = oldFgValid = false;\n        continue;\n      }\n\n      T bg = tile.getBackground();\n      T fg = 0;\n\n      if (!oldBgValid || oldBg != bg) {\n        tileType |= hextileBgSpecified;\n        oldBg = bg;\n        oldBgValid = true;\n      }\n\n      if (tileType & hextileAnySubrects) {\n        if (tileType & hextileSubrectsColoured) {\n          oldFgValid = false;\n        } else {\n          fg = tile.getForeground();\n          if (!oldFgValid || oldFg != fg) {\n            tileType |= hextileFgSpecified;\n            oldFg = fg;\n            oldFgValid = true;\n          }\n        }\n        tile.encode(encoded);\n      }\n\n      os->writeU8(tileType);\n      if (tileType & hextileBgSpecified) writePixel(os, bg);\n      if (tileType & hextileFgSpecified) writePixel(os, fg);\n      if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen);\n    }\n  }\n}\n"
  },
  {
    "path": "common/rfb/HextileEncoder.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_HEXTILEENCODER_H__\n#define __RFB_HEXTILEENCODER_H__\n\n#include <rfb/Encoder.h>\n\nnamespace rfb {\n\n  class HextileEncoder : public Encoder {\n  public:\n    HextileEncoder(SConnection* conn);\n    virtual ~HextileEncoder();\n    bool isSupported() override;\n    void writeRect(const PixelBuffer* pb,\n                   const Palette& palette) override;\n    void writeSolidRect(int width, int height, const PixelFormat& pf,\n                        const uint8_t* colour) override;\n  private:\n    template<class T>\n    inline void writePixel(rdr::OutStream* os, T pixel);\n\n    template<class T>\n    void hextileEncode(rdr::OutStream* os, const PixelBuffer* pb);\n    template<class T>\n    int hextileEncodeTile(T* data, int w, int h, int tileType,\n                          uint8_t* encoded, T bg);\n    template<class T>\n    int testTileType(T* data, int w, int h, T* bg, T* fg);\n\n    template<class T>\n    void hextileEncodeBetter(rdr::OutStream* os, const PixelBuffer* pb);\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/JPEGDecoder.cxx",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright 2004-2005 Cendio AB.\n * Copyright 2009-2025 Pierre Ossman for Cendio AB\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <core/string.h>\n\n#include <rdr/InStream.h>\n#include <rdr/OutStream.h>\n\n#include <rfb/ServerParams.h>\n#include <rfb/Exception.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/JPEGDecoder.h>\n\nusing namespace rfb;\n\nJPEGDecoder::JPEGDecoder() : Decoder(DecoderPlain), state(IDLE)\n{\n}\n\nJPEGDecoder::~JPEGDecoder()\n{\n}\n\nbool JPEGDecoder::readRect(const core::Rect& /*r*/, rdr::InStream* is,\n                           const ServerParams& /*server*/,\n                           rdr::OutStream* os)\n{\n  if (state == IDLE)\n    state = SEGMENT;\n\n  while (state != IDLE) {\n    if (state == SEGMENT) {\n      if (!readSegment(is, os))\n        return false;\n    }\n\n    if (state == STREAM) {\n      if (!readStream(is, os))\n        return false;\n    }\n  }\n\n  return true;\n}\n\nbool JPEGDecoder::readSegment(rdr::InStream* is, rdr::OutStream* os)\n{\n  uint8_t marker, type;\n  uint16_t len;\n\n  if (!is->hasData(2))\n    return false;\n\n  is->setRestorePoint();\n\n  marker = is->readU8();\n  type = is->readU8();\n\n  if (marker != 0xff)\n    throw protocol_error(\n      core::format(\"Invalid JPEG segment marker: 0x%02x\", marker));\n\n  // Markers without data\n  if ((type == 0x01) || ((type >= 0xd0) && type <= 0xd9)) {\n    os->writeU8(marker);\n    os->writeU8(type);\n\n    is->clearRestorePoint();\n\n    // End of image?\n    if (type == 0xd9)\n      state = IDLE;\n\n    return true;\n  }\n\n  if (!is->hasDataOrRestore(2))\n    return false;\n\n  len = is->readU16();\n\n  if (!is->hasDataOrRestore(len-2))\n    return false;\n\n  if (type == 0xc0) {\n    // start of frame, reset our state\n    seenHuffman = false;\n    seenQuant = false;\n  }\n\n  if (type == 0xc4) {\n    const uint8_t *in;\n    uint8_t *out;\n\n    if (!seenHuffman)\n      lastHuffmanTables.clear();\n    seenHuffman = true;\n\n    lastHuffmanTables.resize(lastHuffmanTables.size() + 1);\n    lastHuffmanTables.back().resize(2 + len);\n\n    in = is->getptr(len-2);\n    out = lastHuffmanTables.back().data();\n\n    out[0] = marker;\n    out[1] = type;\n    out[2] = (len >> 8) & 0xff;\n    out[3] = (len >> 0) & 0xff;\n    memcpy(out + 4, in, len-2);\n\n    // getptr() resets the amount of assured data\n    is->hasData(len-2);\n  }\n\n  if (type == 0xdb) {\n    const uint8_t *in;\n    uint8_t *out;\n\n    if (!seenQuant)\n      lastQuantTables.clear();\n    seenQuant = true;\n\n    lastQuantTables.resize(lastQuantTables.size() + 1);\n    lastQuantTables.back().resize(2 + len);\n\n    in = is->getptr(len-2);\n    out = lastQuantTables.back().data();\n\n    out[0] = marker;\n    out[1] = type;\n    out[2] = (len >> 8) & 0xff;\n    out[3] = (len >> 0) & 0xff;\n    memcpy(out + 4, in, len-2);\n\n    // getptr() resets the amount of assured data\n    is->hasData(len-2);\n  }\n\n  if (type == 0xda) {\n    // start of image data, time to inject tables if they are missing\n\n    if (!seenHuffman) {\n      std::vector< std::vector<uint8_t> >::const_iterator iter;\n\n      for (iter = lastHuffmanTables.begin();\n            iter != lastHuffmanTables.end(); ++iter)\n        os->writeBytes(iter->data(), iter->size());\n    }\n\n    if (!seenQuant) {\n      std::vector< std::vector<uint8_t> >::const_iterator iter;\n\n      for (iter = lastQuantTables.begin();\n            iter != lastQuantTables.end(); ++iter)\n        os->writeBytes(iter->data(), iter->size());\n    }\n  }\n\n  os->writeU8(marker);\n  os->writeU8(type);\n  os->writeU16(len);\n  os->copyBytes(is, len-2);\n\n  is->clearRestorePoint();\n\n  // Start of stream?\n  if (type == 0xda)\n    state = STREAM;\n\n  return true;\n}\n\nbool JPEGDecoder::readStream(rdr::InStream* is, rdr::OutStream* os)\n{\n  // Peek instream until we see a marker that isn't a restart marker\n  size_t avail;\n  const uint8_t* ptr;\n  const uint8_t* in;\n\n  if (!is->hasData(2))\n    return false;\n\n  avail = is->avail();\n  ptr = in = is->getptr(avail);\n  while (in < (ptr + avail)) {\n    in = (const uint8_t*)memchr(in, 0xff, (avail - (in - ptr))-1);\n\n    if (in == nullptr)\n      break;\n\n    if ((in[1] != 0x00) && !((in[1] >= 0xd0) && (in[1] <= 0xd7))) {\n      is->hasData(in - ptr);\n      os->copyBytes(is, in - ptr);\n\n      state = SEGMENT;\n      return true;\n    }\n\n    in += 2;\n  }\n\n  is->hasData(avail-1);\n  os->copyBytes(is, avail-1);\n\n  return false;\n}\n\nvoid JPEGDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,\n                             size_t buflen,\n                             const ServerParams& /*server*/,\n                             ModifiablePixelBuffer* pb)\n{\n  int stride;\n  uint8_t *buf;\n\n  JpegDecompressor jd;\n\n  buf = pb->getBufferRW(r, &stride);\n  jd.decompress(buffer, buflen, buf, stride, r, pb->getPF());\n  pb->commitBufferRW(r);\n}\n"
  },
  {
    "path": "common/rfb/JPEGDecoder.h",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2009-2025 Pierre Ossman for Cendio AB\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_JPEGDECODER_H__\n#define __RFB_JPEGDECODER_H__\n\n#include <vector>\n\n#include <rfb/Decoder.h>\n#include <rfb/JpegDecompressor.h>\n\nnamespace rfb {\n\n  class JPEGDecoder : public Decoder {\n\n  public:\n    JPEGDecoder();\n    virtual ~JPEGDecoder();\n    bool readRect(const core::Rect& r, rdr::InStream* is,\n                  const ServerParams& server,\n                  rdr::OutStream* os) override;\n    void decodeRect(const core::Rect& r, const uint8_t* buffer,\n                    size_t buflen, const ServerParams& server,\n                    ModifiablePixelBuffer* pb) override;\n\n  private:\n    bool readSegment(rdr::InStream* is, rdr::OutStream* os);\n    bool readStream(rdr::InStream* is, rdr::OutStream* os);\n\n  private:\n    enum {\n      IDLE,\n      SEGMENT,\n      STREAM,\n    } state;\n    bool seenHuffman, seenQuant;\n    std::vector< std::vector<uint8_t> > lastHuffmanTables;\n    std::vector< std::vector<uint8_t> > lastQuantTables;\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/JPEGEncoder.cxx",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014-2023 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <rdr/OutStream.h>\n#include <rfb/encodings.h>\n#include <rfb/SConnection.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/JPEGEncoder.h>\n\nusing namespace rfb;\n\nJPEGEncoder::JPEGEncoder(SConnection* conn_) :\n  Encoder(conn_, encodingJPEG,\n          (EncoderFlags)(EncoderUseNativePF | EncoderLossy), -1, 9)\n{\n}\n\nJPEGEncoder::~JPEGEncoder()\n{\n}\n\nbool JPEGEncoder::isSupported()\n{\n  return conn->client.supportsEncoding(encodingJPEG);\n}\n\nvoid JPEGEncoder::setQualityLevel(int level)\n{\n  jc.setQualityLevel(level);\n}\n\nvoid JPEGEncoder::setFineQualityLevel(int quality, int subsampling)\n{\n  jc.setFineQualityLevel(quality, subsampling);\n}\n\nint JPEGEncoder::getQualityLevel()\n{\n  return jc.getQualityLevel();\n}\n\nvoid JPEGEncoder::writeRect(const PixelBuffer* pb,\n                            const Palette& /*palette*/)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  const uint8_t* data;\n  size_t len;\n\n  rdr::OutStream* os;\n\n  buffer = pb->getBuffer(pb->getRect(), &stride);\n\n  jc.clear();\n  jc.compress(buffer, stride, pb->getRect(), pb->getPF());\n\n  os = conn->getOutStream();\n\n  data = jc.data();\n  len = jc.length();\n\n  // scan through the segments to look for the huffman table and the\n  // quantization table\n  while (true) {\n    uint8_t type;\n    size_t seglen;\n\n    assert(len >= 2);\n\n    assert(data[0] == 0xff);\n    type = data[1];\n\n    // segment without length?\n    if ((type == 0x01) || ((type >= 0xd0) && (type <= 0xd9))) {\n      os->writeBytes(data, 2);\n      data += 2;\n      len -= 2;\n      continue;\n    }\n\n    assert(len >= 4);\n\n    seglen = data[2] << 16 | data[3];\n\n    assert(len >= (2 + seglen));\n\n    if (type == 0xc4) {\n      // huffman table\n\n      size_t totallen;\n\n      // there are multiple tables following each other\n      totallen = 2 + seglen;\n      while (true) {\n        assert(len >= totallen + 1);\n        assert(data[totallen] == 0xff);\n\n        assert(len >= totallen + 2);\n        if (data[totallen + 1] != 0xc4)\n            break;\n\n        seglen = data[totallen + 2] << 16 | data[totallen + 3];\n\n        assert(len >= (totallen + 2 + seglen));\n\n        totallen += 2 + seglen;\n      }\n\n      if ((totallen == lastHuffmanTables.size()) &&\n          (memcmp(data, lastHuffmanTables.data(), totallen) == 0)) {\n        // same table as last rect, so skip it\n        data += totallen;\n        len -= totallen;\n        continue;\n      }\n\n      // store this for the next rect\n      lastHuffmanTables.resize(totallen);\n      memcpy(lastHuffmanTables.data(), data, totallen);\n\n      os->writeBytes(data, totallen);\n      data += totallen;\n      len -= totallen;\n      continue;\n    }\n\n    if (type == 0xdb) {\n      // quantization table\n\n      size_t totallen;\n\n      // there are multiple tables following each other\n      totallen = 2 + seglen;\n      while (true) {\n        assert(len >= totallen + 1);\n        assert(data[totallen] == 0xff);\n\n        assert(len >= totallen + 2);\n        if (data[totallen + 1] != 0xdb)\n            break;\n\n        seglen = data[totallen + 2] << 16 | data[totallen + 3];\n\n        assert(len >= (totallen + 2 + seglen));\n\n        totallen += 2 + seglen;\n      }\n\n      if ((totallen == lastQuantTables.size()) &&\n          (memcmp(data, lastQuantTables.data(), totallen) == 0)) {\n        // same table as last rect, so skip it\n        data += totallen;\n        len -= totallen;\n        continue;\n      }\n\n      // store this for the next rect\n      lastQuantTables.resize(totallen);\n      memcpy(lastQuantTables.data(), data, totallen);\n\n      os->writeBytes(data, totallen);\n      data += totallen;\n      len -= totallen;\n      continue;\n    }\n\n    if (type == 0xda) {\n      // start of scan, i.e. the actual image data, so we are done\n      os->writeBytes(data, len);\n      break;\n    }\n\n    // some other segment\n    os->writeBytes(data, 2 + seglen);\n    data += 2 + seglen;\n    len -= 2 + seglen;\n  }\n}\n\nvoid JPEGEncoder::writeSolidRect(int width, int height,\n                                 const PixelFormat& pf,\n                                 const uint8_t* colour)\n{\n  // FIXME: Add a shortcut in the JPEG compressor to handle this case\n  //        without having to use the default fallback which is very slow.\n  Encoder::writeSolidRect(width, height, pf, colour);\n}\n"
  },
  {
    "path": "common/rfb/JPEGEncoder.h",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander\n * Copyright 2014-2023 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_JPEGENCODER_H__\n#define __RFB_JPEGENCODER_H__\n\n#include <vector>\n\n#include <rfb/Encoder.h>\n#include <rfb/JpegCompressor.h>\n\nnamespace rfb {\n\n  class JPEGEncoder : public Encoder {\n  public:\n    JPEGEncoder(SConnection* conn);\n    virtual ~JPEGEncoder();\n\n    bool isSupported() override;\n\n    void setQualityLevel(int level) override;\n    void setFineQualityLevel(int quality, int subsampling) override;\n\n    int getQualityLevel() override;\n\n    void writeRect(const PixelBuffer* pb,\n                   const Palette& palette) override;\n    void writeSolidRect(int width, int height, const PixelFormat& pf,\n                        const uint8_t* colour) override;\n\n  protected:\n    JpegCompressor jc;\n\n    std::vector<uint8_t> lastHuffmanTables;\n    std::vector<uint8_t> lastQuantTables;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/JpegCompressor.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdexcept>\n\n#include <core/Rect.h>\n\n#include <rfb/JpegCompressor.h>\n#include <rfb/PixelFormat.h>\n#include <rfb/ClientParams.h>\n\n#include <stdio.h>\nextern \"C\" {\n#include <jpeglib.h>\n}\n#include <setjmp.h>\n\nusing namespace rfb;\n\nstruct JPEGConfiguration {\n    int quality;\n    int subsampling;\n};\n\n// NOTE:  The JPEG quality and subsampling levels below were obtained\n// experimentally by the VirtualGL project.  They represent the approximate\n// average compression ratios listed below, as measured across the set of\n// every 10th frame in the SPECviewperf 9 benchmark suite.\n//\n// 9 = JPEG quality 100, no subsampling (ratio ~= 10:1)\n//     [this should be lossless, except for round-off error]\n// 8 = JPEG quality 92,  no subsampling (ratio ~= 20:1)\n//     [this should be perceptually lossless, based on current research]\n// 7 = JPEG quality 86,  no subsampling (ratio ~= 25:1)\n// 6 = JPEG quality 79,  no subsampling (ratio ~= 30:1)\n// 5 = JPEG quality 77,  4:2:2 subsampling (ratio ~= 40:1)\n// 4 = JPEG quality 62,  4:2:2 subsampling (ratio ~= 50:1)\n// 3 = JPEG quality 42,  4:2:2 subsampling (ratio ~= 60:1)\n// 2 = JPEG quality 41,  4:2:0 subsampling (ratio ~= 70:1)\n// 1 = JPEG quality 29,  4:2:0 subsampling (ratio ~= 80:1)\n// 0 = JPEG quality 15,  4:2:0 subsampling (ratio ~= 100:1)\n\nstatic const struct JPEGConfiguration conf[10] = {\n  {  15, subsample4X }, // 0\n  {  29, subsample4X }, // 1\n  {  41, subsample4X }, // 2\n  {  42, subsample2X }, // 3\n  {  62, subsample2X }, // 4\n  {  77, subsample2X }, // 5\n  {  79, subsampleNone }, // 6\n  {  86, subsampleNone }, // 7\n  {  92, subsampleNone }, // 8\n  { 100, subsampleNone }  // 9\n};\n\n//\n// Special formats that libjpeg can have optimised code paths for\n//\n\nstatic const PixelFormat pfRGBX(32, 24, false, true, 255, 255, 255, 0, 8, 16);\nstatic const PixelFormat pfBGRX(32, 24, false, true, 255, 255, 255, 16, 8, 0);\nstatic const PixelFormat pfXRGB(32, 24, false, true, 255, 255, 255, 8, 16, 24);\nstatic const PixelFormat pfXBGR(32, 24, false, true, 255, 255, 255, 24, 16, 8);\n\n//\n// Error manager implementation for the JPEG library\n//\n\nstruct JPEG_ERROR_MGR {\n  struct jpeg_error_mgr pub;\n  jmp_buf jmpBuffer;\n  char lastError[JMSG_LENGTH_MAX];\n};\n\nstatic void\nJpegErrorExit(j_common_ptr cinfo)\n{\n  JPEG_ERROR_MGR *err = (JPEG_ERROR_MGR *)cinfo->err;\n\n  (*cinfo->err->output_message)(cinfo);\n  longjmp(err->jmpBuffer, 1);\n}\n\nstatic void\nJpegOutputMessage(j_common_ptr cinfo)\n{\n  JPEG_ERROR_MGR *err = (JPEG_ERROR_MGR *)cinfo->err;\n\n  (*cinfo->err->format_message)(cinfo, err->lastError);\n}\n\n//\n// Destination manager implementation for the JPEG library.\n//\n\nstruct JPEG_DEST_MGR {\n  struct jpeg_destination_mgr pub;\n  JpegCompressor *instance;\n  size_t chunkSize;\n};\n\nstatic void\nJpegInitDestination(j_compress_ptr cinfo)\n{\n  JPEG_DEST_MGR *dest = (JPEG_DEST_MGR *)cinfo->dest;\n  JpegCompressor *jc = dest->instance;\n\n  jc->clear();\n  dest->pub.next_output_byte = jc->getptr(jc->length());\n  dest->pub.free_in_buffer = dest->chunkSize = jc->avail();\n}\n\nstatic boolean\nJpegEmptyOutputBuffer(j_compress_ptr cinfo)\n{\n  JPEG_DEST_MGR *dest = (JPEG_DEST_MGR *)cinfo->dest;\n  JpegCompressor *jc = dest->instance;\n\n  jc->setptr(jc->avail());\n  dest->pub.next_output_byte = jc->getptr(jc->length());\n  dest->pub.free_in_buffer = dest->chunkSize = jc->avail();\n\n  return TRUE;\n}\n\nstatic void\nJpegTermDestination(j_compress_ptr cinfo)\n{\n  JPEG_DEST_MGR *dest = (JPEG_DEST_MGR *)cinfo->dest;\n  JpegCompressor *jc = dest->instance;\n\n  jc->setptr(dest->chunkSize - dest->pub.free_in_buffer);\n}\n\nJpegCompressor::JpegCompressor(int bufferLen) :\n  MemOutStream(bufferLen),\n  qualityLevel(-1), fineQuality(-1), fineSubsampling(subsampleUndefined)\n{\n  cinfo = new jpeg_compress_struct;\n\n  err = new struct JPEG_ERROR_MGR;\n  cinfo->err = jpeg_std_error(&err->pub);\n  snprintf(err->lastError, JMSG_LENGTH_MAX, \"No error\");\n  err->pub.error_exit = JpegErrorExit;\n  err->pub.output_message = JpegOutputMessage;\n\n  if(setjmp(err->jmpBuffer)) {\n    // this will execute if libjpeg has an error\n    throw std::runtime_error(err->lastError);\n  }\n\n  jpeg_create_compress(cinfo);\n\n  dest = new struct JPEG_DEST_MGR;\n  dest->pub.init_destination = JpegInitDestination;\n  dest->pub.empty_output_buffer = JpegEmptyOutputBuffer;\n  dest->pub.term_destination = JpegTermDestination;\n  dest->instance = this;\n  cinfo->dest = (struct jpeg_destination_mgr *)dest;\n}\n\nJpegCompressor::~JpegCompressor(void)\n{\n  if(setjmp(err->jmpBuffer)) {\n    // this will execute if libjpeg has an error\n    return;\n  }\n\n  jpeg_destroy_compress(cinfo);\n\n  delete err;\n  delete dest;\n\n  delete cinfo;\n}\n\nvoid JpegCompressor::setQualityLevel(int level)\n{\n  qualityLevel = level;\n}\n\nvoid JpegCompressor::setFineQualityLevel(int quality, int subsampling)\n{\n  fineQuality = quality;\n  fineSubsampling = subsampling;\n}\n\nint JpegCompressor::getQualityLevel()\n{\n  return qualityLevel;\n}\n\nvoid JpegCompressor::compress(const uint8_t *buf, volatile int stride,\n                              const core::Rect& r,\n                              const PixelFormat& pf)\n{\n  int quality, subsampling;\n  int w = r.width();\n  int h = r.height();\n  int pixelsize;\n  uint8_t * volatile srcBuf = nullptr;\n  volatile bool srcBufIsTemp = false;\n  JSAMPROW * volatile rowPointer = nullptr;\n\n  if (qualityLevel >= 0 && qualityLevel <= 9) {\n    quality = conf[qualityLevel].quality;\n    subsampling = conf[qualityLevel].subsampling;\n  } else {\n    quality = -1;\n    subsampling = subsampleUndefined;\n  }\n\n  // Fine settings trump level\n  if (fineQuality != -1)\n    quality = fineQuality;\n  if (fineSubsampling != subsampleUndefined)\n    subsampling = fineSubsampling;\n\n  if(setjmp(err->jmpBuffer)) {\n    // this will execute if libjpeg has an error\n    jpeg_abort_compress(cinfo);\n    if (srcBufIsTemp && srcBuf) delete[] srcBuf;\n    if (rowPointer) delete[] rowPointer;\n    throw std::runtime_error(err->lastError);\n  }\n\n  cinfo->image_width = w;\n  cinfo->image_height = h;\n  cinfo->in_color_space = JCS_RGB;\n  pixelsize = 3;\n\n#ifdef JCS_EXTENSIONS\n  // Try to have libjpeg output directly to our native format\n  // libjpeg can only handle some \"standard\" formats\n  if (pfRGBX == pf)\n    cinfo->in_color_space = JCS_EXT_RGBX;\n  else if (pfBGRX == pf)\n    cinfo->in_color_space = JCS_EXT_BGRX;\n  else if (pfXRGB == pf)\n    cinfo->in_color_space = JCS_EXT_XRGB;\n  else if (pfXBGR == pf)\n    cinfo->in_color_space = JCS_EXT_XBGR;\n\n  if (cinfo->in_color_space != JCS_RGB) {\n    srcBuf = (uint8_t *)buf;\n    pixelsize = 4;\n  }\n#endif\n\n  if (stride == 0)\n    stride = w;\n\n  if (cinfo->in_color_space == JCS_RGB) {\n    srcBuf = new uint8_t[w * h * pixelsize];\n    srcBufIsTemp = true;\n    pf.rgbFromBuffer(srcBuf, (const uint8_t *)buf, w, stride, h);\n    stride = w;\n  }\n\n  cinfo->input_components = pixelsize;\n\n  jpeg_set_defaults(cinfo);\n\n  if (quality >= 1 && quality <= 100) {\n    jpeg_set_quality(cinfo, quality, TRUE);\n    if (quality >= 96)\n      cinfo->dct_method = JDCT_ISLOW;\n    else\n      cinfo->dct_method = JDCT_FASTEST;\n  }\n\n  switch (subsampling) {\n  case subsample16X:\n  case subsample8X:\n    // FIXME (fall through)\n  case subsample4X:\n    cinfo->comp_info[0].h_samp_factor = 2;\n    cinfo->comp_info[0].v_samp_factor = 2;\n    break;\n  case subsample2X:\n    cinfo->comp_info[0].h_samp_factor = 2;\n    cinfo->comp_info[0].v_samp_factor = 1;\n    break;\n  case subsampleGray:\n    jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);\n    // fall through\n  default:\n    cinfo->comp_info[0].h_samp_factor = 1;\n    cinfo->comp_info[0].v_samp_factor = 1;\n  }\n\n  rowPointer = new JSAMPROW[h];\n  for (int dy = 0; dy < h; dy++)\n    rowPointer[dy] = (JSAMPROW)(&srcBuf[dy * stride * pixelsize]);\n\n  jpeg_start_compress(cinfo, TRUE);\n  while (cinfo->next_scanline < cinfo->image_height)\n    jpeg_write_scanlines(cinfo, &rowPointer[cinfo->next_scanline],\n      cinfo->image_height - cinfo->next_scanline);\n\n  jpeg_finish_compress(cinfo);\n\n  if (srcBufIsTemp) delete[] srcBuf;\n  delete[] rowPointer;\n}\n\nvoid JpegCompressor::writeBytes(const uint8_t* /*data*/, int /*length*/)\n{\n  throw std::logic_error(\"writeBytes() is not valid with a JpegCompressor instance.  Use compress() instead.\");\n}\n"
  },
  {
    "path": "common/rfb/JpegCompressor.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// JpegCompressor compresses RGB input into a JPEG image and stores it in\n// an underlying MemOutStream\n//\n\n#ifndef __RFB_JPEGCOMPRESSOR_H__\n#define __RFB_JPEGCOMPRESSOR_H__\n\n#include <core/Rect.h>\n\n#include <rdr/MemOutStream.h>\n\nstruct jpeg_compress_struct;\n\nstruct JPEG_ERROR_MGR;\nstruct JPEG_DEST_MGR;\n\nnamespace rfb {\n\n  class PixelFormat;\n  struct Rect;\n\n  class JpegCompressor : public rdr::MemOutStream {\n\n  public:\n\n    JpegCompressor(int bufferLen = 128*1024);\n    virtual ~JpegCompressor();\n\n    void setQualityLevel(int level);\n    void setFineQualityLevel(int quality, int subsampling);\n\n    int getQualityLevel();\n\n    void compress(const uint8_t*, int, const core::Rect&,\n                  const PixelFormat&);\n\n    void writeBytes(const uint8_t*, int);\n\n  private:\n\n    int qualityLevel;\n    int fineQuality;\n    int fineSubsampling;\n\n    struct jpeg_compress_struct *cinfo;\n\n    struct JPEG_ERROR_MGR *err;\n    struct JPEG_DEST_MGR *dest;\n\n  };\n\n} // end of namespace rfb\n\n#endif\n"
  },
  {
    "path": "common/rfb/JpegDecompressor.cxx",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2004-2005 Cendio AB. All rights reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Rect.h>\n\n#include <rfb/JpegDecompressor.h>\n#include <rfb/Exception.h>\n#include <rfb/PixelFormat.h>\n\n#include <stdio.h>\nextern \"C\" {\n#include <jpeglib.h>\n}\n#include <jerror.h>\n#include <setjmp.h>\n\nusing namespace rfb;\n\n//\n// Special formats that libjpeg can have optimised code paths for\n//\n\nstatic const PixelFormat pfRGBX(32, 24, false, true, 255, 255, 255, 0, 8, 16);\nstatic const PixelFormat pfBGRX(32, 24, false, true, 255, 255, 255, 16, 8, 0);\nstatic const PixelFormat pfXRGB(32, 24, false, true, 255, 255, 255, 8, 16, 24);\nstatic const PixelFormat pfXBGR(32, 24, false, true, 255, 255, 255, 24, 16, 8);\n\n//\n// Error manager implementation for the JPEG library\n//\n\nstruct JPEG_ERROR_MGR {\n  struct jpeg_error_mgr pub;\n  jmp_buf jmpBuffer;\n  char lastError[JMSG_LENGTH_MAX];\n};\n\nstatic void\nJpegErrorExit(j_common_ptr dinfo)\n{\n  JPEG_ERROR_MGR *err = (JPEG_ERROR_MGR *)dinfo->err;\n\n  (*dinfo->err->output_message)(dinfo);\n  longjmp(err->jmpBuffer, 1);\n}\n\nstatic void\nJpegOutputMessage(j_common_ptr dinfo)\n{\n  JPEG_ERROR_MGR *err = (JPEG_ERROR_MGR *)dinfo->err;\n\n  (*dinfo->err->format_message)(dinfo, err->lastError);\n}\n\n\n//\n// Source manager implementation for the JPEG library.\n//\n\nstruct JPEG_SRC_MGR {\n  struct jpeg_source_mgr pub;\n  JpegDecompressor *instance;\n};\n\nstatic void\nJpegNoOp(j_decompress_ptr /*dinfo*/)\n{\n}\n\nstatic boolean\nJpegFillInputBuffer(j_decompress_ptr dinfo)\n{\n  ERREXIT(dinfo, JERR_BUFFER_SIZE);\n  return TRUE;\n}\n\nstatic void\nJpegSkipInputData(j_decompress_ptr dinfo, long num_bytes)\n{\n  JPEG_SRC_MGR *src = (JPEG_SRC_MGR *)dinfo->src;\n\n  if (num_bytes < 0 || (size_t)num_bytes > src->pub.bytes_in_buffer) {\n    ERREXIT(dinfo, JERR_BUFFER_SIZE);\n  } else {\n    src->pub.next_input_byte += (size_t) num_bytes;\n    src->pub.bytes_in_buffer -= (size_t) num_bytes;\n  }\n}\n\nJpegDecompressor::JpegDecompressor(void)\n{\n  dinfo = new jpeg_decompress_struct;\n\n  err = new struct JPEG_ERROR_MGR;\n  dinfo->err = jpeg_std_error(&err->pub);\n  snprintf(err->lastError, JMSG_LENGTH_MAX, \"No error\");\n  err->pub.error_exit = JpegErrorExit;\n  err->pub.output_message = JpegOutputMessage;\n\n  if(setjmp(err->jmpBuffer)) {\n    // this will execute if libjpeg has an error\n    throw std::runtime_error(err->lastError);\n  }\n\n  jpeg_create_decompress(dinfo);\n\n  src = new struct JPEG_SRC_MGR;\n  src->pub.init_source = JpegNoOp;\n  src->pub.fill_input_buffer = JpegFillInputBuffer;\n  src->pub.skip_input_data = JpegSkipInputData;\n  src->pub.resync_to_restart = jpeg_resync_to_restart;\n  src->pub.term_source = JpegNoOp;\n  src->instance = this;\n  dinfo->src = (struct jpeg_source_mgr *)src;\n}\n\nJpegDecompressor::~JpegDecompressor(void)\n{\n  if(setjmp(err->jmpBuffer)) {\n    // this will execute if libjpeg has an error\n    return;\n  }\n\n  jpeg_destroy_decompress(dinfo);\n\n  delete err;\n  delete src;\n\n  delete dinfo;\n}\n\nvoid JpegDecompressor::decompress(const uint8_t *jpegBuf,\n                                  int jpegBufLen, uint8_t *buf,\n                                  volatile int stride,\n                                  const core::Rect& r,\n                                  const PixelFormat& pf)\n{\n  int w = r.width();\n  int h = r.height();\n  int pixelsize;\n  int dstBufStride;\n  uint8_t * volatile dstBuf = nullptr;\n  volatile bool dstBufIsTemp = false;\n  JSAMPROW * volatile rowPointer = nullptr;\n\n  if(setjmp(err->jmpBuffer)) {\n    // this will execute if libjpeg has an error\n    jpeg_abort_decompress(dinfo);\n    if (dstBufIsTemp && dstBuf) delete[] dstBuf;\n    if (rowPointer) delete[] rowPointer;\n    throw std::runtime_error(err->lastError);\n  }\n\n  src->pub.next_input_byte = jpegBuf;\n  src->pub.bytes_in_buffer = jpegBufLen;\n\n  jpeg_read_header(dinfo, TRUE);\n  dinfo->out_color_space = JCS_RGB;\n  pixelsize = 3;\n  if (stride == 0)\n    stride = w;\n  dstBufStride = stride;\n\n#ifdef JCS_EXTENSIONS\n  // Try to have libjpeg output directly to our native format\n  // libjpeg can only handle some \"standard\" formats\n  if (pfRGBX == pf)\n    dinfo->out_color_space = JCS_EXT_RGBX;\n  else if (pfBGRX == pf)\n    dinfo->out_color_space = JCS_EXT_BGRX;\n  else if (pfXRGB == pf)\n    dinfo->out_color_space = JCS_EXT_XRGB;\n  else if (pfXBGR == pf)\n    dinfo->out_color_space = JCS_EXT_XBGR;\n\n  if (dinfo->out_color_space != JCS_RGB) {\n    dstBuf = (uint8_t *)buf;\n    pixelsize = 4;\n  }\n#endif\n\n  if (dinfo->out_color_space == JCS_RGB) {\n    dstBuf = new uint8_t[w * h * pixelsize];\n    dstBufIsTemp = true;\n    dstBufStride = w;\n  }\n\n  rowPointer = new JSAMPROW[h];\n  for (int dy = 0; dy < h; dy++)\n    rowPointer[dy] = (JSAMPROW)(&dstBuf[dy * dstBufStride * pixelsize]);\n\n  jpeg_start_decompress(dinfo);\n\n  if (dinfo->output_width != (unsigned)r.width()\n    || dinfo->output_height != (unsigned)r.height()\n    || dinfo->output_components != pixelsize) {\n    jpeg_abort_decompress(dinfo);\n    if (dstBufIsTemp && dstBuf) delete[] dstBuf;\n    if (rowPointer) delete[] rowPointer;\n    throw protocol_error(\"Tight Decoding: Wrong JPEG data received.\\n\");\n  }\n\n  while (dinfo->output_scanline < dinfo->output_height) {\n    jpeg_read_scanlines(dinfo, &rowPointer[dinfo->output_scanline],\n\t\t\tdinfo->output_height - dinfo->output_scanline);\n  }\n\n  if (dinfo->out_color_space == JCS_RGB)\n    pf.bufferFromRGB((uint8_t*)buf, dstBuf, w, stride, h);\n\n  jpeg_finish_decompress(dinfo);\n\n  if (dstBufIsTemp) delete [] dstBuf;\n  delete[] rowPointer;\n}\n"
  },
  {
    "path": "common/rfb/JpegDecompressor.h",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2004-2005 Cendio AB. All rights reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// JpegDecompressor decompresses a JPEG image into RGB output\n// an underlying MemOutStream\n//\n\n#ifndef __RFB_JPEGDECOMPRESSOR_H__\n#define __RFB_JPEGDECOMPRESSOR_H__\n\n#include <stdint.h>\n\nstruct jpeg_decompress_struct;\n\nstruct JPEG_ERROR_MGR;\nstruct JPEG_SRC_MGR;\n\nnamespace core { struct Rect; }\n\nnamespace rfb {\n\n  class PixelFormat;\n\n  class JpegDecompressor {\n\n  public:\n\n    JpegDecompressor(void);\n    virtual ~JpegDecompressor();\n\n    void decompress(const uint8_t*, int, uint8_t*, int,\n                    const core::Rect&, const PixelFormat&);\n\n  private:\n\n    struct jpeg_decompress_struct *dinfo;\n\n    struct JPEG_ERROR_MGR *err;\n    struct JPEG_SRC_MGR *src;\n\n  };\n\n} // end of namespace rfb\n\n#endif\n"
  },
  {
    "path": "common/rfb/KeyRemapper.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <string.h>\n\n#include <core/Configuration.h>\n#include <core/LogWriter.h>\n\n#include <rfb/KeyRemapper.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"KeyRemapper\");\n\nKeyRemapper KeyRemapper::defInstance;\n\nKeyRemapper::KeyRemapper()\n{\n}\n\nKeyRemapper::~KeyRemapper()\n{\n}\n\nvoid KeyRemapper::setMapping(const std::map<uint32_t,uint32_t>& m)\n{\n  mapping = m;\n}\n\nuint32_t KeyRemapper::remapKey(uint32_t key) const {\n  std::map<uint32_t,uint32_t>::const_iterator i = mapping.find(key);\n  if (i != mapping.end())\n    return i->second;\n  return key;\n}\n\n\nclass KeyMapParameter : public core::StringListParameter {\npublic:\n  KeyMapParameter()\n    : core::StringListParameter(\"RemapKeys\",\n                                \"Comma-separated list of incoming \"\n                                \"keysyms to remap.  Mappings are \"\n                                \"expressed as two hex values, prefixed \"\n                                \"by 0x, and separated by ->\",\n                                {}) {\n    KeyRemapper::defInstance.setMapping({});\n  }\n  bool setParam(const char* v) override {\n    std::map<uint32_t,uint32_t> mapping;\n\n    if (!core::StringListParameter::setParam(v))\n      return false;\n\n    for (const char* m : *this) {\n      int from, to;\n      char bidi;\n      if (sscanf(m, \"0x%x%c>0x%x\", &from,\n                &bidi, &to) == 3) {\n        if (bidi != '-' && bidi != '<')\n          vlog.error(\"Warning: Unknown operation %c>, assuming ->\", bidi);\n        mapping[from] = to;\n        if (bidi == '<')\n          mapping[to] = from;\n      } else {\n        vlog.error(\"Warning: Bad mapping %s\", m);\n      }\n    }\n\n    KeyRemapper::defInstance.setMapping(mapping);\n\n    return true;\n  }\n} defaultParam;\n\n\n"
  },
  {
    "path": "common/rfb/KeyRemapper.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_KEYREMAPPER_H__\n#define __RFB_KEYREMAPPER_H__\n\n#include <map>\n\n#include <stdint.h>\n\nnamespace rfb {\n\n  class KeyRemapper {\n  public:\n    KeyRemapper();\n    ~KeyRemapper();\n    void setMapping(const std::map<uint32_t,uint32_t>& m);\n    uint32_t remapKey(uint32_t key) const;\n    static KeyRemapper defInstance;\n  private:\n    std::map<uint32_t,uint32_t> mapping;\n  };\n\n};\n\n#endif // __RFB_KEYREMAPPER_H__\n"
  },
  {
    "path": "common/rfb/KeysymStr.c",
    "content": "\n/*\n\nCopyright 1990, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\nAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall not be\nused in advertising or otherwise to promote the sale, use or other dealings\nin this Software without prior written authorization from The Open Group.\n\n*/\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdlib.h>\n\n#include \"keysymdef.h\"\n#include \"KeysymStr.h\"\n\n/* Change the name of this to avoid conflict with libX11 */\n#define _XkeyTable _vncXkeyTable\n\n#define NEEDKTABLE\n#define NEEDVTABLE\n#include \"ks_tables.h\"\n\nstatic const char *_XKeysymToString(unsigned ks)\n{\n    if (!ks || (ks & ((unsigned long) ~0x1fffffff)) != 0)\n\treturn ((char *)NULL);\n    if (ks == XK_VoidSymbol)\n\tks = 0;\n    if (ks <= 0x1fffffff)\n    {\n\tunsigned char val1 = ks >> 24;\n\tunsigned char val2 = (ks >> 16) & 0xff;\n\tunsigned char val3 = (ks >> 8) & 0xff;\n\tunsigned char val4 = ks & 0xff;\n\tint i = ks % VTABLESIZE;\n\tint h = i + 1;\n\tint n = VMAXHASH;\n\tint idx;\n\twhile ((idx = hashKeysym[i]))\n\t{\n\t    const unsigned char *entry = &_XkeyTable[idx];\n\t    if ((entry[0] == val1) && (entry[1] == val2) &&\n                (entry[2] == val3) && (entry[3] == val4))\n\t\treturn ((char *)entry + 4);\n\t    if (!--n)\n\t\tbreak;\n\t    i += h;\n\t    if (i >= VTABLESIZE)\n\t\ti -= VTABLESIZE;\n\t}\n    }\n\n    if (ks >= 0x01000100 && ks <= 0x0110ffff) {\n        unsigned val = ks & 0xffffff;\n        char *s;\n        int i;\n        if (val & 0xff0000)\n            i = 10;\n        else\n            i = 6;\n        s = malloc(i);\n        if (s == NULL)\n            return s;\n        i--;\n        s[i--] = '\\0';\n        for (; i; i--){\n            unsigned char val1 = val & 0xf;\n            val >>= 4;\n            if (val1 < 10)\n                s[i] = '0'+ val1;\n            else\n                s[i] = 'A'+ val1 - 10;\n        }\n        s[i] = 'U';\n        return s;\n    }\n    return ((char *) NULL);\n}\n\nconst char* KeySymName(unsigned keysym)\n{\n    const char* name;\n\n    name = _XKeysymToString(keysym);\n    if (name == NULL)\n      return \"[unknown keysym]\";\n\n    return name;\n}\n\n"
  },
  {
    "path": "common/rfb/KeysymStr.h",
    "content": "/* Copyright 2021 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_KEYSYMSTR_H__\n#define __RFB_KEYSYMSTR_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nconst char* KeySymName(unsigned keysym);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "common/rfb/Palette.h",
    "content": "/* Copyright (C) 2000-2005 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_PALETTE_H__\n#define __RFB_PALETTE_H__\n\n#include <assert.h>\n#include <string.h>\n#include <stdint.h>\n\nnamespace rfb {\n  class Palette {\n  public:\n    Palette() { clear(); }\n    ~Palette() {}\n\n    int size() const { return numColours; }\n\n    void clear() { numColours = 0; memset(hash, 0, sizeof(hash)); }\n\n    inline bool insert(uint32_t colour, int numPixels);\n    inline unsigned char lookup(uint32_t colour) const;\n    inline uint32_t getColour(unsigned char index) const;\n    inline int getCount(unsigned char index) const;\n\n  protected:\n    inline unsigned char genHash(uint32_t colour) const;\n\n  protected:\n    int numColours;\n\n    struct PaletteListNode {\n      PaletteListNode *next;\n      unsigned char idx;\n      uint32_t colour;\n    };\n\n    struct PaletteEntry {\n      PaletteListNode *listNode;\n      int numPixels;\n    };\n\n    // This is the raw list of colours, allocated from 0 and up\n    PaletteListNode list[256];\n    // Hash table for quick lookup into the list above\n    PaletteListNode *hash[256];\n    // Occurances of each colour, where the 0:th entry is the most common.\n    // Indices also refer to this array.\n    PaletteEntry entry[256];\n  };\n}\n\ninline bool rfb::Palette::insert(uint32_t colour, int numPixels)\n{\n  PaletteListNode* pnode;\n  PaletteListNode* prev_pnode;\n  unsigned char hash_key, idx;\n\n  hash_key = genHash(colour);\n\n  pnode = hash[hash_key];\n  prev_pnode = nullptr;\n\n  // Do we already have an entry for this colour?\n  while (pnode != nullptr) {\n    if (pnode->colour == colour) {\n      // Yup\n\n      idx = pnode->idx;\n      numPixels = entry[idx].numPixels + numPixels;\n\n      // The extra pixels might mean we have to adjust the sort list\n      while (idx > 0) {\n        if (entry[idx-1].numPixels >= numPixels)\n          break;\n        entry[idx] = entry[idx-1];\n        entry[idx].listNode->idx = idx;\n        idx--;\n      }\n\n      if (idx != pnode->idx) {\n        entry[idx].listNode = pnode;\n        pnode->idx = idx;\n      }\n\n      entry[idx].numPixels = numPixels;\n\n      return true;\n    }\n\n    prev_pnode = pnode;\n    pnode = pnode->next;\n  }\n\n  // Check if palette is full.\n  if (numColours == 256)\n    return false;\n\n  // Create a new colour entry\n  pnode = &list[numColours];\n  pnode->next = nullptr;\n  pnode->idx = 0;\n  pnode->colour = colour;\n\n  // Add it to the hash table\n  if (prev_pnode != nullptr)\n    prev_pnode->next = pnode;\n  else\n    hash[hash_key] = pnode;\n\n  // Move palette entries with lesser pixel counts.\n  idx = numColours;\n  while (idx > 0) {\n    if (entry[idx-1].numPixels >= numPixels)\n      break;\n    entry[idx] = entry[idx-1];\n    entry[idx].listNode->idx = idx;\n    idx--;\n  }\n\n  // And add it into the freed slot.\n  pnode->idx = idx;\n  entry[idx].listNode = pnode;\n  entry[idx].numPixels = numPixels;\n\n  numColours++;\n\n  return true;\n}\n\ninline unsigned char rfb::Palette::lookup(uint32_t colour) const\n{\n  unsigned char hash_key;\n  PaletteListNode* pnode;\n\n  hash_key = genHash(colour);\n  pnode = hash[hash_key];\n\n  while (pnode != nullptr) {\n    if (pnode->colour == colour)\n      return pnode->idx;\n    pnode = pnode->next;\n  }\n\n  // We are being fed a bad colour\n  assert(false);\n\n  return 0;\n}\n\ninline uint32_t rfb::Palette::getColour(unsigned char index) const\n{\n  return entry[index].listNode->colour;\n}\n\ninline int rfb::Palette::getCount(unsigned char index) const\n{\n  return entry[index].numPixels;\n}\n\ninline unsigned char rfb::Palette::genHash(uint32_t colour) const\n{\n  unsigned char hash_key;\n\n  // djb2 hash function\n  hash_key = 5; // 5381 & 0xff\n  for (int i = 0; i < 32; i += 8)\n    hash_key = ((hash_key << 5) + hash_key) ^ (colour >> i);\n\n  return hash_key;\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/PixelBuffer.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- PixelBuffer.cxx\n//\n// The PixelBuffer class encapsulates the PixelFormat and dimensions\n// of a block of pixel data.\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string.h>\n\n#include <stdexcept>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb/PixelBuffer.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"PixelBuffer\");\n\n// We do a lot of byte offset calculations that assume the result fits\n// inside a signed 32 bit integer. Limit the maximum size of pixel\n// buffers so that these calculations never overflow.\n\nconst int maxPixelBufferWidth = 16384;\nconst int maxPixelBufferHeight = 16384;\nconst int maxPixelBufferStride = 16384;\n\n\n// -=- Generic pixel buffer class\n\nPixelBuffer::PixelBuffer(const PixelFormat& pf, int w, int h)\n  : format(pf), width_(0), height_(0)\n{\n  setSize(w, h);\n}\n\nPixelBuffer::PixelBuffer() : width_(0), height_(0)\n{\n}\n\nPixelBuffer::~PixelBuffer() {}\n\n\nvoid\nPixelBuffer::getImage(void* imageBuf, const core::Rect& r,\n                      int outStride) const\n{\n  int inStride;\n  const uint8_t* data;\n  int bytesPerPixel, inBytesPerRow, outBytesPerRow, bytesPerMemCpy;\n  uint8_t* imageBufPos;\n  const uint8_t* end;\n\n  if (!r.enclosed_by(getRect()))\n    throw std::out_of_range(core::format(\n      \"Source rect %dx%d at %d,%d exceeds framebuffer %dx%d\",\n      r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));\n\n  data = getBuffer(r, &inStride);\n\n  bytesPerPixel = format.bpp/8;\n  inBytesPerRow = inStride * bytesPerPixel;\n\n  if (!outStride)\n    outStride = r.width();\n  outBytesPerRow = outStride * bytesPerPixel;\n  bytesPerMemCpy = r.width() * bytesPerPixel;\n\n  imageBufPos = (uint8_t*)imageBuf;\n  end = data + (inBytesPerRow * r.height());\n\n  while (data < end) {\n    memcpy(imageBufPos, data, bytesPerMemCpy);\n    imageBufPos += outBytesPerRow;\n    data += inBytesPerRow;\n  }\n}\n\nvoid PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf,\n                           const core::Rect& r, int stride) const\n{\n  const uint8_t* srcBuffer;\n  int srcStride;\n\n  if (format == pf) {\n    getImage(imageBuf, r, stride);\n    return;\n  }\n\n  if (!r.enclosed_by(getRect()))\n    throw std::out_of_range(core::format(\n      \"Source rect %dx%d at %d,%d exceeds framebuffer %dx%d\",\n      r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));\n\n  if (stride == 0)\n    stride = r.width();\n\n  srcBuffer = getBuffer(r, &srcStride);\n\n  pf.bufferFromBuffer((uint8_t*)imageBuf, format, srcBuffer,\n                      r.width(), r.height(), stride, srcStride);\n}\n\nvoid PixelBuffer::setSize(int width, int height)\n{\n  if ((width < 0) || (width > maxPixelBufferWidth))\n    throw std::out_of_range(core::format(\n      \"Invalid PixelBuffer width of %d pixels requested\", width));\n  if ((height < 0) || (height > maxPixelBufferHeight))\n    throw std::out_of_range(core::format(\n      \"Invalid PixelBuffer height of %d pixels requested\", height));\n\n  width_ = width;\n  height_ = height;\n}\n\n// -=- Modifiable generic pixel buffer class\n\nModifiablePixelBuffer::ModifiablePixelBuffer(const PixelFormat& pf,\n                                             int w, int h)\n  : PixelBuffer(pf, w, h)\n{\n}\n\nModifiablePixelBuffer::ModifiablePixelBuffer()\n{\n}\n\nModifiablePixelBuffer::~ModifiablePixelBuffer()\n{\n}\n\nvoid ModifiablePixelBuffer::fillRect(const core::Rect& r,\n                                     const void* pix)\n{\n  int stride;\n  uint8_t *buf;\n  int w, h, b;\n\n  if (!r.enclosed_by(getRect()))\n    throw std::out_of_range(core::format(\n      \"Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d\",\n      r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));\n\n  w = r.width();\n  h = r.height();\n  b = format.bpp/8;\n\n  if (h == 0)\n    return;\n\n  buf = getBufferRW(r, &stride);\n\n  if (b == 1) {\n    while (h--) {\n      memset(buf, *(const uint8_t*)pix, w);\n      buf += stride * b;\n    }\n  } else {\n    uint8_t *start;\n    int w1;\n\n    start = buf;\n\n    w1 = w;\n    while (w1--) {\n      memcpy(buf, pix, b);\n      buf += b;\n    }\n    buf += (stride - w) * b;\n    h--;\n\n    while (h--) {\n      memcpy(buf, start, w * b);\n      buf += stride * b;\n    }\n  }\n\n  commitBufferRW(r);\n}\n\nvoid ModifiablePixelBuffer::imageRect(const core::Rect& r,\n                                      const void* pixels, int srcStride)\n{\n  uint8_t* dest;\n  int destStride;\n  int bytesPerPixel, bytesPerDestRow, bytesPerSrcRow, bytesPerFill;\n  const uint8_t* src;\n  uint8_t* end;\n\n  if (!r.enclosed_by(getRect()))\n    throw std::out_of_range(core::format(\n      \"Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d\",\n      r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));\n\n  bytesPerPixel = getPF().bpp/8;\n\n  dest = getBufferRW(r, &destStride);\n\n  bytesPerDestRow = bytesPerPixel * destStride;\n\n  if (!srcStride)\n    srcStride = r.width();\n  bytesPerSrcRow = bytesPerPixel * srcStride;\n  bytesPerFill = bytesPerPixel * r.width();\n\n  src = (const uint8_t*)pixels;\n  end = dest + (bytesPerDestRow * r.height());\n\n  while (dest < end) {\n    memcpy(dest, src, bytesPerFill);\n    dest += bytesPerDestRow;\n    src += bytesPerSrcRow;\n  }\n\n  commitBufferRW(r);\n}\n\nvoid ModifiablePixelBuffer::copyRect(const core::Rect& rect,\n                                     const core::Point& move_by_delta)\n{\n  int srcStride, dstStride;\n  int bytesPerPixel;\n  const uint8_t* srcData;\n  uint8_t* dstData;\n\n  core::Rect drect, srect;\n\n  drect = rect;\n  if (!drect.enclosed_by(getRect()))\n    throw std::out_of_range(core::format(\n      \"Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d\",\n      drect.width(), drect.height(), drect.tl.x, drect.tl.y,\n      width(), height()));\n\n  srect = drect.translate(move_by_delta.negate());\n  if (!srect.enclosed_by(getRect()))\n    throw std::out_of_range(core::format(\n      \"Source rect %dx%d at %d,%d exceeds framebuffer %dx%d\",\n      srect.width(), srect.height(), srect.tl.x, srect.tl.y,\n      width(), height()));\n\n  bytesPerPixel = format.bpp/8;\n\n  srcData = getBuffer(srect, &srcStride);\n  dstData = getBufferRW(drect, &dstStride);\n\n  if (move_by_delta.y == 0) {\n    // Possible overlap. Be careful and use memmove().\n    int h = drect.height();\n    while (h--) {\n      memmove(dstData, srcData, drect.width() * bytesPerPixel);\n      dstData += dstStride * bytesPerPixel;\n      srcData += srcStride * bytesPerPixel;\n    }\n  } else if (move_by_delta.y < 0) {\n    // The data shifted upwards. Copy from top to bottom.\n    int h = drect.height();\n    while (h--) {\n      memcpy(dstData, srcData, drect.width() * bytesPerPixel);\n      dstData += dstStride * bytesPerPixel;\n      srcData += srcStride * bytesPerPixel;\n    }\n  } else {\n    // The data shifted downwards. Copy from bottom to top.\n    int h = drect.height();\n    dstData += (h-1) * dstStride * bytesPerPixel;\n    srcData += (h-1) * srcStride * bytesPerPixel;\n    while (h--) {\n      memcpy(dstData, srcData, drect.width() * bytesPerPixel);\n      dstData -= dstStride * bytesPerPixel;\n      srcData -= srcStride * bytesPerPixel;\n    }\n  }\n\n  commitBufferRW(drect);\n}\n\nvoid ModifiablePixelBuffer::fillRect(const PixelFormat& pf,\n                                     const core::Rect& dest,\n                                     const void* pix)\n{\n  uint8_t buf[4];\n  format.bufferFromBuffer(buf, pf, (const uint8_t*)pix, 1);\n  fillRect(dest, buf);\n}\n\nvoid ModifiablePixelBuffer::imageRect(const PixelFormat& pf,\n                                      const core::Rect& dest,\n                                      const void* pixels, int stride)\n{\n  uint8_t* dstBuffer;\n  int dstStride;\n\n  if (!dest.enclosed_by(getRect()))\n    throw std::out_of_range(core::format(\n      \"Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d\",\n      dest.width(), dest.height(), dest.tl.x, dest.tl.y,\n      width(), height()));\n\n  if (stride == 0)\n    stride = dest.width();\n\n  dstBuffer = getBufferRW(dest, &dstStride);\n  format.bufferFromBuffer(dstBuffer, pf, (const uint8_t*)pixels,\n                          dest.width(), dest.height(),\n                          dstStride, stride);\n  commitBufferRW(dest);\n}\n\n// -=- Simple pixel buffer with a continuous block of memory\n\nFullFramePixelBuffer::FullFramePixelBuffer(const PixelFormat& pf, int w, int h,\n                                           uint8_t* data_, int stride_)\n  : ModifiablePixelBuffer(pf, w, h), data(data_), stride(stride_)\n{\n}\n\nFullFramePixelBuffer::FullFramePixelBuffer() : data(nullptr) {}\n\nFullFramePixelBuffer::~FullFramePixelBuffer() {}\n\nuint8_t* FullFramePixelBuffer::getBufferRW(const core::Rect& r,\n                                           int* stride_)\n{\n  if (!r.enclosed_by(getRect()))\n    throw std::out_of_range(core::format(\n      \"Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d\",\n      r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));\n\n  *stride_ = stride;\n  return &data[(r.tl.x + (r.tl.y * stride)) * (format.bpp/8)];\n}\n\nvoid FullFramePixelBuffer::commitBufferRW(const core::Rect& /*r*/)\n{\n}\n\nconst uint8_t* FullFramePixelBuffer::getBuffer(const core::Rect& r,\n                                               int* stride_) const\n{\n  if (!r.enclosed_by(getRect()))\n    throw std::out_of_range(core::format(\n      \"Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d\",\n      r.width(), r.height(), r.tl.x, r.tl.y, width(), height()));\n\n  *stride_ = stride;\n  return &data[(r.tl.x + (r.tl.y * stride)) * (format.bpp/8)];\n}\n\nvoid FullFramePixelBuffer::setBuffer(int width, int height,\n                                     uint8_t* data_, int stride_)\n{\n  if ((width < 0) || (width > maxPixelBufferWidth))\n    throw std::out_of_range(core::format(\n      \"Invalid PixelBuffer width of %d pixels requested\", width));\n  if ((height < 0) || (height > maxPixelBufferHeight))\n    throw std::out_of_range(core::format(\n      \"Invalid PixelBuffer height of %d pixels requested\", height));\n  if ((stride_ < 0) || (stride_ > maxPixelBufferStride) || (stride_ < width))\n    throw std::invalid_argument(core::format(\n      \"Invalid PixelBuffer stride of %d pixels requested\", stride_));\n  if ((width != 0) && (height != 0) && (data_ == nullptr))\n    throw std::logic_error(core::format(\n      \"PixelBuffer requested without a valid memory area\"));\n\n  ModifiablePixelBuffer::setSize(width, height);\n  stride = stride_;\n  data = data_;\n}\n\nvoid FullFramePixelBuffer::setSize(int /*w*/, int /*h*/)\n{\n  // setBuffer() should be used\n  throw std::logic_error(\"Invalid call to FullFramePixelBuffer::setSize()\");\n}\n\n// -=- Managed pixel buffer class\n// Automatically allocates enough space for the specified format & area\n\nManagedPixelBuffer::ManagedPixelBuffer()\n  : data_(nullptr), datasize(0)\n{\n}\n\nManagedPixelBuffer::ManagedPixelBuffer(const PixelFormat& pf, int w, int h)\n  : FullFramePixelBuffer(pf, 0, 0, nullptr, 0), data_(nullptr), datasize(0)\n{\n  setSize(w, h);\n}\n\nManagedPixelBuffer::~ManagedPixelBuffer()\n{\n  if (data_)\n    delete [] data_;\n}\n\nvoid ManagedPixelBuffer::setPF(const PixelFormat &pf)\n{\n  format = pf;\n  setSize(width(), height());\n}\n\nvoid ManagedPixelBuffer::setSize(int w, int h)\n{\n  unsigned long new_datasize = w * h * (format.bpp/8);\n\n  new_datasize = w * h * (format.bpp/8);\n  if (datasize < new_datasize) {\n    if (data_) {\n      delete [] data_;\n      data_ = nullptr;\n      datasize = 0;\n    }\n    if (new_datasize) {\n      data_ = new uint8_t[new_datasize];\n      datasize = new_datasize;\n    }\n  }\n\n  setBuffer(w, h, data_, w);\n}\n"
  },
  {
    "path": "common/rfb/PixelBuffer.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- PixelBuffer.h\n//\n// The PixelBuffer class encapsulates the PixelFormat and dimensions\n// of a block of pixel data.\n\n#ifndef __RFB_PIXEL_BUFFER_H__\n#define __RFB_PIXEL_BUFFER_H__\n\n#include <core/Rect.h>\n\n#include <rfb/PixelFormat.h>\n\nnamespace core { class Region; }\n\nnamespace rfb {\n\n  class PixelBuffer {\n  public:\n    PixelBuffer(const PixelFormat& pf, int width, int height);\n    virtual ~PixelBuffer();\n\n    ///////////////////////////////////////////////\n    // Format / Layout\n    //\n\n  public:\n    // Get pixel format\n    const PixelFormat &getPF() const { return format; }\n\n    // Get width, height and number of pixels\n    int width()  const { return width_; }\n    int height() const { return height_; }\n    int area() const { return width_ * height_; }\n\n    // Get rectangle encompassing this buffer\n    //   Top-left of rectangle is either at (0,0), or the specified point.\n    core::Rect getRect() const { return {0, 0, width_, height_}; }\n    core::Rect getRect(const core::Point& pos) const {\n      return {pos, pos.translate({width_, height_})};\n    }\n\n    ///////////////////////////////////////////////\n    // Access to pixel data\n    //\n\n    // Get a pointer into the buffer\n    //   The pointer is to the top-left pixel of the specified Rect.\n    //   The buffer stride (in pixels) is returned.\n    virtual const uint8_t* getBuffer(const core::Rect& r,\n                                     int* stride) const = 0;\n\n    // Get pixel data for a given part of the buffer\n    //   Data is copied into the supplied buffer, with the specified\n    //   stride. Try to avoid using this though as getBuffer() will in\n    //   most cases avoid the extra memory copy.\n    void getImage(void* imageBuf, const core::Rect& r,\n                  int stride=0) const;\n    // Get pixel data in a given format\n    //   Works just the same as getImage(), but guaranteed to be in a\n    //   specific format.\n    void getImage(const PixelFormat& pf, void* imageBuf,\n                  const core::Rect& r, int stride=0) const;\n\n    ///////////////////////////////////////////////\n    // Framebuffer update methods\n    //\n\n    // Ensure that the specified rectangle of buffer is up to date.\n    //   Overridden by derived classes implementing framebuffer access\n    //   to copy the required display data into place.\n    virtual void grabRegion(const core::Region& /*region*/) {}\n\n  protected:\n    PixelBuffer();\n    virtual void setSize(int width, int height);\n\n  protected:\n    PixelFormat format;\n\n  private:\n    int width_, height_;\n  };\n\n  // ModifiablePixelBuffer\n  class ModifiablePixelBuffer : public PixelBuffer {\n  public:\n    ModifiablePixelBuffer(const PixelFormat& pf, int width, int height);\n    virtual ~ModifiablePixelBuffer();\n\n    ///////////////////////////////////////////////\n    // Access to pixel data\n    //\n\n    // Get a writeable pointer into the buffer\n    //   Like getBuffer(), the pointer is to the top-left pixel of the\n    //   specified Rect and the stride in pixels is returned.\n    virtual uint8_t* getBufferRW(const core::Rect& r, int* stride) = 0;\n    // Commit the modified contents\n    //   Ensures that the changes to the specified Rect is properly\n    //   stored away and any temporary buffers are freed. The Rect given\n    //   here needs to match the Rect given to the earlier call to\n    //   getBufferRW().\n    virtual void commitBufferRW(const core::Rect& r) = 0;\n\n    ///////////////////////////////////////////////\n    // Basic rendering operations\n    // These operations DO NOT clip to the pixelbuffer area, or trap overruns.\n\n    // Fill a rectangle\n    void fillRect(const core::Rect& dest, const void* pix);\n\n    // Copy pixel data to the buffer\n    void imageRect(const core::Rect& dest, const void* pixels,\n                   int stride=0);\n\n    // Copy pixel data from one PixelBuffer location to another\n    void copyRect(const core::Rect& dest,\n                  const core::Point& move_by_delta);\n\n    // Render in a specific format\n    //   Does the exact same thing as the above methods, but the given\n    //   pixel values are defined by the given PixelFormat.\n    void fillRect(const PixelFormat& pf, const core::Rect& dest,\n                  const void* pix);\n    void imageRect(const PixelFormat& pf, const core::Rect& dest,\n                   const void* pixels, int stride=0);\n\n  protected:\n    ModifiablePixelBuffer();\n  };\n\n  // FullFramePixelBuffer\n\n  class FullFramePixelBuffer : public ModifiablePixelBuffer {\n  public:\n    FullFramePixelBuffer(const PixelFormat& pf, int width, int height,\n                         uint8_t* data_, int stride);\n    virtual ~FullFramePixelBuffer();\n\n  public:\n    const uint8_t* getBuffer(const core::Rect& r,\n                             int* stride) const override;\n    uint8_t* getBufferRW(const core::Rect& r, int* stride) override;\n    void commitBufferRW(const core::Rect& r) override;\n\n  protected:\n    FullFramePixelBuffer();\n    virtual void setBuffer(int width, int height, uint8_t* data, int stride);\n\n  private:\n    void setSize(int w, int h) override;\n\n  private:\n    uint8_t* data;\n    int stride;\n  };\n\n  // -=- Managed pixel buffer class\n  // Automatically allocates enough space for the specified format & area\n\n  class ManagedPixelBuffer : public FullFramePixelBuffer {\n  public:\n    ManagedPixelBuffer();\n    ManagedPixelBuffer(const PixelFormat& pf, int width, int height);\n    virtual ~ManagedPixelBuffer();\n\n    // Manage the pixel buffer layout\n    virtual void setPF(const PixelFormat &pf);\n    void setSize(int w, int h) override;\n\n  private:\n    uint8_t* data_; // Mirrors FullFramePixelBuffer::data\n    unsigned long datasize;\n  };\n\n};\n\n#endif // __RFB_PIXEL_BUFFER_H__\n"
  },
  {
    "path": "common/rfb/PixelFormat.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2009-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdint.h>\n#include <string.h>\n#include <rdr/InStream.h>\n#include <rdr/OutStream.h>\n#include <rfb/Exception.h>\n#include <rfb/PixelFormat.h>\n\n#ifdef _WIN32\n#define strcasecmp _stricmp\n#endif\n\nusing namespace rfb;\n\nuint8_t PixelFormat::upconvTable[256*8];\nuint8_t PixelFormat::downconvTable[256*8];\n\nclass PixelFormat::Init {\npublic:\n  Init();\n};\n\nPixelFormat::Init PixelFormat::_init;\n\n\nPixelFormat::Init::Init()\n{\n  int bits;\n\n  // Shifting bits is almost perfect, but not quite. And\n  // a lookup table is still quicker when there is a large\n  // difference between the source and destination depth.\n\n  for (bits = 1;bits <= 8;bits++) {\n    int i, maxVal;\n    uint8_t *subUpTable;\n    uint8_t *subDownTable;\n\n    maxVal = (1 << bits) - 1;\n    subUpTable = &upconvTable[(bits-1)*256];\n    subDownTable = &downconvTable[(bits-1)*256];\n\n    for (i = 0;i <= maxVal;i++)\n      subUpTable[i] = i * 255 / maxVal;\n\n    // Duplicate the up table so that we don't have to care about\n    // the upper bits when doing a lookup\n    for (;i < 256;i += maxVal+1)\n      memcpy(&subUpTable[i], &subUpTable[0], maxVal+1);\n\n    for (i = 0;i <= 255;i++)\n      subDownTable[i] = (i * maxVal + 128) / 255;\n  }\n}\n\n\nPixelFormat::PixelFormat(int b, int d, bool e, bool t,\n                         int rm, int gm, int bm, int rs, int gs, int bs)\n  : bpp(b), depth(d), trueColour(t), bigEndian(e),\n    redMax(rm), greenMax(gm), blueMax(bm),\n    redShift(rs), greenShift(gs), blueShift(bs)\n{\n  if (!isSane())\n    throw std::invalid_argument(\"Invalid pixel format\");\n\n  updateState();\n}\n\nPixelFormat::PixelFormat()\n  : bpp(8), depth(8), trueColour(true), bigEndian(false),\n    redMax(7), greenMax(7), blueMax(3),\n    redShift(0), greenShift(3), blueShift(6)\n{\n  updateState();\n}\n\nbool PixelFormat::operator==(const PixelFormat& other) const\n{\n  if (bpp != other.bpp || depth != other.depth)\n    return false;\n\n  if (redMax != other.redMax)\n    return false;\n  if (greenMax != other.greenMax)\n    return false;\n  if (blueMax != other.blueMax)\n    return false;\n\n  // Endianness requires more care to determine compatibility\n  if (bigEndian == other.bigEndian || bpp == 8) {\n    if (redShift != other.redShift)\n      return false;\n    if (greenShift != other.greenShift)\n      return false;\n    if (blueShift != other.blueShift)\n      return false;\n  } else {\n    // Has to be the same byte for each channel\n    if (redShift/8 != (3 - other.redShift/8))\n      return false;\n    if (greenShift/8 != (3 - other.greenShift/8))\n      return false;\n    if (blueShift/8 != (3 - other.blueShift/8))\n      return false;\n\n    // And the same bit offset within the byte\n    if (redShift%8 != other.redShift%8)\n      return false;\n    if (greenShift%8 != other.greenShift%8)\n      return false;\n    if (blueShift%8 != other.blueShift%8)\n      return false;\n\n    // And not cross a byte boundary\n    if (redShift/8 != (redShift + redBits - 1)/8)\n      return false;\n    if (greenShift/8 != (greenShift + greenBits - 1)/8)\n      return false;\n    if (blueShift/8 != (blueShift + blueBits - 1)/8)\n      return false;\n  }\n\n  return true;\n}\n\nbool PixelFormat::operator!=(const PixelFormat& other) const\n{\n  return !(*this == other);\n}\n\nvoid PixelFormat::read(rdr::InStream* is)\n{\n  bpp = is->readU8();\n  depth = is->readU8();\n  bigEndian = is->readU8();\n  trueColour = is->readU8();\n  redMax = is->readU16();\n  greenMax = is->readU16();\n  blueMax = is->readU16();\n  redShift = is->readU8();\n  greenShift = is->readU8();\n  blueShift = is->readU8();\n  is->skip(3);\n\n  // We have no real support for colour maps. If the client\n  // wants one, then we force a 8-bit true colour format and\n  // pretend it's a colour map.\n  if (!trueColour) {\n    redMax = 7;\n    greenMax = 7;\n    blueMax = 3;\n    redShift = 0;\n    greenShift = 3;\n    blueShift = 6;\n  }\n\n  if (!isSane())\n    throw protocol_error(\"Invalid pixel format\");\n\n  updateState();\n}\n\nvoid PixelFormat::write(rdr::OutStream* os) const\n{\n  os->writeU8(bpp);\n  os->writeU8(depth);\n  os->writeU8(bigEndian);\n  os->writeU8(trueColour);\n  os->writeU16(redMax);\n  os->writeU16(greenMax);\n  os->writeU16(blueMax);\n  os->writeU8(redShift);\n  os->writeU8(greenShift);\n  os->writeU8(blueShift);\n  os->pad(3);\n}\n\n\nbool PixelFormat::is888(void) const\n{\n  if (!trueColour)\n    return false;\n  if (bpp != 32)\n    return false;\n  if (depth != 24)\n    return false;\n  if (redMax != 255)\n    return false;\n  if (greenMax != 255)\n    return false;\n  if (blueMax != 255)\n    return false;\n  if ((redShift & 0x7) != 0)\n    return false;\n  if ((greenShift & 0x7) != 0)\n    return false;\n  if ((blueShift & 0x7) != 0)\n    return false;\n\n  return true;\n}\n\n\nbool PixelFormat::isBigEndian(void) const\n{\n  return bigEndian;\n}\n\n\nbool PixelFormat::isLittleEndian(void) const\n{\n  return ! bigEndian;\n}\n\n\nvoid PixelFormat::bufferFromRGB(uint8_t *dst, const uint8_t* src, int pixels) const\n{\n  bufferFromRGB(dst, src, pixels, pixels, 1);\n}\n\nvoid PixelFormat::bufferFromRGB(uint8_t *dst, const uint8_t* src,\n                                int w, int stride, int h) const\n{\n  if (is888()) {\n    // Optimised common case\n    uint8_t *r, *g, *b, *x;\n\n    if (bigEndian) {\n      r = dst + (24 - redShift)/8;\n      g = dst + (24 - greenShift)/8;\n      b = dst + (24 - blueShift)/8;\n      x = dst + (24 - (48 - redShift - greenShift - blueShift))/8;\n    } else {\n      r = dst + redShift/8;\n      g = dst + greenShift/8;\n      b = dst + blueShift/8;\n      x = dst + (48 - redShift - greenShift - blueShift)/8;\n    }\n\n    int dstPad = (stride - w) * 4;\n    while (h--) {\n      int w_ = w;\n      while (w_--) {\n        *r = *(src++);\n        *g = *(src++);\n        *b = *(src++);\n        *x = 0;\n        r += 4;\n        g += 4;\n        b += 4;\n        x += 4;\n      }\n      r += dstPad;\n      g += dstPad;\n      b += dstPad;\n      x += dstPad;\n    }\n  } else {\n    // Generic code\n    int dstPad = (stride - w) * bpp/8;\n    while (h--) {\n      int w_ = w;\n      while (w_--) {\n        Pixel p;\n        uint8_t r, g, b;\n\n        r = *(src++);\n        g = *(src++);\n        b = *(src++);\n\n        p = pixelFromRGB(r, g, b);\n\n        bufferFromPixel(dst, p);\n        dst += bpp/8;\n      }\n      dst += dstPad;\n    }\n  }\n}\n\n\nvoid PixelFormat::rgbFromBuffer(uint8_t* dst, const uint8_t* src, int pixels) const\n{\n  rgbFromBuffer(dst, src, pixels, pixels, 1);\n}\n\n\nvoid PixelFormat::rgbFromBuffer(uint8_t* dst, const uint8_t* src,\n                                int w, int stride, int h) const\n{\n  if (is888()) {\n    // Optimised common case\n    const uint8_t *r, *g, *b;\n\n    if (bigEndian) {\n      r = src + (24 - redShift)/8;\n      g = src + (24 - greenShift)/8;\n      b = src + (24 - blueShift)/8;\n    } else {\n      r = src + redShift/8;\n      g = src + greenShift/8;\n      b = src + blueShift/8;\n    }\n\n    int srcPad = (stride - w) * 4;\n    while (h--) {\n      int w_ = w;\n      while (w_--) {\n        *(dst++) = *r;\n        *(dst++) = *g;\n        *(dst++) = *b;\n        r += 4;\n        g += 4;\n        b += 4;\n      }\n      r += srcPad;\n      g += srcPad;\n      b += srcPad;\n    }\n  } else {\n    // Generic code\n    int srcPad = (stride - w) * bpp/8;\n    while (h--) {\n      int w_ = w;\n      while (w_--) {\n        Pixel p;\n        uint8_t r, g, b;\n\n        p = pixelFromBuffer(src);\n\n        rgbFromPixel(p, &r, &g, &b);\n\n        *(dst++) = r;\n        *(dst++) = g;\n        *(dst++) = b;\n        src += bpp/8;\n      }\n      src += srcPad;\n    }\n  }\n}\n\n\nPixel PixelFormat::pixelFromPixel(const PixelFormat &srcPF, Pixel src) const\n{\n  uint16_t r, g, b;\n  srcPF.rgbFromPixel(src, &r, &g, &b);\n  return pixelFromRGB(r, g, b);\n}\n\n\nvoid PixelFormat::bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF,\n                                   const uint8_t* src, int pixels) const\n{\n  bufferFromBuffer(dst, srcPF, src, pixels, 1, pixels, pixels);\n}\n\n#define IS_ALIGNED(v, a) (((intptr_t)v & (a-1)) == 0)\n\nvoid PixelFormat::bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF,\n                                   const uint8_t* src, int w, int h,\n                                   int dstStride, int srcStride) const\n{\n  if (*this == srcPF) {\n    // Trivial case\n    while (h--) {\n      memcpy(dst, src, w * bpp/8);\n      dst += dstStride * bpp/8;\n      src += srcStride * srcPF.bpp/8;\n    }\n  } else if (is888() && srcPF.is888()) {\n    // Optimised common case A: byte shuffling (e.g. endian conversion)\n    uint8_t *d[4], *s[4];\n    int dstPad, srcPad;\n\n    if (bigEndian) {\n      s[0] = dst + (24 - redShift)/8;\n      s[1] = dst + (24 - greenShift)/8;\n      s[2] = dst + (24 - blueShift)/8;\n      s[3] = dst + (24 - (48 - redShift - greenShift - blueShift))/8;\n    } else {\n      s[0] = dst + redShift/8;\n      s[1] = dst + greenShift/8;\n      s[2] = dst + blueShift/8;\n      s[3] = dst + (48 - redShift - greenShift - blueShift)/8;\n    }\n\n    if (srcPF.bigEndian) {\n      d[(24 - srcPF.redShift)/8] = s[0];\n      d[(24 - srcPF.greenShift)/8] = s[1];\n      d[(24 - srcPF.blueShift)/8] = s[2];\n      d[(24 - (48 - srcPF.redShift - srcPF.greenShift - srcPF.blueShift))/8] = s[3];\n    } else {\n      d[srcPF.redShift/8] = s[0];\n      d[srcPF.greenShift/8] = s[1];\n      d[srcPF.blueShift/8] = s[2];\n      d[(48 - srcPF.redShift - srcPF.greenShift - srcPF.blueShift)/8] = s[3];\n    }\n\n    dstPad = (dstStride - w) * 4;\n    srcPad = (srcStride - w) * 4;\n    while (h--) {\n      int w_ = w;\n      while (w_--) {\n        *d[0] = *(src++);\n        *d[1] = *(src++);\n        *d[2] = *(src++);\n        *d[3] = *(src++);\n        d[0] += 4;\n        d[1] += 4;\n        d[2] += 4;\n        d[3] += 4;\n      }\n      d[0] += dstPad;\n      d[1] += dstPad;\n      d[2] += dstPad;\n      d[3] += dstPad;\n      src += srcPad;\n    }\n  } else if (IS_ALIGNED(dst, bpp/8) && srcPF.is888()) {\n    // Optimised common case B: 888 source\n    switch (bpp) {\n    case 8:\n      directBufferFromBufferFrom888((uint8_t*)dst, srcPF, src,\n                                    w, h, dstStride, srcStride);\n      break;\n    case 16:\n      directBufferFromBufferFrom888((uint16_t*)dst, srcPF, src,\n                                    w, h, dstStride, srcStride);\n      break;\n    case 32:\n      directBufferFromBufferFrom888((uint32_t*)dst, srcPF, src,\n                                    w, h, dstStride, srcStride);\n      break;\n    }\n  } else if (IS_ALIGNED(src, srcPF.bpp/8) && is888()) {\n    // Optimised common case C: 888 destination\n    switch (srcPF.bpp) {\n    case 8:\n      directBufferFromBufferTo888(dst, srcPF, (uint8_t*)src,\n                                  w, h, dstStride, srcStride);\n      break;\n    case 16:\n      directBufferFromBufferTo888(dst, srcPF, (uint16_t*)src,\n                                  w, h, dstStride, srcStride);\n      break;\n    case 32:\n      directBufferFromBufferTo888(dst, srcPF, (uint32_t*)src,\n                                  w, h, dstStride, srcStride);\n      break;\n    }\n  } else {\n    // Generic code\n    int dstPad = (dstStride - w) * bpp/8;\n    int srcPad = (srcStride - w) * srcPF.bpp/8;\n    while (h--) {\n      int w_ = w;\n      while (w_--) {\n        Pixel p;\n        uint8_t r, g, b;\n\n        p = srcPF.pixelFromBuffer(src);\n        srcPF.rgbFromPixel(p, &r, &g, &b);\n        p = pixelFromRGB(r, g, b);\n        bufferFromPixel(dst, p);\n\n        dst += bpp/8;\n        src += srcPF.bpp/8;\n      }\n      dst += dstPad;\n      src += srcPad;\n    }\n  }\n}\n\n\nvoid PixelFormat::print(char* str, int len) const\n{\n  // Unfortunately snprintf is not widely available so we build the string up\n  // using strncat - not pretty, but should be safe against buffer overruns.\n\n  char num[20];\n  if (len < 1) return;\n  str[0] = 0;\n  strncat(str, \"depth \", len-1-strlen(str));\n  sprintf(num,\"%d\",depth);\n  strncat(str, num, len-1-strlen(str));\n  strncat(str, \" (\", len-1-strlen(str));\n  sprintf(num,\"%d\",bpp);\n  strncat(str, num, len-1-strlen(str));\n  strncat(str, \"bpp)\", len-1-strlen(str));\n  if (bpp != 8) {\n    if (bigEndian)\n      strncat(str, \" big-endian\", len-1-strlen(str));\n    else\n      strncat(str, \" little-endian\", len-1-strlen(str));\n  }\n\n  if (!trueColour) {\n    strncat(str, \" color-map\", len-1-strlen(str));\n    return;\n  }\n\n  if (blueShift == 0 && greenShift > blueShift && redShift > greenShift &&\n      blueMax  == (1 << greenShift) - 1 &&\n      greenMax == (1 << (redShift-greenShift)) - 1 &&\n      redMax   == (1 << (depth-redShift)) - 1)\n  {\n    strncat(str, \" rgb\", len-1-strlen(str));\n    sprintf(num,\"%d\",depth-redShift);\n    strncat(str, num, len-1-strlen(str));\n    sprintf(num,\"%d\",redShift-greenShift);\n    strncat(str, num, len-1-strlen(str));\n    sprintf(num,\"%d\",greenShift);\n    strncat(str, num, len-1-strlen(str));\n    return;\n  }\n\n  if (redShift == 0 && greenShift > redShift && blueShift > greenShift &&\n      redMax   == (1 << greenShift) - 1 &&\n      greenMax == (1 << (blueShift-greenShift)) - 1 &&\n      blueMax  == (1 << (depth-blueShift)) - 1)\n  {\n    strncat(str, \" bgr\", len-1-strlen(str));\n    sprintf(num,\"%d\",depth-blueShift);\n    strncat(str, num, len-1-strlen(str));\n    sprintf(num,\"%d\",blueShift-greenShift);\n    strncat(str, num, len-1-strlen(str));\n    sprintf(num,\"%d\",greenShift);\n    strncat(str, num, len-1-strlen(str));\n    return;\n  }\n\n  strncat(str, \" rgb max \", len-1-strlen(str));\n  sprintf(num,\"%d,\",redMax);\n  strncat(str, num, len-1-strlen(str));\n  sprintf(num,\"%d,\",greenMax);\n  strncat(str, num, len-1-strlen(str));\n  sprintf(num,\"%d\",blueMax);\n  strncat(str, num, len-1-strlen(str));\n  strncat(str, \" shift \", len-1-strlen(str));\n  sprintf(num,\"%d,\",redShift);\n  strncat(str, num, len-1-strlen(str));\n  sprintf(num,\"%d,\",greenShift);\n  strncat(str, num, len-1-strlen(str));\n  sprintf(num,\"%d\",blueShift);\n  strncat(str, num, len-1-strlen(str));\n}\n\n\nbool PixelFormat::parse(const char* str)\n{\n  char rgbbgr[4];\n  int bits1, bits2, bits3;\n  if (sscanf(str, \"%3s%1d%1d%1d\", rgbbgr, &bits1, &bits2, &bits3) < 4)\n    return false;\n  \n  depth = bits1 + bits2 + bits3;\n  bpp = depth <= 8 ? 8 : ((depth <= 16) ? 16 : 32);\n  trueColour = true;\n  uint32_t endianTest = 1;\n  bigEndian = (*(uint8_t*)&endianTest == 0);\n\n  greenShift = bits3;\n  greenMax = (1 << bits2) - 1;\n\n  if (strcasecmp(rgbbgr, \"bgr\") == 0) {\n    redShift = 0;\n    redMax = (1 << bits3) - 1;\n    blueShift = bits3 + bits2;\n    blueMax = (1 << bits1) - 1;\n  } else if (strcasecmp(rgbbgr, \"rgb\") == 0) {\n    blueShift = 0;\n    blueMax = (1 << bits3) - 1;\n    redShift = bits3 + bits2;\n    redMax = (1 << bits1) - 1;\n  } else {\n    return false;\n  }\n\n  assert(isSane());\n\n  updateState();\n\n  return true;\n}\n\n\nstatic int bits(uint16_t value)\n{\n  int bits;\n\n  bits = 16;\n\n  if (!(value & 0xff00)) {\n    bits -= 8;\n    value <<= 8;\n  }\n  if (!(value & 0xf000)) {\n    bits -= 4;\n    value <<= 4;\n  }\n  if (!(value & 0xc000)) {\n    bits -= 2;\n    value <<= 2;\n  }\n  if (!(value & 0x8000)) {\n    bits -= 1;\n    value <<= 1;\n  }\n\n  return bits;\n}\n\nvoid PixelFormat::updateState(void)\n{\n  int endianTest = 1;\n\n  redBits = bits(redMax);\n  greenBits = bits(greenMax);\n  blueBits = bits(blueMax);\n\n  maxBits = redBits;\n  if (greenBits > maxBits)\n    maxBits = greenBits;\n  if (blueBits > maxBits)\n    maxBits = blueBits;\n\n  minBits = redBits;\n  if (greenBits < minBits)\n    minBits = greenBits;\n  if (blueBits < minBits)\n    minBits = blueBits;\n\n  if (((*(char*)&endianTest) == 0) != bigEndian)\n    endianMismatch = true;\n  else\n    endianMismatch = false;\n}\n\nbool PixelFormat::isSane(void)\n{\n  int totalBits;\n\n  if ((bpp != 8) && (bpp != 16) && (bpp != 32))\n    return false;\n  if (depth > bpp)\n    return false;\n\n  if (!trueColour && (depth != 8))\n    return false;\n\n  if ((redMax & (redMax + 1)) != 0)\n    return false;\n  if ((greenMax & (greenMax + 1)) != 0)\n    return false;\n  if ((blueMax & (blueMax + 1)) != 0)\n    return false;\n\n  /*\n   * We don't allow individual channels > 8 bits in order to keep our\n   * conversions simple.\n   */\n  if (redMax >= (1 << 8))\n    return false;\n  if (greenMax >= (1 << 8))\n    return false;\n  if (blueMax >= (1 << 8))\n    return false;\n\n  totalBits = bits(redMax) + bits(greenMax) + bits(blueMax);\n  if (totalBits > depth)\n    return false;\n\n  if ((bits(redMax) + redShift) > bpp)\n    return false;\n  if ((bits(greenMax) + greenShift) > bpp)\n    return false;\n  if ((bits(blueMax) + blueShift) > bpp)\n    return false;\n\n  if (((redMax << redShift) & (greenMax << greenShift)) != 0)\n    return false;\n  if (((redMax << redShift) & (blueMax << blueShift)) != 0)\n    return false;\n  if (((greenMax << greenShift) & (blueMax << blueShift)) != 0)\n    return false;\n\n  return true;\n}\n\nstatic inline uint8_t swap(uint8_t n)\n{\n  return n;\n}\n\nstatic inline uint16_t swap(uint16_t n)\n{\n  return (((n) & 0xff) << 8) | (((n) >> 8) & 0xff);\n}\n\nstatic inline uint32_t swap(uint32_t n)\n{\n  return ((n) >> 24) | (((n) & 0x00ff0000) >> 8) |\n         (((n) & 0x0000ff00) << 8) | ((n) << 24);\n}\n\ntemplate<class T>\nvoid PixelFormat::directBufferFromBufferFrom888(T* dst,\n                                                const PixelFormat &srcPF,\n                                                const uint8_t* src,\n                                                int w, int h,\n                                                int dstStride,\n                                                int srcStride) const\n{\n  const uint8_t *r, *g, *b;\n  int dstPad, srcPad;\n\n  const uint8_t *redDownTable, *greenDownTable, *blueDownTable;\n\n  redDownTable = &downconvTable[(redBits-1)*256];\n  greenDownTable = &downconvTable[(greenBits-1)*256];\n  blueDownTable = &downconvTable[(blueBits-1)*256];\n\n  if (srcPF.bigEndian) {\n    r = src + (24 - srcPF.redShift)/8;\n    g = src + (24 - srcPF.greenShift)/8;\n    b = src + (24 - srcPF.blueShift)/8;\n  } else {\n    r = src + srcPF.redShift/8;\n    g = src + srcPF.greenShift/8;\n    b = src + srcPF.blueShift/8;\n  }\n\n  dstPad = (dstStride - w);\n  srcPad = (srcStride - w) * 4;\n  while (h--) {\n    int w_ = w;\n    while (w_--) {\n      T d;\n\n      d = redDownTable[*r] << redShift;\n      d |= greenDownTable[*g] << greenShift;\n      d |= blueDownTable[*b] << blueShift;\n\n      if (endianMismatch)\n        d = swap(d);\n\n      *dst = d;\n\n      dst++;\n      r += 4;\n      g += 4;\n      b += 4;\n    }\n    dst += dstPad;\n    r += srcPad;\n    g += srcPad;\n    b += srcPad;\n  }\n}\n\ntemplate<class T>\nvoid PixelFormat::directBufferFromBufferTo888(uint8_t* dst,\n                                              const PixelFormat &srcPF,\n                                              const T* src,\n                                              int w, int h,\n                                              int dstStride,\n                                              int srcStride) const\n{\n  uint8_t *r, *g, *b, *x;\n  int dstPad, srcPad;\n\n  const uint8_t *redUpTable, *greenUpTable, *blueUpTable;\n\n  redUpTable = &upconvTable[(srcPF.redBits-1)*256];\n  greenUpTable = &upconvTable[(srcPF.greenBits-1)*256];\n  blueUpTable = &upconvTable[(srcPF.blueBits-1)*256];\n\n  if (bigEndian) {\n    r = dst + (24 - redShift)/8;\n    g = dst + (24 - greenShift)/8;\n    b = dst + (24 - blueShift)/8;\n    x = dst + (24 - (48 - redShift - greenShift - blueShift))/8;\n  } else {\n    r = dst + redShift/8;\n    g = dst + greenShift/8;\n    b = dst + blueShift/8;\n    x = dst + (48 - redShift - greenShift - blueShift)/8;\n  }\n\n  dstPad = (dstStride - w) * 4;\n  srcPad = (srcStride - w);\n  while (h--) {\n    int w_ = w;\n    while (w_--) {\n      T s;\n\n      s = *src;\n\n      if (srcPF.endianMismatch)\n        s = swap(s);\n\n      *r = redUpTable[(s >> srcPF.redShift) & 0xff];\n      *g = greenUpTable[(s >> srcPF.greenShift) & 0xff];\n      *b = blueUpTable[(s >> srcPF.blueShift) & 0xff];\n      *x = 0;\n\n      r += 4;\n      g += 4;\n      b += 4;\n      x += 4;\n      src++;\n    }\n    r += dstPad;\n    g += dstPad;\n    b += dstPad;\n    x += dstPad;\n    src += srcPad;\n  }\n}\n"
  },
  {
    "path": "common/rfb/PixelFormat.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2009-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// PixelFormat - structure to represent a pixel format.  Also has useful\n// methods for reading & writing to streams, etc. Conversion to and from\n// other formats are also handled by this class. We have three different\n// representations that we refer to:\n//\n// a) Pixels - Unsigned native integers in the format specified by this\n//             PixelFormat object.\n// b) Buffer - Same thing as pixels, but in the appropriate byte stream\n//             format. This involves endian conversion and padding.\n// c) RGB - A byte stream of 8 bit red, green and blue elements, in that\n//          order.\n//\n\n#ifndef __RFB_PIXELFORMAT_H__\n#define __RFB_PIXELFORMAT_H__\n\n#include <stdint.h>\n\nnamespace rdr { class InStream; class OutStream; }\n\nnamespace rfb {\n\n  typedef uint32_t Pixel; // must be big enough to hold any pixel value\n\n  class PixelFormat {\n  public:\n    PixelFormat(int b, int d, bool e, bool t,\n                int rm, int gm, int bm, int rs, int gs, int bs);\n    PixelFormat();\n\n    // Checks if the formats have identical buffer representation.\n    // They might still have different pixel representation, endianness\n    // or true colour state.\n    bool operator==(const PixelFormat& other) const;\n    bool operator!=(const PixelFormat& other) const;\n\n    void read(rdr::InStream* is);\n    void write(rdr::OutStream* os) const;\n\n    bool is888(void) const;\n    bool isBigEndian(void) const;\n    bool isLittleEndian(void) const;\n\n    inline Pixel pixelFromBuffer(const uint8_t* buffer) const;\n    inline void bufferFromPixel(uint8_t* buffer, Pixel pixel) const;\n\n    inline Pixel pixelFromRGB(uint16_t red, uint16_t green, uint16_t blue) const;\n    inline Pixel pixelFromRGB(uint8_t red, uint8_t green, uint8_t blue) const;\n\n    void bufferFromRGB(uint8_t *dst, const uint8_t* src, int pixels) const;\n    void bufferFromRGB(uint8_t *dst, const uint8_t* src,\n                       int w, int stride, int h) const;\n\n    inline void rgbFromPixel(Pixel pix, uint16_t *r, uint16_t *g, uint16_t *b) const;\n    inline void rgbFromPixel(Pixel pix, uint8_t *r, uint8_t *g, uint8_t *b) const;\n\n    void rgbFromBuffer(uint8_t* dst, const uint8_t* src, int pixels) const;\n    void rgbFromBuffer(uint8_t* dst, const uint8_t* src,\n                       int w, int stride, int h) const;\n\n    Pixel pixelFromPixel(const PixelFormat &srcPF, Pixel src) const;\n\n    void bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF,\n                          const uint8_t* src, int pixels) const;\n    void bufferFromBuffer(uint8_t* dst, const PixelFormat &srcPF,\n                          const uint8_t* src, int w, int h,\n                          int dstStride, int srcStride) const;\n\n    void print(char* str, int len) const;\n    bool parse(const char* str);\n\n  protected:\n    void updateState(void);\n    bool isSane(void);\n\n  private:\n    // Templated, optimised methods\n    template<class T>\n    void directBufferFromBufferFrom888(T* dst, const PixelFormat &srcPF,\n                                       const uint8_t* src, int w, int h,\n                                       int dstStride, int srcStride) const;\n    template<class T>\n    void directBufferFromBufferTo888(uint8_t* dst, const PixelFormat &srcPF,\n                                     const T* src, int w, int h,\n                                     int dstStride, int srcStride) const;\n\n  public:\n    int bpp;\n    int depth;\n\n    // This only tracks if the client thinks it is in colour map mode.\n    // In practice we are always in true colour mode.\n    bool trueColour;\n\n  protected:\n    bool bigEndian;\n    int redMax;\n    int greenMax;\n    int blueMax;\n    int redShift;\n    int greenShift;\n    int blueShift;\n\n  protected:\n    /* Pre-computed values to keep algorithms simple */\n    int redBits, greenBits, blueBits;\n    int maxBits, minBits;\n    bool endianMismatch;\n\n    static uint8_t upconvTable[256*8];\n    static uint8_t downconvTable[256*8];\n\n    class Init;\n    friend class Init;\n    static Init _init;\n\n    /* Only for testing this class */\n    friend void makePixel(const rfb::PixelFormat &, uint8_t *);\n    friend void verifyPixel(const rfb::PixelFormat &,\n                            const rfb::PixelFormat &,\n                            const uint8_t *);\n  };\n}\n\n#include <rfb/PixelFormat.inl>\n\n#endif\n"
  },
  {
    "path": "common/rfb/PixelFormat.inl",
    "content": "/* Copyright 2009-2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\nnamespace rfb {\n\n\ninline Pixel PixelFormat::pixelFromBuffer(const uint8_t* buffer) const\n{\n  Pixel p;\n\n  p = 0;\n\n  if (bigEndian) {\n    switch (bpp) {\n    case 32:\n      p |= ((Pixel)*(buffer++)) << 24;\n      p |= ((Pixel)*(buffer++)) << 16;\n      /* fall through */\n    case 16:\n      p |= ((Pixel)*(buffer++)) << 8;\n      /* fall through */\n    case 8:\n      p |= *buffer;\n    }\n  } else {\n    p |= buffer[0];\n    if (bpp >= 16) {\n      p |= ((Pixel)buffer[1]) << 8;\n      if (bpp == 32) {\n        p |= ((Pixel)buffer[2]) << 16;\n        p |= ((Pixel)buffer[3]) << 24;\n      }\n    }\n  }\n\n  return p;\n}\n\n\ninline void PixelFormat::bufferFromPixel(uint8_t* buffer, Pixel p) const\n{\n  if (bigEndian) {\n    switch (bpp) {\n    case 32:\n      *(buffer++) = (p >> 24) & 0xff;\n      *(buffer++) = (p >> 16) & 0xff;\n      /* fall through */\n    case 16:\n      *(buffer++) = (p >>  8) & 0xff;\n      /* fall through */\n    case 8:\n      *(buffer++) = (p >>  0) & 0xff;\n    }\n  } else {\n    buffer[0] = (p >>  0) & 0xff;\n    if (bpp >= 16) {\n      buffer[1] = (p >>  8) & 0xff;\n      if (bpp == 32) {\n        buffer[2] = (p >> 16) & 0xff;\n        buffer[3] = (p >> 24) & 0xff;\n      }\n    }\n  }\n}\n\n\ninline Pixel PixelFormat::pixelFromRGB(uint16_t red, uint16_t green, uint16_t blue) const\n{\n  Pixel p;\n\n  p = (Pixel)downconvTable[(redBits-1)*256 + (red >> 8)] << redShift;\n  p |= (Pixel)downconvTable[(greenBits-1)*256 + (green >> 8)] << greenShift;\n  p |= (Pixel)downconvTable[(blueBits-1)*256 + (blue >> 8)] << blueShift;\n\n  return p;\n}\n\n\ninline Pixel PixelFormat::pixelFromRGB(uint8_t red, uint8_t green, uint8_t blue) const\n{\n  Pixel p;\n\n  p = (Pixel)downconvTable[(redBits-1)*256 + red] << redShift;\n  p |= (Pixel)downconvTable[(greenBits-1)*256 + green] << greenShift;\n  p |= (Pixel)downconvTable[(blueBits-1)*256 + blue] << blueShift;\n\n  return p;\n}\n\n\ninline void PixelFormat::rgbFromPixel(Pixel p, uint16_t *r, uint16_t *g, uint16_t *b) const\n{\n  uint8_t _r, _g, _b;\n\n  _r = p >> redShift;\n  _g = p >> greenShift;\n  _b = p >> blueShift;\n\n  _r = upconvTable[(redBits-1)*256 + _r];\n  _g = upconvTable[(greenBits-1)*256 + _g];\n  _b = upconvTable[(blueBits-1)*256 + _b];\n\n  *r = _r << 8 | _r;\n  *g = _g << 8 | _g;\n  *b = _b << 8 | _b;\n}\n\n\ninline void PixelFormat::rgbFromPixel(Pixel p, uint8_t *r, uint8_t *g, uint8_t *b) const\n{\n  uint8_t _r, _g, _b;\n\n  _r = p >> redShift;\n  _g = p >> greenShift;\n  _b = p >> blueShift;\n\n  *r = upconvTable[(redBits-1)*256 + _r];\n  *g = upconvTable[(greenBits-1)*256 + _g];\n  *b = upconvTable[(blueBits-1)*256 + _b];\n}\n\n\n}\n\n"
  },
  {
    "path": "common/rfb/RREDecoder.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rdr/InStream.h>\n#include <rdr/MemInStream.h>\n#include <rdr/OutStream.h>\n\n#include <rfb/Exception.h>\n#include <rfb/ServerParams.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/RREDecoder.h>\n\nusing namespace rfb;\n\nRREDecoder::RREDecoder() : Decoder(DecoderPlain)\n{\n}\n\nRREDecoder::~RREDecoder()\n{\n}\n\nbool RREDecoder::readRect(const core::Rect& /*r*/, rdr::InStream* is,\n                          const ServerParams& server, rdr::OutStream* os)\n{\n  uint32_t numRects;\n  size_t len;\n\n  if (!is->hasData(4))\n    return false;\n\n  is->setRestorePoint();\n\n  numRects = is->readU32();\n\n  len = server.pf().bpp/8 + numRects * (server.pf().bpp/8 + 8);\n\n  if (!is->hasDataOrRestore(len))\n    return false;\n\n  is->clearRestorePoint();\n\n  os->writeU32(numRects);\n  os->copyBytes(is, len);\n\n  return true;\n}\n\nvoid RREDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,\n                            size_t buflen, const ServerParams& server,\n                            ModifiablePixelBuffer* pb)\n{\n  rdr::MemInStream is(buffer, buflen);\n  const PixelFormat& pf = server.pf();\n  switch (pf.bpp) {\n  case 8:  rreDecode<uint8_t >(r, &is, pf, pb); break;\n  case 16: rreDecode<uint16_t>(r, &is, pf, pb); break;\n  case 32: rreDecode<uint32_t>(r, &is, pf, pb); break;\n  }\n}\n\ntemplate<class T>\ninline T RREDecoder::readPixel(rdr::InStream* is)\n{\n  if (sizeof(T) == 1)\n    return is->readOpaque8();\n  if (sizeof(T) == 2)\n    return is->readOpaque16();\n  if (sizeof(T) == 4)\n    return is->readOpaque32();\n}\n\ntemplate<class T>\nvoid RREDecoder::rreDecode(const core::Rect& r, rdr::InStream* is,\n                           const PixelFormat& pf,\n                           ModifiablePixelBuffer* pb)\n{\n  int nSubrects = is->readU32();\n  T bg = readPixel<T>(is);\n  pb->fillRect(pf, r, &bg);\n\n  for (int i = 0; i < nSubrects; i++) {\n    T pix = readPixel<T>(is);\n    int x = is->readU16();\n    int y = is->readU16();\n    int w = is->readU16();\n    int h = is->readU16();\n\n    if (((x+w) > r.width()) || ((y+h) > r.height()))\n      throw protocol_error(\"RRE decode error\");\n\n    pb->fillRect(pf, {r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h}, &pix);\n  }\n}\n"
  },
  {
    "path": "common/rfb/RREDecoder.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_RREDECODER_H__\n#define __RFB_RREDECODER_H__\n\n#include <rfb/Decoder.h>\n\nnamespace rfb {\n\n  class PixelFormat;\n\n  class RREDecoder : public Decoder {\n  public:\n    RREDecoder();\n    virtual ~RREDecoder();\n    bool readRect(const core::Rect& r, rdr::InStream* is,\n                  const ServerParams& server,\n                  rdr::OutStream* os) override;\n    void decodeRect(const core::Rect& r, const uint8_t* buffer,\n                    size_t buflen, const ServerParams& server,\n                    ModifiablePixelBuffer* pb) override;\n  private:\n    template<class T>\n    inline T readPixel(rdr::InStream* is);\n    template<class T>\n    void rreDecode(const core::Rect& r, rdr::InStream* is,\n                   const PixelFormat& pf, ModifiablePixelBuffer* pb);\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/RREEncoder.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rdr/OutStream.h>\n#include <rfb/encodings.h>\n#include <rfb/SConnection.h>\n#include <rfb/PixelFormat.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/Palette.h>\n#include <rfb/RREEncoder.h>\n\nusing namespace rfb;\n\nRREEncoder::RREEncoder(SConnection* conn_) :\n  Encoder(conn_, encodingRRE, EncoderPlain)\n{\n}\n\nRREEncoder::~RREEncoder()\n{\n}\n\nbool RREEncoder::isSupported()\n{\n  return conn->client.supportsEncoding(encodingRRE);\n}\n\nvoid RREEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)\n{\n  uint8_t* imageBuf;\n  int stride;\n  uint32_t bg;\n\n  int w = pb->width();\n  int h = pb->height();\n\n  if (palette.size() == 1) {\n    Encoder::writeSolidRect(pb, palette);\n    return;\n  }\n\n  // We have to have our own copy of the data as we modify it as\n  // we find subrects.\n  bufferCopy.setPF(pb->getPF());\n  bufferCopy.setSize(w, h);\n\n  imageBuf = bufferCopy.getBufferRW(pb->getRect(), &stride);\n  pb->getImage(imageBuf, pb->getRect());\n\n  if (palette.size() > 0)\n    bg = palette.getColour(0);\n  else {\n    // Some crazy person is using this encoder for high colour\n    // data. Just pick the first pixel as the background colour.\n    bg = 0;\n    memcpy(&bg, imageBuf, pb->getPF().bpp/8);\n  }\n\n  int nSubrects = -1;\n  switch (pb->getPF().bpp) {\n  case 8:\n    nSubrects = rreEncode<uint8_t>((uint8_t*)imageBuf, w, h, &mos, bg);\n    break;\n  case 16:\n    nSubrects = rreEncode<uint16_t>((uint16_t*)imageBuf, w, h, &mos, bg);\n    break;\n  case 32:\n    nSubrects = rreEncode<uint32_t>((uint32_t*)imageBuf, w, h, &mos, bg);\n    break;\n  }\n\n  bufferCopy.commitBufferRW(pb->getRect());\n\n  rdr::OutStream* os = conn->getOutStream();\n  os->writeU32(nSubrects);\n  os->writeBytes(mos.data(), mos.length());\n  mos.clear();\n}\n\nvoid RREEncoder::writeSolidRect(int /*width*/, int /*height*/,\n                                const PixelFormat& pf,\n                                const uint8_t* colour)\n{\n  rdr::OutStream* os;\n\n  os = conn->getOutStream();\n\n  os->writeU32(0);\n  os->writeBytes(colour, pf.bpp/8);\n}\n\ntemplate<class T>\ninline void RREEncoder::writePixel(rdr::OutStream* os, T pixel)\n{\n  if (sizeof(T) == 1)\n    os->writeOpaque8(pixel);\n  else if (sizeof(T) == 2)\n    os->writeOpaque16(pixel);\n  else if (sizeof(T) == 4)\n    os->writeOpaque32(pixel);\n}\n\ntemplate<class T>\nint RREEncoder::rreEncode(T* data, int w, int h,\n                          rdr::OutStream* os, T bg)\n{\n  writePixel(os, bg);\n\n  int nSubrects = 0;\n\n  for (int y = 0; y < h; y++)\n  {\n    int x = 0;\n    while (x < w) {\n      if (*data == bg) {\n        x++;\n        data++;\n        continue;\n      }\n\n      // Find horizontal subrect first\n      T* ptr = data+1;\n      T* eol = data+w-x;\n      while (ptr < eol && *ptr == *data) ptr++;\n      int sw = ptr - data;\n\n      ptr = data + w;\n      int sh = 1;\n      while (sh < h-y) {\n        eol = ptr + sw;\n        while (ptr < eol)\n          if (*ptr++ != *data) goto endOfHorizSubrect;\n        ptr += w - sw;\n        sh++;\n      }\n    endOfHorizSubrect:\n\n      // Find vertical subrect\n      int vh;\n      for (vh = sh; vh < h-y; vh++)\n        if (data[vh*w] != *data) break;\n\n      if (vh != sh) {\n        ptr = data+1;\n        int vw;\n        for (vw = 1; vw < sw; vw++) {\n          for (int i = 0; i < vh; i++)\n            if (ptr[i*w] != *data) goto endOfVertSubrect;\n          ptr++;\n        }\n      endOfVertSubrect:\n\n        // If vertical subrect bigger than horizontal then use that.\n        if (sw*sh < vw*vh) {\n          sw = vw;\n          sh = vh;\n        }\n      }\n\n      nSubrects++;\n      writePixel(os, *data);\n      os->writeU16(x);\n      os->writeU16(y);\n      os->writeU16(sw);\n      os->writeU16(sh);\n\n      ptr = data+w;\n      T* eor = data+w*sh;\n      while (ptr < eor) {\n        eol = ptr + sw;\n        while (ptr < eol) *ptr++ = bg;\n        ptr += w - sw;\n      }\n      x += sw;\n      data += sw;\n    }\n  }\n\n  return nSubrects;\n}\n"
  },
  {
    "path": "common/rfb/RREEncoder.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_RREENCODER_H__\n#define __RFB_RREENCODER_H__\n\n#include <rdr/MemOutStream.h>\n#include <rfb/Encoder.h>\n#include <rfb/PixelBuffer.h>\n\nnamespace rfb {\n\n  class RREEncoder : public Encoder {\n  public:\n    RREEncoder(SConnection* conn);\n    virtual ~RREEncoder();\n    bool isSupported() override;\n    void writeRect(const PixelBuffer* pb,\n                   const Palette& palette) override;\n    void writeSolidRect(int width, int height, const PixelFormat& pf,\n                        const uint8_t* colour) override;\n  private:\n    template<class T>\n    inline void writePixel(rdr::OutStream* os, T pixel);\n    template<class T>\n    int rreEncode(T* data, int w, int h, rdr::OutStream* os, T bg);\n  private:\n    rdr::MemOutStream mos;\n    ManagedPixelBuffer bufferCopy;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/RawDecoder.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <rdr/OutStream.h>\n#include <rfb/ServerParams.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/RawDecoder.h>\n\nusing namespace rfb;\n\nRawDecoder::RawDecoder() : Decoder(DecoderPlain)\n{\n}\n\nRawDecoder::~RawDecoder()\n{\n}\n\nbool RawDecoder::readRect(const core::Rect& r, rdr::InStream* is,\n                          const ServerParams& server, rdr::OutStream* os)\n{\n  if (!is->hasData(r.area() * (server.pf().bpp/8)))\n    return false;\n  os->copyBytes(is, r.area() * (server.pf().bpp/8));\n  return true;\n}\n\nvoid RawDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,\n                            size_t buflen, const ServerParams& server,\n                            ModifiablePixelBuffer* pb)\n{\n  assert(buflen >= (size_t)r.area() * (server.pf().bpp/8));\n  pb->imageRect(server.pf(), r, buffer);\n}\n"
  },
  {
    "path": "common/rfb/RawDecoder.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_RAWDECODER_H__\n#define __RFB_RAWDECODER_H__\n\n#include <rfb/Decoder.h>\n\nnamespace rfb {\n  class RawDecoder : public Decoder {\n  public:\n    RawDecoder();\n    virtual ~RawDecoder();\n    bool readRect(const core::Rect& r, rdr::InStream* is,\n                  const ServerParams& server,\n                  rdr::OutStream* os) override;\n    void decodeRect(const core::Rect& r, const uint8_t* buffer,\n                    size_t buflen, const ServerParams& server,\n                    ModifiablePixelBuffer* pb) override;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/RawEncoder.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rdr/OutStream.h>\n#include <rfb/encodings.h>\n#include <rfb/SConnection.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/RawEncoder.h>\n\nusing namespace rfb;\n\nRawEncoder::RawEncoder(SConnection* conn_) :\n  Encoder(conn_, encodingRaw, EncoderPlain)\n{\n}\n\nRawEncoder::~RawEncoder()\n{\n}\n\nbool RawEncoder::isSupported()\n{\n  // Implicitly required;\n  return true;\n}\n\nvoid RawEncoder::writeRect(const PixelBuffer* pb,\n                           const Palette& /*palette*/)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  rdr::OutStream* os;\n  int h, line_bytes, stride_bytes;\n\n  buffer = pb->getBuffer(pb->getRect(), &stride);\n\n  os = conn->getOutStream();\n\n  h = pb->height();\n  line_bytes = pb->width() * pb->getPF().bpp/8;\n  stride_bytes = stride * pb->getPF().bpp/8;\n  while (h--) {\n    os->writeBytes(buffer, line_bytes);\n    buffer += stride_bytes;\n  }\n}\n\nvoid RawEncoder::writeSolidRect(int width, int height,\n                                const PixelFormat& pf,\n                                const uint8_t* colour)\n{\n  rdr::OutStream* os;\n  int pixels, pixel_size;\n\n  os = conn->getOutStream();\n\n  pixels = width*height;\n  pixel_size = pf.bpp/8;\n  while (pixels--)\n    os->writeBytes(colour, pixel_size);\n}\n"
  },
  {
    "path": "common/rfb/RawEncoder.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_RAWENCODER_H__\n#define __RFB_RAWENCODER_H__\n\n#include <rfb/Encoder.h>\n\nnamespace rfb {\n\n  class RawEncoder : public Encoder {\n  public:\n    RawEncoder(SConnection* conn);\n    virtual ~RawEncoder();\n    bool isSupported() override;\n    void writeRect(const PixelBuffer* pb,\n                   const Palette& palette) override;\n    void writeSolidRect(int width, int height, const PixelFormat& pf,\n                        const uint8_t* colour) override;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/SConnection.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <string.h>\n\n#include <algorithm>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rdr/OutStream.h>\n\n#include <rfb/Exception.h>\n#include <rfb/Security.h>\n#include <rfb/clipboardTypes.h>\n#include <rfb/msgTypes.h>\n#include <rfb/fenceTypes.h>\n#include <rfb/SMsgReader.h>\n#include <rfb/SMsgWriter.h>\n#include <rfb/SConnection.h>\n#include <rfb/ServerCore.h>\n#include <rfb/encodings.h>\n#include <rfb/EncodeManager.h>\n#include <rfb/SSecurity.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"SConnection\");\n\nSConnection::SConnection(AccessRights accessRights_)\n  : readyForSetColourMapEntries(false), is(nullptr), os(nullptr),\n    reader_(nullptr), writer_(nullptr), ssecurity(nullptr),\n    authFailureTimer(this, &SConnection::handleAuthFailureTimeout),\n    state_(RFBSTATE_UNINITIALISED), preferredEncoding(encodingRaw),\n    accessRights(accessRights_), hasRemoteClipboard(false),\n    hasLocalClipboard(false),\n    unsolicitedClipboardAttempt(false)\n{\n  defaultMajorVersion = 3;\n  defaultMinorVersion = 8;\n  if (rfb::Server::protocol3_3)\n    defaultMinorVersion = 3;\n\n  client.setVersion(defaultMajorVersion, defaultMinorVersion);\n}\n\nSConnection::~SConnection()\n{\n  cleanup();\n}\n\nvoid SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)\n{\n  is = is_;\n  os = os_;\n}\n\nvoid SConnection::initialiseProtocol()\n{\n  char str[13];\n\n  sprintf(str, \"RFB %03d.%03d\\n\", defaultMajorVersion, defaultMinorVersion);\n  os->writeBytes((const uint8_t*)str, 12);\n  os->flush();\n\n  state_ = RFBSTATE_PROTOCOL_VERSION;\n}\n\nbool SConnection::processMsg()\n{\n  switch (state_) {\n  case RFBSTATE_PROTOCOL_VERSION: return processVersionMsg();      break;\n  case RFBSTATE_SECURITY_TYPE:    return processSecurityTypeMsg(); break;\n  case RFBSTATE_SECURITY:         return processSecurityMsg();     break;\n  case RFBSTATE_SECURITY_FAILURE: return processSecurityFailure(); break;\n  case RFBSTATE_INITIALISATION:   return processInitMsg();         break;\n  case RFBSTATE_NORMAL:           return reader_->readMsg();       break;\n  case RFBSTATE_QUERYING:\n    throw std::logic_error(\"SConnection::processMsg: Bogus data from \"\n                           \"client while querying\");\n  case RFBSTATE_CLIENT_READY:\n    throw std::logic_error(\"SConnection::processMsg: Bogus data from \"\n                           \"client while waiting for desktop\");\n  case RFBSTATE_CLOSING:\n    throw std::logic_error(\"SConnection::processMsg: Called while closing\");\n  case RFBSTATE_UNINITIALISED:\n    throw std::logic_error(\"SConnection::processMsg: Not initialised yet?\");\n  default:\n    throw std::logic_error(\"SConnection::processMsg: Invalid state\");\n  }\n}\n\nbool SConnection::processVersionMsg()\n{\n  char verStr[13];\n  int majorVersion;\n  int minorVersion;\n\n  vlog.debug(\"Reading protocol version\");\n\n  if (!is->hasData(12))\n    return false;\n\n  is->readBytes((uint8_t*)verStr, 12);\n  verStr[12] = '\\0';\n\n  if (sscanf(verStr, \"RFB %03d.%03d\\n\",\n             &majorVersion, &minorVersion) != 2) {\n    state_ = RFBSTATE_INVALID;\n    throw protocol_error(\"Reading version failed, not an RFB client?\");\n  }\n\n  client.setVersion(majorVersion, minorVersion);\n\n  vlog.info(\"Client needs protocol version %d.%d\",\n            client.majorVersion, client.minorVersion);\n\n  if (client.majorVersion != 3) {\n    // unknown protocol version\n    failConnection(core::format(\n      \"Client needs protocol version %d.%d, server has %d.%d\",\n      client.majorVersion, client.minorVersion,\n      defaultMajorVersion, defaultMinorVersion));\n  }\n\n  if (client.minorVersion != 3 && client.minorVersion != 7 && client.minorVersion != 8) {\n    vlog.error(\"Client uses unofficial protocol version %d.%d\",\n               client.majorVersion,client.minorVersion);\n    if (client.minorVersion >= 8)\n      client.minorVersion = 8;\n    else if (client.minorVersion == 7)\n      client.minorVersion = 7;\n    else\n      client.minorVersion = 3;\n    vlog.error(\"Assuming compatibility with version %d.%d\",\n               client.majorVersion,client.minorVersion);\n  }\n\n  std::list<uint8_t> secTypes;\n  std::list<uint8_t>::iterator i;\n  secTypes = security.GetEnabledSecTypes();\n\n  if (client.isVersion(3,3)) {\n\n    // cope with legacy 3.3 client only if \"no authentication\" or \"vnc\n    // authentication\" is supported.\n    for (i=secTypes.begin(); i!=secTypes.end(); i++) {\n      if (*i == secTypeNone || *i == secTypeVncAuth) break;\n    }\n    if (i == secTypes.end()) {\n      failConnection(\n        core::format(\"No supported security type for %d.%d client\",\n                     client.majorVersion, client.minorVersion));\n    }\n\n    os->writeU32(*i);\n    if (*i == secTypeNone) os->flush();\n    state_ = RFBSTATE_SECURITY;\n    ssecurity = security.GetSSecurity(this, *i);\n    return true;\n  }\n\n  // list supported security types for >=3.7 clients\n\n  if (secTypes.empty())\n    failConnection(\"No supported security types\");\n\n  os->writeU8(secTypes.size());\n  for (i=secTypes.begin(); i!=secTypes.end(); i++)\n    os->writeU8(*i);\n  os->flush();\n  state_ = RFBSTATE_SECURITY_TYPE;\n\n  return true;\n}\n\n\nbool SConnection::processSecurityTypeMsg()\n{\n  vlog.debug(\"Processing security type message\");\n\n  if (!is->hasData(1))\n    return false;\n\n  int secType = is->readU8();\n\n  processSecurityType(secType);\n\n  return true;\n}\n\nvoid SConnection::processSecurityType(int secType)\n{\n  // Verify that the requested security type should be offered\n  std::list<uint8_t> secTypes;\n\n  secTypes = security.GetEnabledSecTypes();\n  if (std::find(secTypes.begin(), secTypes.end(),\n                secType) == secTypes.end())\n    throw protocol_error(\"Requested security type not available\");\n\n  vlog.info(\"Client requests security type %s(%d)\",\n            secTypeName(secType),secType);\n\n  try {\n    state_ = RFBSTATE_SECURITY;\n    ssecurity = security.GetSSecurity(this, secType);\n  } catch (std::exception& e) {\n    failConnection(e.what());\n  }\n}\n\nbool SConnection::processSecurityMsg()\n{\n  vlog.debug(\"Processing security message\");\n  try {\n    if (!ssecurity->processMsg())\n      return false;\n  } catch (auth_error& e) {\n    vlog.error(\"Authentication error: %s\", e.what());\n    state_ = RFBSTATE_SECURITY_FAILURE;\n    // Introduce a slight delay of the authentication failure response\n    // to make it difficult to brute force a password\n    authFailureMsg = e.what();\n    authFailureTimer.start(100);\n    return true;\n  }\n\n  state_ = RFBSTATE_QUERYING;\n  setAccessRights(accessRights & ssecurity->getAccessRights());\n  queryConnection(ssecurity->getUserName());\n\n  // If the connection got approved right away then we can continue\n  if (state_ == RFBSTATE_INITIALISATION)\n    return true;\n\n  // Otherwise we need to wait for the result\n  // (or give up if if was rejected)\n  return false;\n}\n\nbool SConnection::processSecurityFailure()\n{\n  // Silently drop any data if we are currently delaying an\n  // authentication failure response as otherwise we would close\n  // the connection on unexpected data, and an attacker could use\n  // that to detect our delayed state.\n\n  if (!is->hasData(1))\n    return false;\n\n  is->skip(is->avail());\n\n  return true;\n}\n\nbool SConnection::processInitMsg()\n{\n  vlog.debug(\"Reading client initialisation\");\n  if (!reader_->readClientInit())\n    return false;\n\n  // If the desktop is ready right away then we can continue\n  if (state_ == RFBSTATE_NORMAL)\n    return true;\n\n  // Otherwise we need to wait\n  return false;\n}\n\nvoid SConnection::handleAuthFailureTimeout(core::Timer* /*t*/)\n{\n  if (state_ != RFBSTATE_SECURITY_FAILURE) {\n    close(\"SConnection::handleAuthFailureTimeout: Invalid state\");\n    return;\n  }\n\n  try {\n    os->writeU32(secResultFailed);\n    if (!client.beforeVersion(3,8)) { // 3.8 onwards have failure message\n      os->writeU32(authFailureMsg.size());\n      os->writeBytes((const uint8_t*)authFailureMsg.data(),\n                     authFailureMsg.size());\n    }\n    os->flush();\n  } catch (std::exception& e) {\n    close(e.what());\n    return;\n  }\n\n  close(authFailureMsg.c_str());\n}\n\nvoid SConnection::failConnection(const char* message)\n{\n  vlog.info(\"Connection failed: %s\", message);\n\n  if (state_ == RFBSTATE_PROTOCOL_VERSION) {\n    if (client.majorVersion == 3 && client.minorVersion == 3) {\n      os->writeU32(0);\n      os->writeU32(strlen(message));\n      os->writeBytes((const uint8_t*)message, strlen(message));\n      os->flush();\n    } else {\n      os->writeU8(0);\n      os->writeU32(strlen(message));\n      os->writeBytes((const uint8_t*)message, strlen(message));\n      os->flush();\n    }\n  }\n\n  state_ = RFBSTATE_INVALID;\n  throw protocol_error(message);\n}\n\nvoid SConnection::failConnection(const std::string& message)\n{\n  failConnection(message.c_str());\n}\n\nvoid SConnection::setAccessRights(AccessRights ar)\n{\n  accessRights = ar;\n}\n\nbool SConnection::accessCheck(AccessRights ar) const\n{\n  if (state_ < RFBSTATE_QUERYING)\n    throw std::logic_error(\"SConnection::accessCheck: Invalid state\");\n\n  return (accessRights & ar) == ar;\n}\n\nvoid SConnection::clientInit(bool shared)\n{\n  state_ = RFBSTATE_CLIENT_READY;\n  clientReady(shared);\n}\n\nvoid SConnection::setEncodings(int nEncodings, const int32_t* encodings)\n{\n  int i;\n  bool firstFence, firstContinuousUpdates, firstLEDState,\n       firstQEMUKeyEvent, firstExtMouseButtonsEvent;\n\n  preferredEncoding = encodingRaw;\n  for (i = 0;i < nEncodings;i++) {\n    if (EncodeManager::supported(encodings[i])) {\n      preferredEncoding = encodings[i];\n      break;\n    }\n  }\n\n  firstFence = !client.supportsFence();\n  firstContinuousUpdates = !client.supportsContinuousUpdates();\n  firstLEDState = !client.supportsLEDState();\n  firstQEMUKeyEvent = !client.supportsEncoding(pseudoEncodingQEMUKeyEvent);\n  firstExtMouseButtonsEvent = !client.supportsEncoding(pseudoEncodingExtendedMouseButtons);\n\n  client.setEncodings(nEncodings, encodings);\n\n  supportsLocalCursor();\n\n  if (client.supportsFence() && firstFence)\n    supportsFence();\n  if (client.supportsContinuousUpdates() && firstContinuousUpdates)\n    supportsContinuousUpdates();\n  if (client.supportsLEDState() && firstLEDState)\n    supportsLEDState();\n  if (client.supportsEncoding(pseudoEncodingQEMUKeyEvent) && firstQEMUKeyEvent)\n    writer()->writeQEMUKeyEvent();\n  if (client.supportsEncoding(pseudoEncodingExtendedMouseButtons) && firstExtMouseButtonsEvent)\n    writer()->writeExtendedMouseButtonsSupport();\n\n  if (client.supportsEncoding(pseudoEncodingExtendedClipboard)) {\n    uint32_t sizes[] = { 0 };\n    writer()->writeClipboardCaps(rfb::clipboardUTF8 |\n                                 rfb::clipboardRequest |\n                                 rfb::clipboardPeek |\n                                 rfb::clipboardNotify |\n                                 rfb::clipboardProvide,\n                                 sizes);\n  }\n}\n\nvoid SConnection::clientCutText(const char* str)\n{\n  hasLocalClipboard = false;\n\n  clientClipboard = str;\n  hasRemoteClipboard = true;\n\n  if (!accessCheck(AccessCutText))\n    return;\n\n  handleClipboardAnnounce(true);\n}\n\nvoid SConnection::handleClipboardCaps(uint32_t flags, const uint32_t* lengths)\n{\n  int i;\n\n  vlog.debug(\"Got client clipboard capabilities:\");\n  for (i = 0;i < 16;i++) {\n    if (flags & (1 << i)) {\n      const char *type;\n\n      switch (1 << i) {\n        case clipboardUTF8:\n          type = \"Plain text\";\n          break;\n        case clipboardRTF:\n          type = \"Rich text\";\n          break;\n        case clipboardHTML:\n          type = \"HTML\";\n          break;\n        case clipboardDIB:\n          type = \"Images\";\n          break;\n        case clipboardFiles:\n          type = \"Files\";\n          break;\n        default:\n          vlog.debug(\"    Unknown format 0x%x\", 1 << i);\n          continue;\n      }\n\n      if (lengths[i] == 0)\n        vlog.debug(\"    %s (only notify)\", type);\n      else {\n        vlog.debug(\"    %s (automatically send up to %s)\",\n                   type, core::iecPrefix(lengths[i], \"B\").c_str());\n      }\n    }\n  }\n\n  client.setClipboardCaps(flags, lengths);\n}\n\nvoid SConnection::handleClipboardRequest(uint32_t flags)\n{\n  if (!(flags & rfb::clipboardUTF8)) {\n    vlog.debug(\"Ignoring clipboard request for unsupported formats 0x%x\", flags);\n    return;\n  }\n  if (!hasLocalClipboard) {\n    vlog.debug(\"Ignoring unexpected clipboard request\");\n    return;\n  }\n  if (!accessCheck(AccessCutText))\n    return;\n  handleClipboardRequest();\n}\n\nvoid SConnection::handleClipboardPeek()\n{\n  if (client.clipboardFlags() & rfb::clipboardNotify)\n    writer()->writeClipboardNotify(hasLocalClipboard ? rfb::clipboardUTF8 : 0);\n}\n\nvoid SConnection::handleClipboardNotify(uint32_t flags)\n{\n  hasRemoteClipboard = false;\n\n  if (flags & rfb::clipboardUTF8) {\n    hasLocalClipboard = false;\n    if (!accessCheck(AccessCutText))\n      return;\n    handleClipboardAnnounce(true);\n  } else {\n    if (!accessCheck(AccessCutText))\n      return;\n    handleClipboardAnnounce(false);\n  }\n\n}\n\nvoid SConnection::handleClipboardProvide(uint32_t flags,\n                                         const size_t* lengths,\n                                         const uint8_t* const* data)\n{\n  if (!(flags & rfb::clipboardUTF8)) {\n    vlog.debug(\"Ignoring clipboard provide with unsupported formats 0x%x\", flags);\n    return;\n  }\n\n  // FIXME: This conversion magic should be in SMsgReader\n  if (!core::isValidUTF8((const char*)data[0], lengths[0])) {\n    vlog.error(\"Invalid UTF-8 sequence in clipboard - ignoring\");\n    return;\n  }\n  clientClipboard = core::convertLF((const char*)data[0], lengths[0]);\n  hasRemoteClipboard = true;\n\n  if (!accessCheck(AccessCutText))\n    return;\n\n  // FIXME: Should probably verify that this data was actually requested\n  handleClipboardData(clientClipboard.c_str());\n}\n\nvoid SConnection::supportsLocalCursor()\n{\n}\n\nvoid SConnection::supportsFence()\n{\n}\n\nvoid SConnection::supportsContinuousUpdates()\n{\n}\n\nvoid SConnection::supportsLEDState()\n{\n}\n\nvoid SConnection::authSuccess()\n{\n}\n\nvoid SConnection::queryConnection(const char* /*userName*/)\n{\n  approveConnection(true);\n}\n\nvoid SConnection::clientReady(bool /*shared*/)\n{\n  desktopReady();\n}\n\nvoid SConnection::approveConnection(bool accept, const char* reason)\n{\n  if (state_ != RFBSTATE_QUERYING)\n    throw std::logic_error(\"SConnection::approveConnection: Invalid state\");\n\n  if (!client.beforeVersion(3,8) || ssecurity->getType() != secTypeNone) {\n    if (accept) {\n      os->writeU32(secResultOK);\n    } else {\n      os->writeU32(secResultFailed);\n      if (!client.beforeVersion(3,8)) { // 3.8 onwards have failure message\n        if (!reason)\n          reason = \"Connection rejected\";\n        os->writeU32(strlen(reason));\n        os->writeBytes((const uint8_t*)reason, strlen(reason));\n      }\n    }\n    os->flush();\n  }\n\n  if (accept) {\n    state_ = RFBSTATE_INITIALISATION;\n    reader_ = new SMsgReader(this, is);\n    writer_ = new SMsgWriter(&client, os);\n    authSuccess();\n  } else {\n    state_ = RFBSTATE_INVALID;\n    if (reason)\n      throw auth_error(reason);\n    else\n      throw auth_error(\"Connection rejected\");\n  }\n}\n\nvoid SConnection::desktopReady()\n{\n  if (state() != RFBSTATE_CLIENT_READY)\n    return;\n  writer_->writeServerInit(client.width(), client.height(),\n                           client.pf(), client.name());\n  state_ = RFBSTATE_NORMAL;\n}\n\nvoid SConnection::close(const char* /*reason*/)\n{\n  state_ = RFBSTATE_CLOSING;\n  cleanup();\n}\n\nvoid SConnection::setPixelFormat(const PixelFormat& pf)\n{\n  client.setPF(pf);\n  readyForSetColourMapEntries = true;\n  if (!pf.trueColour)\n    writeFakeColourMap();\n}\n\nvoid SConnection::framebufferUpdateRequest(const core::Rect& /*r*/,\n                                           bool /*incremental*/)\n{\n  if (!readyForSetColourMapEntries) {\n    readyForSetColourMapEntries = true;\n    if (!client.pf().trueColour) {\n      writeFakeColourMap();\n    }\n  }\n}\n\nvoid SConnection::fence(uint32_t flags, unsigned len,\n                        const uint8_t data[])\n{\n  if (!(flags & fenceFlagRequest))\n    return;\n\n  // We cannot guarantee any synchronisation at this level\n  flags = 0;\n\n  writer()->writeFence(flags, len, data);\n}\n\nvoid SConnection::enableContinuousUpdates(bool /*enable*/,\n                                          int /*x*/, int /*y*/,\n                                          int /*w*/, int /*h*/)\n{\n}\n\nvoid SConnection::handleClipboardRequest()\n{\n}\n\nvoid SConnection::handleClipboardAnnounce(bool /*available*/)\n{\n}\n\nvoid SConnection::handleClipboardData(const char* /*data*/)\n{\n}\n\nvoid SConnection::requestClipboard()\n{\n  if (!accessCheck(AccessCutText))\n    return;\n\n  if (hasRemoteClipboard) {\n    handleClipboardData(clientClipboard.c_str());\n    return;\n  }\n\n  if (client.supportsEncoding(pseudoEncodingExtendedClipboard) &&\n      (client.clipboardFlags() & rfb::clipboardRequest))\n    writer()->writeClipboardRequest(rfb::clipboardUTF8);\n}\n\nvoid SConnection::announceClipboard(bool available)\n{\n  if (!accessCheck(AccessCutText))\n    return;\n\n  hasLocalClipboard = available;\n  unsolicitedClipboardAttempt = false;\n\n  if (client.supportsEncoding(pseudoEncodingExtendedClipboard)) {\n    // Attempt an unsolicited transfer?\n    if (available &&\n        (client.clipboardSize(rfb::clipboardUTF8) > 0) &&\n        (client.clipboardFlags() & rfb::clipboardProvide)) {\n      vlog.debug(\"Attempting unsolicited clipboard transfer...\");\n      unsolicitedClipboardAttempt = true;\n      handleClipboardRequest();\n      return;\n    }\n\n    if (client.clipboardFlags() & rfb::clipboardNotify) {\n      writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);\n      return;\n    }\n  }\n\n  if (available)\n    handleClipboardRequest();\n}\n\nvoid SConnection::sendClipboardData(const char* data)\n{\n  if (!accessCheck(AccessCutText))\n    return;\n\n  if (client.supportsEncoding(pseudoEncodingExtendedClipboard) &&\n      (client.clipboardFlags() & rfb::clipboardProvide)) {\n    // FIXME: This conversion magic should be in SMsgWriter\n    std::string filtered(core::convertCRLF(data));\n    size_t sizes[1] = { filtered.size() + 1 };\n    const uint8_t* datas[1] = { (const uint8_t*)filtered.c_str() };\n\n    if (unsolicitedClipboardAttempt) {\n      unsolicitedClipboardAttempt = false;\n      if (sizes[0] > client.clipboardSize(rfb::clipboardUTF8)) {\n        vlog.debug(\"Clipboard was too large for unsolicited clipboard transfer\");\n        if (client.clipboardFlags() & rfb::clipboardNotify)\n          writer()->writeClipboardNotify(rfb::clipboardUTF8);\n        return;\n      }\n    }\n\n    writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, datas);\n  } else {\n    writer()->writeServerCutText(data);\n  }\n}\n\nvoid SConnection::cleanup()\n{\n  delete ssecurity;\n  ssecurity = nullptr;\n  delete reader_;\n  reader_ = nullptr;\n  delete writer_;\n  writer_ = nullptr;\n}\n\nvoid SConnection::writeFakeColourMap(void)\n{\n  int i;\n  uint16_t red[256], green[256], blue[256];\n\n  for (i = 0;i < 256;i++)\n    client.pf().rgbFromPixel(i, &red[i], &green[i], &blue[i]);\n\n  writer()->writeSetColourMapEntries(0, 256, red, green, blue);\n}\n"
  },
  {
    "path": "common/rfb/SConnection.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// SConnection - class on the server side representing a connection to a\n// client.  A derived class should override methods appropriately.\n//\n\n#ifndef __RFB_SCONNECTION_H__\n#define __RFB_SCONNECTION_H__\n\n#include <string>\n\n#include <core/Timer.h>\n\n#include <rfb/AccessRights.h>\n#include <rfb/SMsgHandler.h>\n#include <rfb/SecurityServer.h>\n\nnamespace rdr {\n  class InStream;\n  class OutStream;\n}\n\nnamespace rfb {\n\n  class SMsgReader;\n  class SMsgWriter;\n  class SSecurity;\n\n  class SConnection : public SMsgHandler {\n  public:\n\n    SConnection(AccessRights accessRights);\n    virtual ~SConnection();\n\n    // Methods to initialise the connection\n\n    // setStreams() sets the streams to be used for the connection.  These must\n    // be set before initialiseProtocol() and processMsg() are called.  The\n    // SSecurity object may call setStreams() again to provide alternative\n    // streams over which the RFB protocol is sent (i.e. encrypting/decrypting\n    // streams).  Ownership of the streams remains with the caller\n    // (i.e. SConnection will not delete them).\n    void setStreams(rdr::InStream* is, rdr::OutStream* os);\n\n    // initialiseProtocol() should be called once the streams and security\n    // types are set.  Subsequently, processMsg() should be called whenever\n    // there is data to read on the InStream.\n    void initialiseProtocol();\n\n    // processMsg() should be called whenever there is data available on\n    // the CConnection's current InStream. It will process at most one\n    // RFB message before returning. If there was insufficient data,\n    // then it will return false and should be called again once more\n    // data is available.\n    bool processMsg();\n\n    // approveConnection() is called to either accept or reject the\n    // connection. If accept is false, the reason string gives the\n    // reason for the rejection.  It can either be called directly from\n    // queryConnection() or later, after queryConnection() has returned.\n    // It can only be called when in state RFBSTATE_QUERYING.  On\n    // rejection, an auth_error is thrown, so this must be handled\n    // appropriately by the caller.\n    void approveConnection(bool accept, const char* reason=nullptr);\n\n    // desktopReady() is called when the desktop has finished\n    // initializing and is ready for a client.\n    virtual void desktopReady();\n\n\n    // Methods to terminate the connection\n\n    // close() shuts down the connection to the client and awaits\n    // cleanup of the SConnection object by the server\n    virtual void close(const char* reason);\n\n    // requestClipboard() will result in a request to the client to\n    // transfer its clipboard data. A call to handleClipboardData()\n    // will be made once the data is available.\n    virtual void requestClipboard();\n\n    // announceClipboard() informs the client of changes to the\n    // clipboard on the server. The client may later request the\n    // clipboard data via handleClipboardRequest().\n    virtual void announceClipboard(bool available);\n\n    // sendClipboardData() transfers the clipboard data to the client\n    // and should be called whenever the client has requested the\n    // clipboard via handleClipboardRequest().\n    virtual void sendClipboardData(const char* data);\n\n    // getAccessRights() returns the access rights of a SConnection to the server.\n    AccessRights getAccessRights() { return accessRights; }\n\n    // setAccessRights() allows a security package to limit the access rights\n    // of a SConnection to the server.  How the access rights are treated\n    // is up to the derived class.\n    virtual void setAccessRights(AccessRights ar);\n    virtual bool accessCheck(AccessRights ar) const;\n\n    // authenticated() returns true if the client has authenticated\n    // successfully.\n    bool authenticated() { return (state_ == RFBSTATE_INITIALISATION ||\n                                   state_ == RFBSTATE_CLIENT_READY ||\n                                   state_ == RFBSTATE_NORMAL); }\n\n    SMsgReader* reader() { return reader_; }\n    SMsgWriter* writer() { return writer_; }\n\n    rdr::InStream* getInStream() { return is; }\n    rdr::OutStream* getOutStream() { return os; }\n\n    enum stateEnum {\n      RFBSTATE_UNINITIALISED,\n      RFBSTATE_PROTOCOL_VERSION,\n      RFBSTATE_SECURITY_TYPE,\n      RFBSTATE_SECURITY,\n      RFBSTATE_SECURITY_FAILURE,\n      RFBSTATE_QUERYING,\n      RFBSTATE_INITIALISATION,\n      RFBSTATE_CLIENT_READY,\n      RFBSTATE_NORMAL,\n      RFBSTATE_CLOSING,\n      RFBSTATE_INVALID\n    };\n\n    stateEnum state() { return state_; }\n\n    int32_t getPreferredEncoding() { return preferredEncoding; }\n\n  protected:\n\n    // Overridden from SMsgHandler\n\n    void clientInit(bool shared) override;\n\n    void setEncodings(int nEncodings, const int32_t* encodings) override;\n\n    void clientCutText(const char* str) override;\n\n    void handleClipboardCaps(uint32_t flags,\n                             const uint32_t* lengths) override;\n    void handleClipboardRequest(uint32_t flags) override;\n    void handleClipboardPeek() override;\n    void handleClipboardNotify(uint32_t flags) override;\n    void handleClipboardProvide(uint32_t flags, const size_t* lengths,\n                                const uint8_t* const* data) override;\n\n    // Methods to be overridden in a derived class\n\n    // supportsLocalCursor() is called whenever the status of\n    // cp.supportsLocalCursor has changed.  At the moment this happens on a\n    // setEncodings message, but in the future this may be due to a message\n    // specially for this purpose.\n    virtual void supportsLocalCursor();\n\n    // supportsFence() is called the first time we detect support for fences\n    // in the client. A fence message should be sent at this point to notify\n    // the client of server support.\n    virtual void supportsFence();\n\n    // supportsContinuousUpdates() is called the first time we detect that\n    // the client wants the continuous updates extension. A\n    // EndOfContinuousUpdates message should be sent back to the client at\n    // this point if it is supported.\n    virtual void supportsContinuousUpdates();\n\n    // supportsLEDState() is called the first time we detect that the\n    // client supports the LED state extension. A LEDState message\n    // should be sent back to the client to inform it of the current\n    // server state.\n    virtual void supportsLEDState();\n\n    // authSuccess() is called when authentication has succeeded.\n    virtual void authSuccess();\n\n    // queryConnection() is called when authentication has succeeded, but\n    // before informing the client.  It can be overridden to query a local user\n    // to accept the incoming connection, for example.  The userName argument\n    // is the name of the user making the connection, or null (note that the\n    // storage for userName is owned by the caller).  The connection must be\n    // accepted or rejected by calling approveConnection(), either directly\n    // from queryConnection() or some time later.\n    virtual void queryConnection(const char* userName);\n\n    // clientReady() is called when the client has fully completed\n    // initialization. This can be overridden if the desktop needs more\n    // time to get ready (i.e. provide a framebuffer and name). Once the\n    // desktop is ready, the derived class must call on to\n    // SConnection::desktopReady().\n    virtual void clientReady(bool shared);\n\n    // setPixelFormat() is called when a SetPixelFormat message is received.\n    // The derived class must call on to SConnection::setPixelFormat().\n    void setPixelFormat(const PixelFormat& pf) override;\n\n    // framebufferUpdateRequest() is called when a FramebufferUpdateRequest\n    // message is received.  The derived class must call on to\n    // SConnection::framebufferUpdateRequest().\n    void framebufferUpdateRequest(const core::Rect& r, bool incremental) override;\n\n    // fence() is called when we get a fence request or response. By default\n    // it responds directly to requests (stating it doesn't support any\n    // synchronisation) and drops responses. Override to implement more proper\n    // support.\n    void fence(uint32_t flags, unsigned len, const uint8_t data[]) override;\n\n    // enableContinuousUpdates() is called when the client wants to enable\n    // or disable continuous updates, or change the active area.\n    void enableContinuousUpdates(bool enable,\n                                 int x, int y, int w, int h) override;\n\n    // handleClipboardRequest() is called whenever the client requests\n    // the server to send over its clipboard data. It will only be\n    // called after the server has first announced a clipboard change\n    // via announceClipboard().\n    virtual void handleClipboardRequest();\n\n    // handleClipboardAnnounce() is called to indicate a change in the\n    // clipboard on the client. Call requestClipboard() to access the\n    // actual data.\n    virtual void handleClipboardAnnounce(bool available);\n\n    // handleClipboardData() is called when the client has sent over\n    // the clipboard data as a result of a previous call to\n    // requestClipboard(). Note that this function might never be\n    // called if the clipboard data was no longer available when the\n    // client received the request.\n    virtual void handleClipboardData(const char* data);\n\n    // failConnection() prints a message to the log, sends a connection\n    // failed message to the client (if possible) and throws an\n    // Exception.\n    void failConnection(const char* message);\n    void failConnection(const std::string& message);\n\n    void setState(stateEnum s) { state_ = s; }\n\n    void setReader(SMsgReader *r) { reader_ = r; }\n    void setWriter(SMsgWriter *w) { writer_ = w; }\n\n  private:\n    void cleanup();\n    void writeFakeColourMap(void);\n\n    bool readyForSetColourMapEntries;\n\n    bool processVersionMsg();\n    bool processSecurityTypeMsg();\n    void processSecurityType(int secType);\n    bool processSecurityMsg();\n    bool processSecurityFailure();\n    bool processInitMsg();\n\n    void handleAuthFailureTimeout(core::Timer* t);\n\n    int defaultMajorVersion, defaultMinorVersion;\n\n    rdr::InStream* is;\n    rdr::OutStream* os;\n\n    SMsgReader* reader_;\n    SMsgWriter* writer_;\n\n    SecurityServer security;\n    SSecurity* ssecurity;\n\n    core::MethodTimer<SConnection> authFailureTimer;\n    std::string authFailureMsg;\n\n    stateEnum state_;\n    int32_t preferredEncoding;\n    AccessRights accessRights;\n\n    std::string clientClipboard;\n    bool hasRemoteClipboard;\n    bool hasLocalClipboard;\n    bool unsolicitedClipboardAttempt;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/SDesktop.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n/////////////////////////////////////////////////////////////////////////////\n\n// SDesktop is an interface implemented by back-ends, on which callbacks are\n// made by the VNCServer as appropriate for pointer and keyboard events, etc.\n// SDesktop objects are always created before the VNCServer - the SDesktop\n// will be passed a pointer to the VNCServer in the start() call.  If a more\n// implementation-specific pointer to the VNCServer is required then this\n// can be provided to the SDesktop via an implementation-specific method.\n//\n// An SDesktop usually has an associated PixelBuffer which it tells the\n// VNCServer via the VNCServer's setPixelBuffer() method.  It can do this at\n// any time, but the PixelBuffer MUST be valid by the time the call to start()\n// returns.  The PixelBuffer may be set to null again if desired when stop() is\n// called.  Note that start() and stop() are guaranteed to be called\n// alternately; there should never be two calls to start() without an\n// intervening stop() and vice-versa.\n//\n\n#ifndef __RFB_SDESKTOP_H__\n#define __RFB_SDESKTOP_H__\n\n#include <stdint.h>\n\n#include <rfb/screenTypes.h>\n\nnamespace core { struct Point; }\n\nnamespace network { class Socket; }\n\nnamespace rfb {\n\n  struct ScreenSet;\n  class VNCServer;\n\n  class SDesktop {\n  protected:\n    SDesktop() {};\n  public:\n    virtual ~SDesktop() {}\n\n    // init() is called immediately when the VNCServer gets a reference\n    // to the SDesktop, so that a reverse reference can be set up.\n    virtual void init(rfb::VNCServer* vs) = 0;\n\n    // start() is called by the server when the first client authenticates\n    // successfully, and can be used to begin any expensive tasks which are not\n    // needed when there are no clients.  A valid PixelBuffer must have been\n    // set via the VNCServer's setPixelBuffer() method by the time this call\n    // returns.\n    virtual void start() {}\n\n    // stop() is called by the server when there are no longer any\n    // authenticated clients, and therefore the desktop can cease any\n    // expensive tasks.\n    virtual void stop() {}\n\n    // queryConnection() is called when a connection has been\n    // successfully authenticated.  The sock and userName arguments\n    // identify the socket and the name of the authenticated user, if\n    // any. At some point later VNCServer::approveConnection() should\n    // be called to either accept or reject the client.\n    virtual void queryConnection(network::Socket* sock,\n                                 const char* userName) = 0;\n\n    // terminate() is called by the server when it wishes to terminate\n    // itself, e.g. because it was configured to terminate when no one is\n    // using it.\n\n    virtual void terminate() = 0;\n\n    // setScreenLayout() requests to reconfigure the framebuffer and/or\n    // the layout of screens.\n    virtual unsigned int setScreenLayout(int /*fb_width*/,\n                                         int /*fb_height*/,\n                                         const ScreenSet& /*layout*/) {\n      return resultProhibited;\n    }\n\n    // frameTick() is called whenever a frame update has been processed,\n    // signalling that a good time to render new data\n    virtual void frameTick(uint64_t msc) { (void)msc; }\n\n    // keyEvent() is called whenever a client sends an event that a\n    // key was pressed or released.\n    virtual void keyEvent(uint32_t /*keysym*/, uint32_t /*keycode*/,\n                          bool /*down*/) {};\n\n    // pointerEvent() is called whenever a client sends an event that\n    // the pointer moved, or a button was pressed or released.\n    virtual void pointerEvent(const core::Point& /*pos*/,\n                              uint16_t /*buttonMask*/) {};\n\n    // handleClipboardRequest() is called whenever a client requests\n    // the server to send over its clipboard data. It will only be\n    // called after the server has first announced a clipboard change\n    // via VNCServer::announceClipboard().\n    virtual void handleClipboardRequest() {}\n\n    // handleClipboardAnnounce() is called to indicate a change in the\n    // clipboard on a client. Call VNCServer::requestClipboard() to\n    // access the actual data.\n    virtual void handleClipboardAnnounce(bool /*available*/) {}\n\n    // handleClipboardData() is called when a client has sent over\n    // the clipboard data as a result of a previous call to\n    // VNCServer::requestClipboard(). Note that this function might\n    // never be called if the clipboard data was no longer available\n    // when the client received the request.\n    virtual void handleClipboardData(const char* /*data*/) {}\n\n  };\n\n};\n\n#endif // __RFB_SDESKTOP_H__\n"
  },
  {
    "path": "common/rfb/SMsgHandler.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// SMsgHandler - class to handle incoming messages on the server side.\n//\n\n#ifndef __RFB_SMSGHANDLER_H__\n#define __RFB_SMSGHANDLER_H__\n\n#include <stdint.h>\n\n#include <rfb/ClientParams.h>\n\nnamespace rfb {\n\n  class SMsgHandler {\n  public:\n    virtual ~SMsgHandler() {}\n\n    // The following methods are called as corresponding messages are\n    // read. A derived class must override these methods.\n\n    virtual void clientInit(bool shared) = 0;\n\n    virtual void setPixelFormat(const PixelFormat& pf) = 0;\n    virtual void setEncodings(int nEncodings,\n                              const int32_t* encodings) = 0;\n    virtual void framebufferUpdateRequest(const core::Rect& r,\n                                          bool incremental) = 0;\n    virtual void setDesktopSize(int fb_width, int fb_height,\n                                const ScreenSet& layout) = 0;\n    virtual void fence(uint32_t flags, unsigned len,\n                       const uint8_t data[]) = 0;\n    virtual void enableContinuousUpdates(bool enable,\n                                         int x, int y,\n                                         int w, int h) = 0;\n\n    virtual void keyEvent(uint32_t keysym, uint32_t keycode,\n                          bool down) = 0;\n    virtual void pointerEvent(const core::Point& pos,\n                              uint16_t buttonMask) = 0;\n\n    virtual void clientCutText(const char* str) = 0;\n\n    virtual void handleClipboardCaps(uint32_t flags,\n                                     const uint32_t* lengths) = 0;\n    virtual void handleClipboardRequest(uint32_t flags) = 0;\n    virtual void handleClipboardPeek() = 0;\n    virtual void handleClipboardNotify(uint32_t flags) = 0;\n    virtual void handleClipboardProvide(uint32_t flags,\n                                        const size_t* lengths,\n                                        const uint8_t* const* data) = 0;\n\n    ClientParams client;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/SMsgReader.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n\n#include <vector>\n\n#include <core/Configuration.h>\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rdr/InStream.h>\n#include <rdr/ZlibInStream.h>\n\n#include <rfb/msgTypes.h>\n#include <rfb/qemuTypes.h>\n#include <rfb/clipboardTypes.h>\n#include <rfb/Exception.h>\n#include <rfb/PixelFormat.h>\n#include <rfb/ScreenSet.h>\n#include <rfb/SMsgHandler.h>\n#include <rfb/SMsgReader.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"SMsgReader\");\n\nstatic core::IntParameter maxCutText(\"MaxCutText\",\n                                     \"Maximum permitted length of an \"\n                                     \"incoming clipboard update\",\n                                     256*1024, 0, INT_MAX);\n\nSMsgReader::SMsgReader(SMsgHandler* handler_, rdr::InStream* is_)\n  : handler(handler_), is(is_), state(MSGSTATE_IDLE)\n{\n}\n\nSMsgReader::~SMsgReader()\n{\n}\n\nbool SMsgReader::readClientInit()\n{\n  if (!is->hasData(1))\n    return false;\n  bool shared = is->readU8();\n  handler->clientInit(shared);\n  return true;\n}\n\nbool SMsgReader::readMsg()\n{\n  bool ret;\n\n  if (state == MSGSTATE_IDLE) {\n    if (!is->hasData(1))\n      return false;\n\n    currentMsgType = is->readU8();\n    state = MSGSTATE_MESSAGE;\n  }\n\n  switch (currentMsgType) {\n  case msgTypeSetPixelFormat:\n    ret = readSetPixelFormat();\n    break;\n  case msgTypeSetEncodings:\n    ret = readSetEncodings();\n    break;\n  case msgTypeSetDesktopSize:\n    ret = readSetDesktopSize();\n    break;\n  case msgTypeFramebufferUpdateRequest:\n    ret = readFramebufferUpdateRequest();\n    break;\n  case msgTypeEnableContinuousUpdates:\n    ret = readEnableContinuousUpdates();\n    break;\n  case msgTypeClientFence:\n    ret = readFence();\n    break;\n  case msgTypeKeyEvent:\n    ret = readKeyEvent();\n    break;\n  case msgTypePointerEvent:\n    ret = readPointerEvent();\n    break;\n  case msgTypeClientCutText:\n    ret = readClientCutText();\n    break;\n  case msgTypeQEMUClientMessage:\n    ret = readQEMUMessage();\n    break;\n  default:\n    vlog.error(\"Unknown message type %d\", currentMsgType);\n    throw protocol_error(\"Unknown message type\");\n  }\n\n  if (ret)\n    state = MSGSTATE_IDLE;\n\n  return ret;\n}\n\nbool SMsgReader::readSetPixelFormat()\n{\n  if (!is->hasData(3 + 16))\n    return false;\n  is->skip(3);\n  PixelFormat pf;\n  pf.read(is);\n  handler->setPixelFormat(pf);\n  return true;\n}\n\nbool SMsgReader::readSetEncodings()\n{\n  if (!is->hasData(1 + 2))\n    return false;\n\n  is->setRestorePoint();\n\n  is->skip(1);\n\n  int nEncodings = is->readU16();\n\n  if (!is->hasDataOrRestore(nEncodings * 4))\n    return false;\n  is->clearRestorePoint();\n\n  std::vector<int32_t> encodings(nEncodings);\n  for (size_t i = 0; i < encodings.size(); i++)\n    encodings[i] = is->readU32();\n\n  handler->setEncodings(nEncodings, encodings.data());\n\n  return true;\n}\n\nbool SMsgReader::readSetDesktopSize()\n{\n  int width, height;\n  int screens, i;\n  uint32_t id, flags;\n  int sx, sy, sw, sh;\n  ScreenSet layout;\n\n  if (!is->hasData(1 + 2 + 2 + 1 + 1))\n    return true;\n\n  is->setRestorePoint();\n\n  is->skip(1);\n\n  width = is->readU16();\n  height = is->readU16();\n\n  screens = is->readU8();\n  is->skip(1);\n\n  if (!is->hasDataOrRestore(screens * (4 + 2 + 2 + 2 + 2 + 4)))\n    return false;\n  is->clearRestorePoint();\n\n  for (i = 0;i < screens;i++) {\n    id = is->readU32();\n    sx = is->readU16();\n    sy = is->readU16();\n    sw = is->readU16();\n    sh = is->readU16();\n    flags = is->readU32();\n\n    layout.add_screen(Screen(id, sx, sy, sw, sh, flags));\n  }\n\n  handler->setDesktopSize(width, height, layout);\n\n  return true;\n}\n\nbool SMsgReader::readFramebufferUpdateRequest()\n{\n  if (!is->hasData(1 + 2 + 2 + 2 + 2))\n    return false;\n  bool inc = is->readU8();\n  int x = is->readU16();\n  int y = is->readU16();\n  int w = is->readU16();\n  int h = is->readU16();\n  handler->framebufferUpdateRequest({x, y, x+w, y+h}, inc);\n  return true;\n}\n\nbool SMsgReader::readEnableContinuousUpdates()\n{\n  bool enable;\n  int x, y, w, h;\n\n  if (!is->hasData(1 + 2 + 2 + 2 + 2))\n    return false;\n\n  enable = is->readU8();\n\n  x = is->readU16();\n  y = is->readU16();\n  w = is->readU16();\n  h = is->readU16();\n\n  handler->enableContinuousUpdates(enable, x, y, w, h);\n\n  return true;\n}\n\nbool SMsgReader::readFence()\n{\n  uint32_t flags;\n  uint8_t len;\n  uint8_t data[64];\n\n  if (!is->hasData(3 + 4 + 1))\n    return false;\n\n  is->setRestorePoint();\n\n  is->skip(3);\n\n  flags = is->readU32();\n\n  len = is->readU8();\n\n  if (!is->hasDataOrRestore(len))\n    return false;\n  is->clearRestorePoint();\n\n  if (len > sizeof(data)) {\n    vlog.error(\"Ignoring fence with too large payload\");\n    is->skip(len);\n    return true;\n  }\n\n  is->readBytes(data, len);\n  \n  handler->fence(flags, len, data);\n\n  return true;\n}\n\nbool SMsgReader::readKeyEvent()\n{\n  if (!is->hasData(1 + 2 + 4))\n    return false;\n  bool down = is->readU8();\n  is->skip(2);\n  uint32_t key = is->readU32();\n  handler->keyEvent(key, 0, down);\n  return true;\n}\n\nbool SMsgReader::readPointerEvent()\n{\n  int mask;\n  int x;\n  int y;\n\n  if (!is->hasData(1 + 2 + 2))\n    return false;\n\n  is->setRestorePoint();\n\n  mask = is->readU8();\n  x = is->readU16();\n  y = is->readU16();\n\n  if (handler->client.supportsExtendedMouseButtons() && mask & 0x80 ) {\n    int highBits;\n    int lowBits;\n\n    if (!is->hasDataOrRestore(1))\n      return false;\n\n    highBits = is->readU8();\n    lowBits = mask & 0x7f; /* Clear marker bit */\n    mask = (highBits << 7) | lowBits;\n  }\n\n  is->clearRestorePoint();\n  handler->pointerEvent({x, y}, mask);\n  return true;\n}\n\n\nbool SMsgReader::readClientCutText()\n{\n  if (!is->hasData(3 + 4))\n    return false;\n\n  is->setRestorePoint();\n\n  is->skip(3);\n  uint32_t len = is->readU32();\n\n  if (len & 0x80000000) {\n    int32_t slen = len;\n    slen = -slen;\n    if (readExtendedClipboard(slen)) {\n      is->clearRestorePoint();\n      return true;\n    } else {\n      is->gotoRestorePoint();\n      return false;\n    }\n  }\n\n  if (!is->hasDataOrRestore(len))\n    return false;\n  is->clearRestorePoint();\n\n  if (len > (size_t)maxCutText) {\n    is->skip(len);\n    vlog.error(\"Cut text too long (%d bytes) - ignoring\", len);\n    return true;\n  }\n\n  std::vector<char> ca(len);\n  is->readBytes((uint8_t*)ca.data(), len);\n\n  std::string utf8(core::latin1ToUTF8(ca.data(), ca.size()));\n  std::string filtered(core::convertLF(utf8.data(), utf8.size()));\n\n  handler->clientCutText(filtered.c_str());\n\n  return true;\n}\n\nbool SMsgReader::readExtendedClipboard(int32_t len)\n{\n  uint32_t flags;\n  uint32_t action;\n\n  if (!is->hasData(len))\n    return false;\n\n  if (len < 4)\n    throw protocol_error(\"Invalid extended clipboard message\");\n  if (len > maxCutText) {\n    vlog.error(\"Extended clipboard message too long (%d bytes) - ignoring\", len);\n    is->skip(len);\n    return true;\n  }\n\n  flags = is->readU32();\n  action = flags & clipboardActionMask;\n\n  if (action & clipboardCaps) {\n    int i;\n    size_t num;\n    uint32_t lengths[16];\n\n    num = 0;\n    for (i = 0;i < 16;i++) {\n      if (flags & (1 << i))\n        num++;\n    }\n\n    if (len < (int32_t)(4 + 4*num))\n      throw protocol_error(\"Invalid extended clipboard message\");\n\n    num = 0;\n    for (i = 0;i < 16;i++) {\n      if (flags & (1 << i))\n        lengths[num++] = is->readU32();\n    }\n\n    handler->handleClipboardCaps(flags, lengths);\n  } else if (action == clipboardProvide) {\n    rdr::ZlibInStream zis;\n\n    int i;\n    size_t num;\n    size_t lengths[16];\n    uint8_t* buffers[16];\n\n    zis.setUnderlying(is, len - 4);\n\n    num = 0;\n    for (i = 0;i < 16;i++) {\n      if (!(flags & 1 << i))\n        continue;\n\n      if (!zis.hasData(4))\n        throw protocol_error(\"Extended clipboard decode error\");\n\n      lengths[num] = zis.readU32();\n\n      if (lengths[num] > (size_t)maxCutText) {\n        vlog.error(\"Extended clipboard data too long (%d bytes) - ignoring\",\n                   (unsigned)lengths[num]);\n\n        // Slowly (safely) drain away the data\n        while (lengths[num] > 0) {\n          size_t chunk;\n\n          if (!zis.hasData(1))\n            throw protocol_error(\"Extended clipboard decode error\");\n\n          chunk = zis.avail();\n          if (chunk > lengths[num])\n            chunk = lengths[num];\n\n          zis.skip(chunk);\n          lengths[num] -= chunk;\n        }\n\n        flags &= ~(1 << i);\n\n        continue;\n      }\n\n      if (!zis.hasData(lengths[num]))\n        throw protocol_error(\"Extended clipboard decode error\");\n\n      buffers[num] = new uint8_t[lengths[num]];\n      zis.readBytes(buffers[num], lengths[num]);\n      num++;\n    }\n\n    zis.flushUnderlying();\n    zis.setUnderlying(nullptr, 0);\n\n    handler->handleClipboardProvide(flags, lengths, buffers);\n\n    num = 0;\n    for (i = 0;i < 16;i++) {\n      if (!(flags & 1 << i))\n        continue;\n      delete [] buffers[num++];\n    }\n  } else {\n    switch (action) {\n    case clipboardRequest:\n      handler->handleClipboardRequest(flags);\n      break;\n    case clipboardPeek:\n      handler->handleClipboardPeek();\n      break;\n    case clipboardNotify:\n      handler->handleClipboardNotify(flags);\n      break;\n    default:\n      throw protocol_error(\"Invalid extended clipboard action\");\n    }\n  }\n\n  return true;\n}\n\nbool SMsgReader::readQEMUMessage()\n{\n  int subType;\n  bool ret;\n\n  if (!is->hasData(1))\n    return false;\n\n  is->setRestorePoint();\n\n  subType = is->readU8();\n\n  switch (subType) {\n  case qemuExtendedKeyEvent:\n    ret = readQEMUKeyEvent();\n    break;\n  default:\n    throw protocol_error(core::format(\"Unknown QEMU submessage type %d\", subType));\n  }\n\n  if (!ret) {\n    is->gotoRestorePoint();\n    return false;\n  } else {\n    is->clearRestorePoint();\n    return true;\n  }\n}\n\nbool SMsgReader::readQEMUKeyEvent()\n{\n  if (!is->hasData(2 + 4 + 4))\n    return false;\n  bool down = is->readU16();\n  uint32_t keysym = is->readU32();\n  uint32_t keycode = is->readU32();\n  if (!keycode) {\n    vlog.error(\"Key event without keycode - ignoring\");\n    return true;\n  }\n  handler->keyEvent(keysym, keycode, down);\n  return true;\n}\n"
  },
  {
    "path": "common/rfb/SMsgReader.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// SMsgReader - class for reading RFB messages on the server side\n// (i.e. messages from client to server).\n//\n\n#ifndef __RFB_SMSGREADER_H__\n#define __RFB_SMSGREADER_H__\n\nnamespace rdr { class InStream; }\n\nnamespace rfb {\n  class SMsgHandler;\n\n  class SMsgReader {\n  public:\n    SMsgReader(SMsgHandler* handler, rdr::InStream* is);\n    virtual ~SMsgReader();\n\n    bool readClientInit();\n\n    // readMsg() reads a message, calling the handler as appropriate.\n    bool readMsg();\n\n    rdr::InStream* getInStream() { return is; }\n\n  protected:\n    bool readSetPixelFormat();\n    bool readSetEncodings();\n    bool readSetDesktopSize();\n\n    bool readFramebufferUpdateRequest();\n    bool readEnableContinuousUpdates();\n\n    bool readFence();\n\n    bool readKeyEvent();\n    bool readPointerEvent();\n    bool readClientCutText();\n    bool readExtendedClipboard(int32_t len);\n\n    bool readQEMUMessage();\n    bool readQEMUKeyEvent();\n\n  private:\n    SMsgHandler* handler;\n    rdr::InStream* is;\n\n    enum stateEnum {\n      MSGSTATE_IDLE,\n      MSGSTATE_MESSAGE,\n    };\n\n    stateEnum state;\n\n    uint8_t currentMsgType;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/SMsgWriter.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rdr/OutStream.h>\n#include <rdr/MemOutStream.h>\n#include <rdr/ZlibOutStream.h>\n\n#include <rfb/msgTypes.h>\n#include <rfb/fenceTypes.h>\n#include <rfb/clipboardTypes.h>\n#include <rfb/ClientParams.h>\n#include <rfb/Cursor.h>\n#include <rfb/UpdateTracker.h>\n#include <rfb/Encoder.h>\n#include <rfb/ScreenSet.h>\n#include <rfb/SMsgWriter.h>\n#include <rfb/encodings.h>\n#include <rfb/ledStates.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"SMsgWriter\");\n\nSMsgWriter::SMsgWriter(ClientParams* client_, rdr::OutStream* os_)\n  : client(client_), os(os_),\n    nRectsInUpdate(0), nRectsInHeader(0),\n    needSetDesktopName(false), needCursor(false),\n    needCursorPos(false), needLEDState(false),\n    needQEMUKeyEvent(false), needExtMouseButtonsEvent(false)\n{\n}\n\nSMsgWriter::~SMsgWriter()\n{\n}\n\nvoid SMsgWriter::writeServerInit(uint16_t width, uint16_t height,\n                                 const PixelFormat& pf, const char* name)\n{\n  os->writeU16(width);\n  os->writeU16(height);\n  pf.write(os);\n  os->writeU32(strlen(name));\n  os->writeBytes((const uint8_t*)name, strlen(name));\n  endMsg();\n}\n\nvoid SMsgWriter::writeSetColourMapEntries(int firstColour, int nColours,\n                                          const uint16_t red[],\n                                          const uint16_t green[],\n                                          const uint16_t blue[])\n{\n  startMsg(msgTypeSetColourMapEntries);\n  os->pad(1);\n  os->writeU16(firstColour);\n  os->writeU16(nColours);\n  for (int i = firstColour; i < firstColour+nColours; i++) {\n    os->writeU16(red[i]);\n    os->writeU16(green[i]);\n    os->writeU16(blue[i]);\n  }\n  endMsg();\n}\n\nvoid SMsgWriter::writeBell()\n{\n  startMsg(msgTypeBell);\n  endMsg();\n}\n\nvoid SMsgWriter::writeServerCutText(const char* str)\n{\n  if (strchr(str, '\\r') != nullptr)\n    throw std::invalid_argument(\"Invalid carriage return in clipboard data\");\n\n  std::string latin1(core::utf8ToLatin1(str));\n\n  startMsg(msgTypeServerCutText);\n  os->pad(3);\n  os->writeU32(latin1.size());\n  os->writeBytes((const uint8_t*)latin1.data(), latin1.size());\n  endMsg();\n}\n\nvoid SMsgWriter::writeClipboardCaps(uint32_t caps,\n                                    const uint32_t* lengths)\n{\n  size_t i, count;\n\n  if (!client->supportsEncoding(pseudoEncodingExtendedClipboard))\n    throw std::logic_error(\"Client does not support extended clipboard\");\n\n  count = 0;\n  for (i = 0;i < 16;i++) {\n    if (caps & (1 << i))\n      count++;\n  }\n\n  startMsg(msgTypeServerCutText);\n  os->pad(3);\n  os->writeS32(-(4 + 4 * count));\n\n  os->writeU32(caps | clipboardCaps);\n\n  count = 0;\n  for (i = 0;i < 16;i++) {\n    if (caps & (1 << i))\n      os->writeU32(lengths[count++]);\n  }\n\n  endMsg();\n}\n\nvoid SMsgWriter::writeClipboardRequest(uint32_t flags)\n{\n  if (!client->supportsEncoding(pseudoEncodingExtendedClipboard))\n    throw std::logic_error(\"Client does not support extended clipboard\");\n  if (!(client->clipboardFlags() & clipboardRequest))\n    throw std::logic_error(\"Client does not support clipboard \\\"request\\\" action\");\n\n  startMsg(msgTypeServerCutText);\n  os->pad(3);\n  os->writeS32(-4);\n  os->writeU32(flags | clipboardRequest);\n  endMsg();\n}\n\nvoid SMsgWriter::writeClipboardPeek(uint32_t flags)\n{\n  if (!client->supportsEncoding(pseudoEncodingExtendedClipboard))\n    throw std::logic_error(\"Client does not support extended clipboard\");\n  if (!(client->clipboardFlags() & clipboardPeek))\n    throw std::logic_error(\"Client does not support clipboard \\\"peek\\\" action\");\n\n  startMsg(msgTypeServerCutText);\n  os->pad(3);\n  os->writeS32(-4);\n  os->writeU32(flags | clipboardPeek);\n  endMsg();\n}\n\nvoid SMsgWriter::writeClipboardNotify(uint32_t flags)\n{\n  if (!client->supportsEncoding(pseudoEncodingExtendedClipboard))\n    throw std::logic_error(\"Client does not support extended clipboard\");\n  if (!(client->clipboardFlags() & clipboardNotify))\n    throw std::logic_error(\"Client does not support clipboard \\\"notify\\\" action\");\n\n  startMsg(msgTypeServerCutText);\n  os->pad(3);\n  os->writeS32(-4);\n  os->writeU32(flags | clipboardNotify);\n  endMsg();\n}\n\nvoid SMsgWriter::writeClipboardProvide(uint32_t flags,\n                                      const size_t* lengths,\n                                      const uint8_t* const* data)\n{\n  rdr::MemOutStream mos;\n  rdr::ZlibOutStream zos;\n\n  int i, count;\n\n  if (!client->supportsEncoding(pseudoEncodingExtendedClipboard))\n    throw std::logic_error(\"Client does not support extended clipboard\");\n  if (!(client->clipboardFlags() & clipboardProvide))\n    throw std::logic_error(\"Client does not support clipboard \\\"provide\\\" action\");\n\n  zos.setUnderlying(&mos);\n\n  count = 0;\n  for (i = 0;i < 16;i++) {\n    if (!(flags & (1 << i)))\n      continue;\n    zos.writeU32(lengths[count]);\n    zos.writeBytes(data[count], lengths[count]);\n    count++;\n  }\n\n  zos.flush();\n\n  startMsg(msgTypeServerCutText);\n  os->pad(3);\n  os->writeS32(-(4 + mos.length()));\n  os->writeU32(flags | clipboardProvide);\n  os->writeBytes(mos.data(), mos.length());\n  endMsg();\n}\n\nvoid SMsgWriter::writeFence(uint32_t flags, unsigned len,\n                            const uint8_t data[])\n{\n  if (!client->supportsEncoding(pseudoEncodingFence))\n    throw std::logic_error(\"Client does not support fences\");\n  if (len > 64)\n    throw std::out_of_range(\"Too large fence payload\");\n  if ((flags & ~fenceFlagsSupported) != 0)\n    throw std::invalid_argument(\"Unknown fence flags\");\n\n  startMsg(msgTypeServerFence);\n  os->pad(3);\n\n  os->writeU32(flags);\n\n  os->writeU8(len);\n\n  if (len > 0)\n    os->writeBytes(data, len);\n\n  endMsg();\n}\n\nvoid SMsgWriter::writeEndOfContinuousUpdates()\n{\n  if (!client->supportsEncoding(pseudoEncodingContinuousUpdates))\n    throw std::logic_error(\"Client does not support continuous updates\");\n\n  startMsg(msgTypeEndOfContinuousUpdates);\n  endMsg();\n}\n\nvoid SMsgWriter::writeDesktopSize(uint16_t reason, uint16_t result)\n{\n  ExtendedDesktopSizeMsg msg;\n\n  if (!client->supportsEncoding(pseudoEncodingDesktopSize) &&\n      !client->supportsEncoding(pseudoEncodingExtendedDesktopSize))\n    throw std::logic_error(\"Client does not support desktop size changes\");\n\n  msg.reason = reason;\n  msg.result = result;\n\n  extendedDesktopSizeMsgs.push_back(msg);\n}\n\nvoid SMsgWriter::writeSetDesktopName()\n{\n  if (!client->supportsEncoding(pseudoEncodingDesktopName))\n    throw std::logic_error(\"Client does not support desktop name changes\");\n\n  needSetDesktopName = true;\n}\n\nvoid SMsgWriter::writeCursor()\n{\n  if (!client->supportsEncoding(pseudoEncodingCursor) &&\n      !client->supportsEncoding(pseudoEncodingXCursor) &&\n      !client->supportsEncoding(pseudoEncodingCursorWithAlpha) &&\n      !client->supportsEncoding(pseudoEncodingVMwareCursor))\n    throw std::logic_error(\"Client does not support local cursor\");\n\n  needCursor = true;\n}\n\nvoid SMsgWriter::writeCursorPos()\n{\n  if (!client->supportsEncoding(pseudoEncodingVMwareCursorPosition))\n    throw std::logic_error(\"Client does not support cursor position\");\n\n  needCursorPos = true;\n}\n\nvoid SMsgWriter::writeLEDState()\n{\n  if (!client->supportsEncoding(pseudoEncodingLEDState) &&\n      !client->supportsEncoding(pseudoEncodingVMwareLEDState))\n    throw std::logic_error(\"Client does not support LED state\");\n  if (client->ledState() == ledUnknown)\n    throw std::logic_error(\"Server has not specified LED state\");\n\n  needLEDState = true;\n}\n\nvoid SMsgWriter::writeQEMUKeyEvent()\n{\n  if (!client->supportsEncoding(pseudoEncodingQEMUKeyEvent))\n    throw std::logic_error(\"Client does not support QEMU key events\");\n\n  needQEMUKeyEvent = true;\n}\n\nvoid SMsgWriter::writeExtendedMouseButtonsSupport()\n{\n  if (!client->supportsEncoding(pseudoEncodingExtendedMouseButtons))\n    throw std::logic_error(\"Client does not support Extended Mouse Buttons\");\n\n  needExtMouseButtonsEvent = true;\n}\n\nbool SMsgWriter::needFakeUpdate()\n{\n  if (needSetDesktopName)\n    return true;\n  if (needCursor)\n    return true;\n  if (needCursorPos)\n    return true;\n  if (needLEDState)\n    return true;\n  if (needQEMUKeyEvent)\n    return true;\n  if (needExtMouseButtonsEvent)\n    return true;\n  if (needNoDataUpdate())\n    return true;\n\n  return false;\n}\n\nbool SMsgWriter::needNoDataUpdate()\n{\n  if (!extendedDesktopSizeMsgs.empty())\n    return true;\n\n  return false;\n}\n\nvoid SMsgWriter::writeNoDataUpdate()\n{\n  int nRects;\n\n  nRects = 0;\n\n  if (!extendedDesktopSizeMsgs.empty()) {\n    if (client->supportsEncoding(pseudoEncodingExtendedDesktopSize))\n      nRects += extendedDesktopSizeMsgs.size();\n    else\n      nRects++;\n  }\n\n  writeFramebufferUpdateStart(nRects);\n  writeNoDataRects();\n  writeFramebufferUpdateEnd();\n}\n\nvoid SMsgWriter::writeFramebufferUpdateStart(int nRects)\n{\n  startMsg(msgTypeFramebufferUpdate);\n  os->pad(1);\n\n  if (nRects != 0xFFFF) {\n    if (needSetDesktopName)\n      nRects++;\n    if (needCursor)\n      nRects++;\n    if (needCursorPos)\n      nRects++;\n    if (needLEDState)\n      nRects++;\n    if (needQEMUKeyEvent)\n      nRects++;\n    if (needExtMouseButtonsEvent)\n      nRects++;\n  }\n\n  os->writeU16(nRects);\n\n  nRectsInUpdate = 0;\n  if (nRects == 0xFFFF)\n    nRectsInHeader = 0;\n  else\n    nRectsInHeader = nRects;\n\n  writePseudoRects();\n}\n\nvoid SMsgWriter::writeFramebufferUpdateEnd()\n{\n  if (nRectsInUpdate != nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeFramebufferUpdateEnd: \"\n                           \"nRects out of sync\");\n\n  if (nRectsInHeader == 0) {\n    // Send last rect. marker\n    os->writeS16(0);\n    os->writeS16(0);\n    os->writeU16(0);\n    os->writeU16(0);\n    os->writeU32(pseudoEncodingLastRect);\n  }\n\n  endMsg();\n}\n\nvoid SMsgWriter::writeCopyRect(const core::Rect& r, int srcX, int srcY)\n{\n  startRect(r,encodingCopyRect);\n  os->writeU16(srcX);\n  os->writeU16(srcY);\n  endRect();\n}\n\nvoid SMsgWriter::startRect(const core::Rect& r, int encoding)\n{\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::startRect: nRects out of sync\");\n\n  os->writeS16(r.tl.x);\n  os->writeS16(r.tl.y);\n  os->writeU16(r.width());\n  os->writeU16(r.height());\n  os->writeU32(encoding);\n}\n\nvoid SMsgWriter::endRect()\n{\n  os->flush();\n}\n\nvoid SMsgWriter::startMsg(int type)\n{\n  os->writeU8(type);\n}\n\nvoid SMsgWriter::endMsg()\n{\n  os->flush();\n}\n\nvoid SMsgWriter::writePseudoRects()\n{\n  if (needCursor) {\n    const Cursor& cursor = client->cursor();\n\n    if (client->supportsEncoding(pseudoEncodingCursorWithAlpha)) {\n      writeSetCursorWithAlphaRect(cursor.width(), cursor.height(),\n                                  cursor.hotspot().x, cursor.hotspot().y,\n                                  cursor.getBuffer());\n    } else if (client->supportsEncoding(pseudoEncodingVMwareCursor)) {\n      writeSetVMwareCursorRect(cursor.width(), cursor.height(),\n                               cursor.hotspot().x, cursor.hotspot().y,\n                               cursor.getBuffer());\n    } else if (client->supportsEncoding(pseudoEncodingCursor)) {\n      size_t data_len = cursor.width()*cursor.height() *\n                        (client->pf().bpp/8);\n      std::vector<uint8_t> data(data_len);\n      std::vector<uint8_t> mask(cursor.getMask());\n\n      const uint8_t* in;\n      uint8_t* out;\n\n      in = cursor.getBuffer();\n      out = data.data();\n      for (int i = 0;i < cursor.width()*cursor.height();i++) {\n        client->pf().bufferFromRGB(out, in, 1);\n        in += 4;\n        out += client->pf().bpp/8;\n      }\n\n      writeSetCursorRect(cursor.width(), cursor.height(),\n                         cursor.hotspot().x, cursor.hotspot().y,\n                         data.data(), mask.data());\n    } else if (client->supportsEncoding(pseudoEncodingXCursor)) {\n      std::vector<uint8_t> bitmap(cursor.getBitmap());\n      std::vector<uint8_t> mask(cursor.getMask());\n\n      writeSetXCursorRect(cursor.width(), cursor.height(),\n                          cursor.hotspot().x, cursor.hotspot().y,\n                          bitmap.data(), mask.data());\n    } else {\n      throw std::logic_error(\"Client does not support local cursor\");\n    }\n\n    needCursor = false;\n  }\n\n  if (needCursorPos) {\n    const core::Point& cursorPos = client->cursorPos();\n\n    if (client->supportsEncoding(pseudoEncodingVMwareCursorPosition)) {\n      writeSetVMwareCursorPositionRect(cursorPos.x, cursorPos.y);\n    } else {\n      throw std::logic_error(\"Client does not support cursor position\");\n    }\n\n    needCursorPos = false;\n  }\n\n  if (needSetDesktopName) {\n    writeSetDesktopNameRect(client->name());\n    needSetDesktopName = false;\n  }\n\n  if (needLEDState) {\n    writeLEDStateRect(client->ledState());\n    needLEDState = false;\n  }\n\n  if (needQEMUKeyEvent) {\n    writeQEMUKeyEventRect();\n    needQEMUKeyEvent = false;\n  }\n\n  if (needExtMouseButtonsEvent) {\n    writeExtendedMouseButtonsRect();\n    needExtMouseButtonsEvent = false;\n  }\n}\n\nvoid SMsgWriter::writeNoDataRects()\n{\n  if (!extendedDesktopSizeMsgs.empty()) {\n    if (client->supportsEncoding(pseudoEncodingExtendedDesktopSize)) {\n      for (ExtendedDesktopSizeMsg msg : extendedDesktopSizeMsgs) {\n        // FIXME: We can probably skip multiple reasonServer entries\n        writeExtendedDesktopSizeRect(msg.reason, msg.result,\n                                     client->width(), client->height(),\n                                     client->screenLayout());\n      }\n    } else if (client->supportsEncoding(pseudoEncodingDesktopSize)) {\n      // Some clients assume this is the last rectangle so don't send anything\n      // more after this\n      writeSetDesktopSizeRect(client->width(), client->height());\n    } else {\n      throw std::logic_error(\"Client does not support desktop size changes\");\n    }\n\n    extendedDesktopSizeMsgs.clear();\n  }\n}\n\nvoid SMsgWriter::writeSetDesktopSizeRect(int width, int height)\n{\n  if (!client->supportsEncoding(pseudoEncodingDesktopSize))\n    throw std::logic_error(\"Client does not support desktop resize\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeSetDesktopSizeRect: nRects out of sync\");\n\n  os->writeS16(0);\n  os->writeS16(0);\n  os->writeU16(width);\n  os->writeU16(height);\n  os->writeU32(pseudoEncodingDesktopSize);\n}\n\nvoid SMsgWriter::writeExtendedDesktopSizeRect(uint16_t reason,\n                                              uint16_t result,\n                                              int fb_width,\n                                              int fb_height,\n                                              const ScreenSet& layout)\n{\n  ScreenSet::const_iterator si;\n\n  if (!client->supportsEncoding(pseudoEncodingExtendedDesktopSize))\n    throw std::logic_error(\"Client does not support extended desktop resize\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeExtendedDesktopSizeRect: nRects out of sync\");\n\n  os->writeU16(reason);\n  os->writeU16(result);\n  os->writeU16(fb_width);\n  os->writeU16(fb_height);\n  os->writeU32(pseudoEncodingExtendedDesktopSize);\n\n  os->writeU8(layout.num_screens());\n  os->pad(3);\n\n  for (si = layout.begin();si != layout.end();++si) {\n    os->writeU32(si->id);\n    os->writeU16(si->dimensions.tl.x);\n    os->writeU16(si->dimensions.tl.y);\n    os->writeU16(si->dimensions.width());\n    os->writeU16(si->dimensions.height());\n    os->writeU32(si->flags);\n  }\n}\n\nvoid SMsgWriter::writeSetDesktopNameRect(const char *name)\n{\n  if (!client->supportsEncoding(pseudoEncodingDesktopName))\n    throw std::logic_error(\"Client does not support desktop rename\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeSetDesktopNameRect: nRects out of sync\");\n\n  os->writeS16(0);\n  os->writeS16(0);\n  os->writeU16(0);\n  os->writeU16(0);\n  os->writeU32(pseudoEncodingDesktopName);\n  os->writeU32(strlen(name));\n  os->writeBytes((const uint8_t*)name, strlen(name));\n}\n\nvoid SMsgWriter::writeSetCursorRect(int width, int height,\n                                    int hotspotX, int hotspotY,\n                                    const uint8_t* data,\n                                    const uint8_t* mask)\n{\n  if (!client->supportsEncoding(pseudoEncodingCursor))\n    throw std::logic_error(\"Client does not support local cursors\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeSetCursorRect: nRects out of sync\");\n\n  os->writeS16(hotspotX);\n  os->writeS16(hotspotY);\n  os->writeU16(width);\n  os->writeU16(height);\n  os->writeU32(pseudoEncodingCursor);\n  os->writeBytes(data, width * height * (client->pf().bpp/8));\n  os->writeBytes(mask, (width+7)/8 * height);\n}\n\nvoid SMsgWriter::writeSetXCursorRect(int width, int height,\n                                     int hotspotX, int hotspotY,\n                                     const uint8_t* data,\n                                     const uint8_t* mask)\n{\n  if (!client->supportsEncoding(pseudoEncodingXCursor))\n    throw std::logic_error(\"Client does not support local cursors\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeSetXCursorRect: nRects out of sync\");\n\n  os->writeS16(hotspotX);\n  os->writeS16(hotspotY);\n  os->writeU16(width);\n  os->writeU16(height);\n  os->writeU32(pseudoEncodingXCursor);\n  if (width * height > 0) {\n    os->writeU8(255);\n    os->writeU8(255);\n    os->writeU8(255);\n    os->writeU8(0);\n    os->writeU8(0);\n    os->writeU8(0);\n    os->writeBytes(data, (width+7)/8 * height);\n    os->writeBytes(mask, (width+7)/8 * height);\n  }\n}\n\nvoid SMsgWriter::writeSetCursorWithAlphaRect(int width, int height,\n                                             int hotspotX, int hotspotY,\n                                             const uint8_t* data)\n{\n  if (!client->supportsEncoding(pseudoEncodingCursorWithAlpha))\n    throw std::logic_error(\"Client does not support local cursors\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeSetCursorWithAlphaRect: nRects out of sync\");\n\n  os->writeS16(hotspotX);\n  os->writeS16(hotspotY);\n  os->writeU16(width);\n  os->writeU16(height);\n  os->writeU32(pseudoEncodingCursorWithAlpha);\n\n  // FIXME: Use an encoder with compression?\n  os->writeU32(encodingRaw);\n\n  // Alpha needs to be pre-multiplied\n  for (int i = 0;i < width*height;i++) {\n    os->writeU8((unsigned)data[0] * data[3] / 255);\n    os->writeU8((unsigned)data[1] * data[3] / 255);\n    os->writeU8((unsigned)data[2] * data[3] / 255);\n    os->writeU8(data[3]);\n    data += 4;\n  }\n}\n\nvoid SMsgWriter::writeSetVMwareCursorRect(int width, int height,\n                                          int hotspotX, int hotspotY,\n                                          const uint8_t* data)\n{\n  if (!client->supportsEncoding(pseudoEncodingVMwareCursor))\n    throw std::logic_error(\"Client does not support local cursors\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeSetVMwareCursorRect: nRects out of sync\");\n\n  os->writeS16(hotspotX);\n  os->writeS16(hotspotY);\n  os->writeU16(width);\n  os->writeU16(height);\n  os->writeU32(pseudoEncodingVMwareCursor);\n\n  os->writeU8(1); // Alpha cursor\n  os->pad(1);\n\n  // FIXME: Should alpha be premultiplied?\n  os->writeBytes(data, width*height*4);\n}\n\nvoid SMsgWriter::writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY)\n{\n  if (!client->supportsEncoding(pseudoEncodingVMwareCursorPosition))\n    throw std::logic_error(\"Client does not support cursor position\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeSetVMwareCursorRect: nRects out of sync\");\n\n  os->writeS16(hotspotX);\n  os->writeS16(hotspotY);\n  os->writeU16(0);\n  os->writeU16(0);\n  os->writeU32(pseudoEncodingVMwareCursorPosition);\n}\n\nvoid SMsgWriter::writeLEDStateRect(uint8_t state)\n{\n  if (!client->supportsEncoding(pseudoEncodingLEDState) &&\n      !client->supportsEncoding(pseudoEncodingVMwareLEDState))\n    throw std::logic_error(\"Client does not support LED state updates\");\n  if (client->ledState() == ledUnknown)\n    throw std::logic_error(\"Server does not support LED state updates\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeLEDStateRect: nRects out of sync\");\n\n  os->writeS16(0);\n  os->writeS16(0);\n  os->writeU16(0);\n  os->writeU16(0);\n  if (client->supportsEncoding(pseudoEncodingLEDState)) {\n    os->writeU32(pseudoEncodingLEDState);\n    os->writeU8(state);\n  } else {\n    os->writeU32(pseudoEncodingVMwareLEDState);\n    os->writeU32(state);\n  }\n}\n\nvoid SMsgWriter::writeQEMUKeyEventRect()\n{\n  if (!client->supportsEncoding(pseudoEncodingQEMUKeyEvent))\n    throw std::logic_error(\"Client does not support QEMU extended key events\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeQEMUKeyEventRect: nRects out of sync\");\n\n  os->writeS16(0);\n  os->writeS16(0);\n  os->writeU16(0);\n  os->writeU16(0);\n  os->writeU32(pseudoEncodingQEMUKeyEvent);\n}\n\nvoid SMsgWriter::writeExtendedMouseButtonsRect()\n{\n  if (!client->supportsEncoding(pseudoEncodingExtendedMouseButtons))\n    throw std::logic_error(\"Client does not support extended mouse button events\");\n  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)\n    throw std::logic_error(\"SMsgWriter::writeExtendedMouseButtonsRect: nRects out of sync\");\n\n  os->writeS16(0);\n  os->writeS16(0);\n  os->writeU16(0);\n  os->writeU16(0);\n  os->writeU32(pseudoEncodingExtendedMouseButtons);\n}\n"
  },
  {
    "path": "common/rfb/SMsgWriter.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// SMsgWriter - class for writing RFB messages on the server side.\n//\n\n#ifndef __RFB_SMSGWRITER_H__\n#define __RFB_SMSGWRITER_H__\n\n#include <stdint.h>\n\nnamespace core { struct Rect; }\n\nnamespace rdr { class OutStream; }\n\nnamespace rfb {\n\n  class ClientParams;\n  class PixelFormat;\n  struct ScreenSet;\n\n  class SMsgWriter {\n  public:\n    SMsgWriter(ClientParams* client, rdr::OutStream* os);\n    virtual ~SMsgWriter();\n\n    // writeServerInit() must only be called at the appropriate time in the\n    // protocol initialisation.\n    void writeServerInit(uint16_t width, uint16_t height,\n                         const PixelFormat& pf, const char* name);\n\n    // Methods to write normal protocol messages\n\n    // writeSetColourMapEntries() writes a setColourMapEntries message, using\n    // the given colour entries.\n    void writeSetColourMapEntries(int firstColour, int nColours,\n                                  const uint16_t red[],\n                                  const uint16_t green[],\n                                  const uint16_t blue[]);\n\n    // writeBell() does the obvious thing.\n    void writeBell();\n\n    void writeServerCutText(const char* str);\n\n    void writeClipboardCaps(uint32_t caps, const uint32_t* lengths);\n    void writeClipboardRequest(uint32_t flags);\n    void writeClipboardPeek(uint32_t flags);\n    void writeClipboardNotify(uint32_t flags);\n    void writeClipboardProvide(uint32_t flags, const size_t* lengths,\n                               const uint8_t* const* data);\n\n    // writeFence() sends a new fence request or response to the client.\n    void writeFence(uint32_t flags, unsigned len, const uint8_t data[]);\n\n    // writeEndOfContinuousUpdates() indicates that we have left continuous\n    // updates mode.\n    void writeEndOfContinuousUpdates();\n\n    // writeDesktopSize() won't actually write immediately, but will\n    // write the relevant pseudo-rectangle as part of the next update.\n    void writeDesktopSize(uint16_t reason, uint16_t result=0);\n\n    void writeSetDesktopName();\n\n    // Like setDesktopSize, we can't just write out a cursor message\n    // immediately. \n    void writeCursor();\n\n    // Notifies the client that the cursor pointer was moved by the server.\n    void writeCursorPos();\n\n    // Same for LED state message\n    void writeLEDState();\n\n    // And QEMU keyboard event handshake\n    void writeQEMUKeyEvent();\n\n    // let the client know we support extended mouse button support\n    void writeExtendedMouseButtonsSupport();\n\n    // needFakeUpdate() returns true when an immediate update is needed in\n    // order to flush out pseudo-rectangles to the client.\n    bool needFakeUpdate();\n\n    // needNoDataUpdate() returns true when an update without any\n    // framebuffer changes need to be sent (using writeNoDataUpdate()).\n    // Commonly this is an update that modifies the size of the framebuffer\n    // or the screen layout.\n    bool needNoDataUpdate();\n\n    // writeNoDataUpdate() write a framebuffer update containing only\n    // pseudo-rectangles.\n    void writeNoDataUpdate();\n\n    // writeFramebufferUpdateStart() initiates an update which you can fill\n    // in using writeCopyRect() and encoders. Finishing the update by calling\n    // writeFramebufferUpdateEnd().\n    void writeFramebufferUpdateStart(int nRects);\n    void writeFramebufferUpdateEnd();\n\n    // There is no explicit encoder for CopyRect rects.\n    void writeCopyRect(const core::Rect& r, int srcX, int srcY);\n\n    // Encoders should call these to mark the start and stop of individual\n    // rects.\n    void startRect(const core::Rect& r, int enc);\n    void endRect();\n\n  protected:\n    void startMsg(int type);\n    void endMsg();\n\n    void writePseudoRects();\n    void writeNoDataRects();\n\n    void writeSetDesktopSizeRect(int width, int height);\n    void writeExtendedDesktopSizeRect(uint16_t reason, uint16_t result,\n                                      int fb_width, int fb_height,\n                                      const ScreenSet& layout);\n    void writeSetDesktopNameRect(const char *name);\n    void writeSetCursorRect(int width, int height,\n                            int hotspotX, int hotspotY,\n                            const uint8_t* data, const uint8_t* mask);\n    void writeSetXCursorRect(int width, int height,\n                             int hotspotX, int hotspotY,\n                             const uint8_t* data, const uint8_t* mask);\n    void writeSetCursorWithAlphaRect(int width, int height,\n                                     int hotspotX, int hotspotY,\n                                     const uint8_t* data);\n    void writeSetVMwareCursorRect(int width, int height,\n                                  int hotspotX, int hotspotY,\n                                  const uint8_t* data);\n    void writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY);\n    void writeLEDStateRect(uint8_t state);\n    void writeQEMUKeyEventRect();\n    void writeExtendedMouseButtonsRect();\n\n    ClientParams* client;\n    rdr::OutStream* os;\n\n    int nRectsInUpdate;\n    int nRectsInHeader;\n\n    bool needSetDesktopName;\n    bool needCursor;\n    bool needCursorPos;\n    bool needLEDState;\n    bool needQEMUKeyEvent;\n    bool needExtMouseButtonsEvent;\n\n    typedef struct {\n      uint16_t reason, result;\n    } ExtendedDesktopSizeMsg;\n\n    std::list<ExtendedDesktopSizeMsg> extendedDesktopSizeMsgs;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/SSecurity.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// SSecurity - class on the server side for handling security handshaking.  A\n// derived class for a particular security type overrides the processMsg()\n// method.\n\n// processMsg() is called first when the security type has been decided\n// on, and will keep being called whenever there is data to read from\n// the client.  It should return false when it needs more data, or true\n// when the connection has been successfully authenticated.  In the\n// event of authentication failure an auth_error should be thrown - this\n// will result in a \"failed\" security result being sent to the client\n// with the str() from the exception being sent as the reason.  Any\n// other type of failure should be indicated by some other kind of\n// exception which will cause the connection to be aborted.\n//\n// processMsg() must never block (or at least must never block until the client\n// has been authenticated) - this is to prevent denial of service attacks.\n// Note that the first time processMsg() is called, there is no guarantee that\n// there is any data to read from the SConnection's InStream, but subsequent\n// calls guarantee there is at least one byte which can be read without\n// blocking.\n//\n// getType() should return the secType value corresponding to the SSecurity\n// implementation.\n//\n\n#ifndef __RFB_SSECURITY_H__\n#define __RFB_SSECURITY_H__\n\n#include <rfb/AccessRights.h>\n\nnamespace rfb {\n\n  class SConnection;\n\n  class SSecurity {\n  public:\n    SSecurity(SConnection* sc_) : sc(sc_) {}\n    virtual ~SSecurity() {}\n    virtual bool processMsg() = 0;\n    virtual int getType() const = 0;\n\n    // getUserName() gets the name of the user attempting authentication.  The\n    // storage is owned by the SSecurity object, so a copy must be taken if\n    // necessary.  Null may be returned to indicate that there is no user name\n    // for this security type.\n    virtual const char* getUserName() const = 0;\n\n    virtual AccessRights getAccessRights() const { return AccessDefault; }\n\n  protected:\n    SConnection* sc;\n  };\n\n}\n#endif\n"
  },
  {
    "path": "common/rfb/SSecurityNone.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// SSecurityNone.h\n//\n\n#ifndef __SSECURITYNONE_H__\n#define __SSECURITYNONE_H__\n\n#include <rfb/SSecurity.h>\n\nnamespace rfb {\n\n  class SSecurityNone : public SSecurity {\n  public:\n    SSecurityNone(SConnection* sc_) : SSecurity(sc_) {}\n    bool processMsg() override { return true; }\n    int getType() const override {return secTypeNone;}\n    const char* getUserName() const override {return nullptr;}\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/SSecurityPlain.cxx",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Configuration.h>\n#include <core/string.h>\n\n#include <rfb/SSecurityPlain.h>\n#include <rfb/SConnection.h>\n#include <rfb/Exception.h>\n#include <rdr/InStream.h>\n#if !defined(WIN32) && !defined(__APPLE__)\n#include <rfb/UnixPasswordValidator.h>\n#include <unistd.h>\n#include <pwd.h>\n#endif\n#ifdef WIN32\n#include <rfb/WinPasswdValidator.h>\n#endif\n\nusing namespace rfb;\n\ncore::StringListParameter PasswordValidator::plainUsers\n(\"PlainUsers\",\n \"Users permitted to access via Plain security type (including TLSPlain, X509Plain etc.)\"\n#ifdef HAVE_NETTLE\n \" or RSA-AES security types (RA2, RA2ne, RA2_256, RA2ne_256)\"\n#endif\n ,\n {});\n\nbool PasswordValidator::validUser(const char* username)\n{\n  for (const char* user : plainUsers) {\n    if (strcmp(user, \"*\") == 0)\n      return true;\n#if !defined(WIN32) && !defined(__APPLE__)\n    if (strcmp(user, \"%u\") == 0) {\n      struct passwd *pw = getpwnam(username);\n      if (pw && pw->pw_uid == getuid())\n        return true;\n    }\n#endif\n    // FIXME: We should compare uid, as the usernames might not be case\n    //        sensitive, or have other normalisation\n    if (strcmp(user, username) == 0)\n      return true;\n  }\n  return false;\n}\n\nSSecurityPlain::SSecurityPlain(SConnection* sc_) : SSecurity(sc_)\n{\n#ifdef WIN32\n  valid = new WinPasswdValidator();\n#elif !defined(__APPLE__)\n  valid = new UnixPasswordValidator();\n#else\n  valid = nullptr;\n#endif\n\n  state = 0;\n}\n\nbool SSecurityPlain::processMsg()\n{\n  rdr::InStream* is = sc->getInStream();\n  char password[1024];\n\n  if (!valid)\n    throw std::logic_error(\"No password validator configured\");\n\n  if (state == 0) {\n    if (!is->hasData(8))\n      return false;\n\n    ulen = is->readU32();\n    if (ulen >= sizeof(username))\n      throw auth_error(\"Too long username\");\n\n    plen = is->readU32();\n    if (plen >= sizeof(password))\n      throw auth_error(\"Too long password\");\n\n    state = 1;\n  }\n\n  if (state == 1) {\n    if (!is->hasData(ulen + plen))\n      return false;\n    state = 2;\n    is->readBytes((uint8_t*)username, ulen);\n    is->readBytes((uint8_t*)password, plen);\n    password[plen] = 0;\n    username[ulen] = 0;\n    plen = 0;\n    std::string msg = \"Authentication failed\";\n    if (!valid->validate(sc, username, password, msg))\n      throw auth_error(msg);\n  }\n\n  return true;\n}\n\n"
  },
  {
    "path": "common/rfb/SSecurityPlain.h",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_SSECURITYPLAIN_H__\n#define __RFB_SSECURITYPLAIN_H__\n\n#include <rfb/Security.h>\n#include <rfb/SSecurity.h>\n\nnamespace core { class StringListParameter; }\n\nnamespace rfb {\n\n  class PasswordValidator {\n  public:\n    bool validate(SConnection* sc,\n                  const char *username,\n                  const char *password,\n                  std::string &msg)\n      { return validUser(username) ? validateInternal(sc, username, password, msg) : false; }\n    static core::StringListParameter plainUsers;\n\n    virtual ~PasswordValidator() { }\n\n  protected:\n    virtual bool validateInternal(SConnection* sc,\n                                  const char *username,\n                                  const char *password,\n                                  std::string &msg) = 0;\n    static bool validUser(const char* username);\n  };\n\n  class SSecurityPlain : public SSecurity {\n  public:\n    SSecurityPlain(SConnection* sc);\n    bool processMsg() override;\n    int getType() const override { return secTypePlain; };\n    const char* getUserName() const override { return username; }\n\n    virtual ~SSecurityPlain() { }\n\n  private:\n    PasswordValidator* valid;\n    unsigned int ulen, plen, state;\n    char username[1024];\n  };\n\n}\n#endif\n\n"
  },
  {
    "path": "common/rfb/SSecurityRSAAES.cxx",
    "content": "/* Copyright (C) 2022 Dinglan Peng\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#ifndef HAVE_NETTLE\n#error \"This source should not be compiled without HAVE_NETTLE defined\"\n#endif\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n\n#include <vector>\n\n#include <nettle/bignum.h>\n#include <nettle/sha1.h>\n#include <nettle/sha2.h>\n#include <nettle/base64.h>\n#include <nettle/asn1.h>\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rdr/AESInStream.h>\n#include <rdr/AESOutStream.h>\n#include <rdr/RandomStream.h>\n\n#include <rfb/SSecurityRSAAES.h>\n#include <rfb/SConnection.h>\n#include <rfb/Exception.h>\n#if !defined(WIN32) && !defined(__APPLE__)\n#include <rfb/UnixPasswordValidator.h>\n#endif\n#ifdef WIN32\n#include <rfb/WinPasswdValidator.h>\n#endif\n#include <rfb/SSecurityVncAuth.h>\n\nenum {\n  SendPublicKey,\n  ReadPublicKey,\n  ReadRandom,\n  ReadHash,\n  ReadCredentials,\n};\n\nconst int MinKeyLength = 1024;\nconst int MaxKeyLength = 8192;\nconst size_t MaxKeyFileSize = 32 * 1024;\n\nusing namespace rfb;\n\ncore::StringParameter SSecurityRSAAES::keyFile\n(\"RSAKey\", \"Path to the RSA key for the RSA-AES security types in \"\n           \"PEM format\", \"\");\ncore::BoolParameter SSecurityRSAAES::requireUsername\n(\"RequireUsername\", \"Require username for the RSA-AES security types\",\n false);\n\nstatic core::LogWriter vlog(\"SSecurityRSAAES\");\n\nSSecurityRSAAES::SSecurityRSAAES(SConnection* sc_, uint32_t _secType,\n                                 int _keySize, bool _isAllEncrypted)\n  : SSecurity(sc_), state(SendPublicKey),\n    keySize(_keySize), isAllEncrypted(_isAllEncrypted), secType(_secType),\n    serverKey(), clientKey(),\n    serverKeyN(nullptr), serverKeyE(nullptr),\n    clientKeyN(nullptr), clientKeyE(nullptr),\n    accessRights(AccessDefault),\n    rais(nullptr), raos(nullptr), rawis(nullptr), rawos(nullptr)\n{\n  assert(keySize == 128 || keySize == 256);\n}\n\nSSecurityRSAAES::~SSecurityRSAAES()\n{\n  cleanup();\n}\n\nvoid SSecurityRSAAES::cleanup()\n{\n  if (raos) {\n    try {\n      if (raos->hasBufferedData()) {\n        raos->cork(false);\n        raos->flush();\n        if (raos->hasBufferedData())\n          vlog.error(\"Failed to flush remaining socket data on close\");\n      }\n    } catch (std::exception& e) {\n      vlog.error(\"Failed to flush remaining socket data on close: %s\", e.what());\n    }\n  }\n\n  if (serverKeyN)\n    delete[] serverKeyN;\n  if (serverKeyE)\n    delete[] serverKeyE;\n  if (clientKeyN)\n    delete[] clientKeyN;\n  if (clientKeyE)\n    delete[] clientKeyE;\n  if (serverKey.size)\n    rsa_private_key_clear(&serverKey);\n  if (clientKey.size)\n    rsa_public_key_clear(&clientKey);\n  if (isAllEncrypted && rawis && rawos)\n    sc->setStreams(rawis, rawos);\n  if (rais)\n    delete rais;\n  if (raos)\n    delete raos;\n}\n\nstatic inline ssize_t findSubstr(uint8_t* data, size_t size, const char *pattern)\n{\n  size_t patternLength = strlen(pattern);\n  for (size_t i = 0; i + patternLength < size; ++i) {\n    for (size_t j = 0; j < patternLength; ++j)\n      if (data[i + j] != pattern[j])\n        goto next;\n    return i;\nnext:\n    continue;\n  }\n  return -1;\n}\n\nstatic bool loadPEM(uint8_t* data, size_t size, const char *begin,\n                    const char *end, std::vector<uint8_t> *der)\n{\n  ssize_t pos1 = findSubstr(data, size, begin);\n  if (pos1 == -1)\n    return false;\n  pos1 += strlen(begin);\n  ssize_t base64Size = findSubstr(data + pos1, size - pos1, end);\n  if (base64Size == -1)\n    return false;\n  char *derBase64 = (char *)data + pos1;\n  if (!base64Size)\n    return false;\n  der->resize(BASE64_DECODE_LENGTH(base64Size));\n  struct base64_decode_ctx ctx;\n  size_t derSize;\n  base64_decode_init(&ctx);\n  if (!base64_decode_update(&ctx, &derSize, der->data(),\n                            base64Size, derBase64))\n    return false;\n  if (!base64_decode_final(&ctx))\n    return false;\n  assert(derSize <= der->size());\n  der->resize(derSize);\n  return true;\n}\n\nvoid SSecurityRSAAES::loadPrivateKey()\n{\n  FILE* file = fopen(keyFile, \"rb\");\n  if (!file)\n    throw core::posix_error(\"Failed to open key file\", errno);\n  fseek(file, 0, SEEK_END);\n  size_t size = ftell(file);\n  if (size == 0 || size > MaxKeyFileSize) {\n    fclose(file);\n    throw std::runtime_error(\"Size of key file is zero or too big\");\n  }\n  fseek(file, 0, SEEK_SET);\n  std::vector<uint8_t> data(size);\n  if (fread(data.data(), 1, data.size(), file) != size) {\n    fclose(file);\n    throw core::posix_error(\"Failed to read key\", errno);\n  }\n  fclose(file);\n\n  std::vector<uint8_t> der;\n  if (loadPEM(data.data(), data.size(),\n              \"-----BEGIN RSA PRIVATE KEY-----\\n\",\n              \"-----END RSA PRIVATE KEY-----\", &der)) {\n    loadPKCS1Key(der.data(), der.size());\n    return;\n  }\n  if (loadPEM(data.data(), data.size(),\n              \"-----BEGIN PRIVATE KEY-----\\n\",\n              \"-----END PRIVATE KEY-----\", &der)) {\n    loadPKCS8Key(der.data(), der.size());\n    return;\n  }\n  throw std::runtime_error(\"Failed to import key\");\n}\n\nvoid SSecurityRSAAES::loadPKCS1Key(const uint8_t* data, size_t size)\n{\n  struct rsa_public_key pub;\n  rsa_private_key_init(&serverKey);\n  rsa_public_key_init(&pub);\n  if (!rsa_keypair_from_der(&pub, &serverKey, 0, size, data)) {\n    rsa_private_key_clear(&serverKey);\n    rsa_public_key_clear(&pub);\n    throw std::runtime_error(\"Failed to import key\");\n  }\n  serverKeyLength = serverKey.size * 8;\n  serverKeyN = new uint8_t[serverKey.size];\n  serverKeyE = new uint8_t[serverKey.size];\n  nettle_mpz_get_str_256(serverKey.size, serverKeyN, pub.n);\n  nettle_mpz_get_str_256(serverKey.size, serverKeyE, pub.e);\n  rsa_public_key_clear(&pub);\n}\n\nvoid SSecurityRSAAES::loadPKCS8Key(const uint8_t* data, size_t size)\n{\n  struct asn1_der_iterator i, j;\n  uint32_t version;\n  const char* rsaIdentifier = \"\\x2a\\x86\\x48\\x86\\xf7\\x0d\\x01\\x01\\x01\";\n  const size_t rsaIdentifierLength = 9;\n  enum asn1_iterator_result res = asn1_der_iterator_first(&i, size, data);\n  if (res != ASN1_ITERATOR_CONSTRUCTED)\n    goto failed;\n  if (i.type != ASN1_SEQUENCE)\n    goto failed;\n  if (asn1_der_decode_constructed_last(&i) != ASN1_ITERATOR_PRIMITIVE)\n    goto failed;\n  if (!(i.type == ASN1_INTEGER &&\n        asn1_der_get_uint32(&i, &version) &&\n        version == 0))\n    goto failed;\n  if (!(asn1_der_iterator_next(&i) == ASN1_ITERATOR_CONSTRUCTED &&\n        i.type == ASN1_SEQUENCE &&\n        asn1_der_decode_constructed(&i, &j) == ASN1_ITERATOR_PRIMITIVE &&\n        j.type == ASN1_IDENTIFIER &&\n        j.length == rsaIdentifierLength &&\n        memcmp(j.data, rsaIdentifier, rsaIdentifierLength) == 0))\n    goto failed;\n  if (!(asn1_der_iterator_next(&i) == ASN1_ITERATOR_PRIMITIVE &&\n        i.type == ASN1_OCTETSTRING && i.length))\n    goto failed;\n  loadPKCS1Key(i.data, i.length);\n  return;\nfailed:\n  throw std::runtime_error(\"Failed to import key\");\n}\n\nbool SSecurityRSAAES::processMsg()\n{\n  switch (state) {\n    case SendPublicKey:\n      loadPrivateKey();\n      writePublicKey();\n      state = ReadPublicKey;\n      /* fall through */\n    case ReadPublicKey:\n      if (!readPublicKey())\n        return false;\n      writeRandom();\n      state = ReadRandom;\n      /* fall through */\n    case ReadRandom:\n      if (!readRandom())\n        return false;\n      setCipher();\n      writeHash();\n      state = ReadHash;\n      /* fall through */\n    case ReadHash:\n      if (!readHash())\n        return false;\n      clearSecrets();\n      writeSubtype();\n      state = ReadCredentials;\n      /* fall through */\n    case ReadCredentials:\n      if (!readCredentials())\n        return false;\n      if (requireUsername)\n        verifyUserPass();\n      else\n        verifyPass();\n      return true;\n  }\n\n  throw std::logic_error(\"Invalid state\");\n\n  return false;\n}\n\nvoid SSecurityRSAAES::writePublicKey()\n{\n  rdr::OutStream* os = sc->getOutStream();\n  os->writeU32(serverKeyLength);\n  os->writeBytes(serverKeyN, serverKey.size);\n  os->writeBytes(serverKeyE, serverKey.size);\n  os->flush();\n}\n\nbool SSecurityRSAAES::readPublicKey()\n{\n  rdr::InStream* is = sc->getInStream();\n  if (!is->hasData(4))\n    return false;\n  is->setRestorePoint();\n  clientKeyLength = is->readU32();\n  if (clientKeyLength < MinKeyLength)\n    throw protocol_error(\"Client key is too short\");\n  if (clientKeyLength > MaxKeyLength)\n    throw protocol_error(\"Client key is too long\");\n  size_t size = (clientKeyLength + 7) / 8;\n  if (!is->hasDataOrRestore(size * 2))\n    return false;\n  is->clearRestorePoint();\n  clientKeyE = new uint8_t[size];\n  clientKeyN = new uint8_t[size];\n  is->readBytes(clientKeyN, size);\n  is->readBytes(clientKeyE, size);\n  rsa_public_key_init(&clientKey);\n  nettle_mpz_set_str_256_u(clientKey.n, size, clientKeyN);\n  nettle_mpz_set_str_256_u(clientKey.e, size, clientKeyE);\n  if (!rsa_public_key_prepare(&clientKey))\n    throw protocol_error(\"Client key is invalid\");\n  return true;\n}\n\nstatic void random_func(void* ctx, size_t length, uint8_t* dst)\n{\n  rdr::RandomStream* rs = (rdr::RandomStream*)ctx;\n  if (!rs->hasData(length))\n    throw std::runtime_error(\"Failed to encrypt random\");\n  rs->readBytes(dst, length);\n}\n\nvoid SSecurityRSAAES::writeRandom()\n{\n  rdr::RandomStream rs;\n  rdr::OutStream* os = sc->getOutStream();\n  if (!rs.hasData(keySize / 8))\n    throw std::runtime_error(\"Failed to generate random\");\n  rs.readBytes(serverRandom, keySize / 8);\n  mpz_t x;\n  mpz_init(x);\n  int res;\n  try {\n    res = rsa_encrypt(&clientKey, &rs, random_func, keySize / 8,\n                      serverRandom, x);\n  } catch (...) {\n    mpz_clear(x);\n    throw;\n  }\n  if (!res) {\n    mpz_clear(x);\n    throw std::runtime_error(\"Failed to encrypt random\");\n  }\n  uint8_t* buffer = new uint8_t[clientKey.size];\n  nettle_mpz_get_str_256(clientKey.size, buffer, x);\n  mpz_clear(x);\n  os->writeU16(clientKey.size);\n  os->writeBytes(buffer, clientKey.size);\n  os->flush();\n  delete[] buffer;\n}\n\nbool SSecurityRSAAES::readRandom()\n{\n  rdr::InStream* is = sc->getInStream();\n  if (!is->hasData(2))\n    return false;\n  is->setRestorePoint();\n  size_t size = is->readU16();\n  if (size != serverKey.size)\n    throw protocol_error(\"Server key length doesn't match\");\n  if (!is->hasDataOrRestore(size))\n    return false;\n  is->clearRestorePoint();\n  uint8_t* buffer = new uint8_t[size];\n  is->readBytes(buffer, size);\n  size_t randomSize = keySize / 8;\n  mpz_t x;\n  nettle_mpz_init_set_str_256_u(x, size, buffer);\n  delete[] buffer;\n  if (!rsa_decrypt(&serverKey, &randomSize, clientRandom, x) ||\n    randomSize != (size_t)keySize / 8) {\n    mpz_clear(x);\n    throw protocol_error(\"Failed to decrypt client random\");\n  }\n  mpz_clear(x);\n  return true;\n}\n\nvoid SSecurityRSAAES::setCipher()\n{\n  rawis = sc->getInStream();\n  rawos = sc->getOutStream();\n  uint8_t key[32];\n  if (keySize == 128) {\n    struct sha1_ctx ctx;\n    sha1_init(&ctx);\n    sha1_update(&ctx, 16, serverRandom);\n    sha1_update(&ctx, 16, clientRandom);\n    sha1_digest(&ctx, 16, key);\n    rais = new rdr::AESInStream(rawis, key, 128);\n    sha1_init(&ctx);\n    sha1_update(&ctx, 16, clientRandom);\n    sha1_update(&ctx, 16, serverRandom);\n    sha1_digest(&ctx, 16, key);\n    raos = new rdr::AESOutStream(rawos, key, 128);\n  } else {\n    struct sha256_ctx ctx;\n    sha256_init(&ctx);\n    sha256_update(&ctx, 32, serverRandom);\n    sha256_update(&ctx, 32, clientRandom);\n    sha256_digest(&ctx, 32, key);\n    rais = new rdr::AESInStream(rawis, key, 256);\n    sha256_init(&ctx);\n    sha256_update(&ctx, 32, clientRandom);\n    sha256_update(&ctx, 32, serverRandom);\n    sha256_digest(&ctx, 32, key);\n    raos = new rdr::AESOutStream(rawos, key, 256);\n  }\n  if (isAllEncrypted)\n    sc->setStreams(rais, raos);\n}\n\nvoid SSecurityRSAAES::writeHash()\n{\n  uint8_t hash[32];\n  size_t len = serverKeyLength;\n  uint8_t lenServerKey[4] = {\n    (uint8_t)((len & 0xff000000) >> 24),\n    (uint8_t)((len & 0xff0000) >> 16),\n    (uint8_t)((len & 0xff00) >> 8),\n    (uint8_t)(len & 0xff)\n  };\n  len = clientKeyLength;\n  uint8_t lenClientKey[4] = {\n    (uint8_t)((len & 0xff000000) >> 24),\n    (uint8_t)((len & 0xff0000) >> 16),\n    (uint8_t)((len & 0xff00) >> 8),\n    (uint8_t)(len & 0xff)\n  };\n  int hashSize;\n  if (keySize == 128) {\n    hashSize = 20;\n    struct sha1_ctx ctx;\n    sha1_init(&ctx);\n    sha1_update(&ctx, 4, lenServerKey);\n    sha1_update(&ctx, serverKey.size, serverKeyN);\n    sha1_update(&ctx, serverKey.size, serverKeyE);\n    sha1_update(&ctx, 4, lenClientKey);\n    sha1_update(&ctx, clientKey.size, clientKeyN);\n    sha1_update(&ctx, clientKey.size, clientKeyE);\n    sha1_digest(&ctx, hashSize, hash);\n  } else {\n    hashSize = 32;\n    struct sha256_ctx ctx;\n    sha256_init(&ctx);\n    sha256_update(&ctx, 4, lenServerKey);\n    sha256_update(&ctx, serverKey.size, serverKeyN);\n    sha256_update(&ctx, serverKey.size, serverKeyE);\n    sha256_update(&ctx, 4, lenClientKey);\n    sha256_update(&ctx, clientKey.size, clientKeyN);\n    sha256_update(&ctx, clientKey.size, clientKeyE);\n    sha256_digest(&ctx, hashSize, hash);\n  }\n  raos->writeBytes(hash, hashSize);\n  raos->flush();\n}\n\nbool SSecurityRSAAES::readHash()\n{\n  uint8_t hash[32];\n  uint8_t realHash[32];\n  int hashSize = keySize == 128 ? 20 : 32;\n  if (!rais->hasData(hashSize))\n    return false;\n  rais->readBytes(hash, hashSize);\n  size_t len = serverKeyLength;\n  uint8_t lenServerKey[4] = {\n    (uint8_t)((len & 0xff000000) >> 24),\n    (uint8_t)((len & 0xff0000) >> 16),\n    (uint8_t)((len & 0xff00) >> 8),\n    (uint8_t)(len & 0xff)\n  };\n  len = clientKeyLength;\n  uint8_t lenClientKey[4] = {\n    (uint8_t)((len & 0xff000000) >> 24),\n    (uint8_t)((len & 0xff0000) >> 16),\n    (uint8_t)((len & 0xff00) >> 8),\n    (uint8_t)(len & 0xff)\n  };\n  if (keySize == 128) {\n    struct sha1_ctx ctx;\n    sha1_init(&ctx);\n    sha1_update(&ctx, 4, lenClientKey);\n    sha1_update(&ctx, clientKey.size, clientKeyN);\n    sha1_update(&ctx, clientKey.size, clientKeyE);\n    sha1_update(&ctx, 4, lenServerKey);\n    sha1_update(&ctx, serverKey.size, serverKeyN);\n    sha1_update(&ctx, serverKey.size, serverKeyE);\n    sha1_digest(&ctx, hashSize, realHash);\n  } else {\n    struct sha256_ctx ctx;\n    sha256_init(&ctx);\n    sha256_update(&ctx, 4, lenClientKey);\n    sha256_update(&ctx, clientKey.size, clientKeyN);\n    sha256_update(&ctx, clientKey.size, clientKeyE);\n    sha256_update(&ctx, 4, lenServerKey);\n    sha256_update(&ctx, serverKey.size, serverKeyN);\n    sha256_update(&ctx, serverKey.size, serverKeyE);\n    sha256_digest(&ctx, hashSize, realHash);\n  }\n  if (memcmp(hash, realHash, hashSize) != 0)\n    throw protocol_error(\"Hash doesn't match\");\n  return true;\n}\n\nvoid SSecurityRSAAES::clearSecrets()\n{\n  rsa_private_key_clear(&serverKey);\n  rsa_public_key_clear(&clientKey);\n  serverKey.size = 0;\n  clientKey.size = 0;\n  delete[] serverKeyN;\n  delete[] serverKeyE;\n  delete[] clientKeyN;\n  delete[] clientKeyE;\n  serverKeyN = nullptr;\n  serverKeyE = nullptr;\n  clientKeyN = nullptr;\n  clientKeyE = nullptr;\n  memset(serverRandom, 0, sizeof(serverRandom));\n  memset(clientRandom, 0, sizeof(clientRandom));\n}\n\nvoid SSecurityRSAAES::writeSubtype()\n{\n  if (requireUsername)\n    raos->writeU8(secTypeRA2UserPass);\n  else\n    raos->writeU8(secTypeRA2Pass);\n  raos->flush();\n}\n\nbool SSecurityRSAAES::readCredentials()\n{\n  if (!rais->hasData(1))\n    return false;\n  rais->setRestorePoint();\n  uint8_t lenUsername = rais->readU8();\n  if (!rais->hasDataOrRestore(lenUsername + 1))\n    return false;\n  rais->readBytes((uint8_t*)username, lenUsername);\n  username[lenUsername] = 0;\n  uint8_t lenPassword = rais->readU8();\n  if (!rais->hasDataOrRestore(lenPassword))\n    return false;\n  rais->readBytes((uint8_t*)password, lenPassword);\n  password[lenPassword] = 0;\n  rais->clearRestorePoint();\n  return true;\n}\n\nvoid SSecurityRSAAES::verifyUserPass()\n{\n#ifndef __APPLE__\n#ifdef WIN32\n  WinPasswdValidator* valid = new WinPasswdValidator();\n#elif !defined(__APPLE__)\n  UnixPasswordValidator *valid = new UnixPasswordValidator();\n#endif\n  std::string msg = \"Authentication failed\";\n  if (!valid->validate(sc, username, password, msg)) {\n    delete valid;\n    throw auth_error(msg);\n  }\n  delete valid;\n#else\n  throw std::logic_error(\"No password validator configured\");\n#endif\n}\n\nvoid SSecurityRSAAES::verifyPass()\n{\n  VncAuthPasswdGetter* pg = &SSecurityVncAuth::vncAuthPasswd;\n  std::string passwd, passwdReadOnly;\n  pg->getVncAuthPasswd(&passwd, &passwdReadOnly);\n\n  if (passwd.empty())\n    throw std::runtime_error(\"No password configured\");\n\n  if (password == passwd) {\n    accessRights = AccessDefault;\n    return;\n  }\n\n  if (!passwdReadOnly.empty() && password == passwdReadOnly) {\n    accessRights = AccessView;\n    return;\n  }\n\n  throw auth_error(\"Authentication failed\");\n}\n\nconst char* SSecurityRSAAES::getUserName() const\n{\n  return username;\n}\n"
  },
  {
    "path": "common/rfb/SSecurityRSAAES.h",
    "content": "/* Copyright (C) 2022 Dinglan Peng\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __S_SECURITY_RSAAES_H__\n#define __S_SECURITY_RSAAES_H__\n\n#ifndef HAVE_NETTLE\n#error \"This header should not be included without HAVE_NETTLE defined\"\n#endif\n\n#include <nettle/rsa.h>\n\n#include <rfb/SSecurity.h>\n\nnamespace core {\n  class BoolParameter;\n  class StringParameter;\n}\n\nnamespace rdr {\n  class InStream;\n  class OutStream;\n  class AESInStream;\n  class AESOutStream;\n}\n\nnamespace rfb {\n\n  class SSecurityRSAAES : public SSecurity {\n  public:\n    SSecurityRSAAES(SConnection* sc, uint32_t secType,\n                    int keySize, bool isAllEncrypted);\n    virtual ~SSecurityRSAAES();\n    bool processMsg() override;\n    const char* getUserName() const override;\n    int getType() const override {return secType;}\n    AccessRights getAccessRights() const override\n    {\n      return accessRights;\n    }\n\n    static core::StringParameter keyFile;\n    static core::BoolParameter requireUsername;\n\n  private:\n    void cleanup();\n    void loadPrivateKey();\n    void loadPKCS1Key(const uint8_t* data, size_t size);\n    void loadPKCS8Key(const uint8_t* data, size_t size);\n    void writePublicKey();\n    bool readPublicKey();\n    void writeRandom();\n    bool readRandom();\n    void setCipher();\n    void writeHash();\n    bool readHash();\n    void clearSecrets();\n    void writeSubtype();\n    bool readCredentials();\n    void verifyUserPass();\n    void verifyPass();\n\n    int state;\n    int keySize;\n    bool isAllEncrypted;\n    uint32_t secType;\n    struct rsa_private_key serverKey;\n    struct rsa_public_key clientKey;\n    uint32_t serverKeyLength;\n    uint8_t* serverKeyN;\n    uint8_t* serverKeyE;\n    uint32_t clientKeyLength;\n    uint8_t* clientKeyN;\n    uint8_t* clientKeyE;\n    uint8_t serverRandom[32];\n    uint8_t clientRandom[32];\n\n    char username[256];\n    char password[256];\n    AccessRights accessRights;\n\n    rdr::AESInStream* rais;\n    rdr::AESOutStream* raos;\n\n    rdr::InStream* rawis;\n    rdr::OutStream* rawos;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/SSecurityStack.cxx",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rfb/SSecurityStack.h>\n\nusing namespace rfb;\n\nSSecurityStack::SSecurityStack(SConnection* sc_, int Type,\n                               SSecurity* s0, SSecurity* s1)\n  : SSecurity(sc_), state(0), state0(s0), state1(s1), type(Type)\n{\n}\n\nSSecurityStack::~SSecurityStack()\n{\n  delete state0;\n  delete state1;\n}\n\nbool SSecurityStack::processMsg()\n{\n  bool res = true;\n\n  if (state == 0) {\n    if (state0)\n      res = state0->processMsg();\n    if (!res)\n      return res;\n    state++;\n  }\n\n  if (state == 1) {\n    if (state1)\n      res = state1->processMsg();\n    if (!res)\n      return res;\n    state++;\n  }\n\n  return res;\n}\n\nconst char* SSecurityStack::getUserName() const\n{\n  const char* c = nullptr;\n\n  if (state1 && !c)\n    c = state1->getUserName();\n  if (state0 && !c)\n    c = state0->getUserName();\n\n  return c;\n}\n\nAccessRights SSecurityStack::getAccessRights() const\n{\n  AccessRights accessRights;\n\n  if (!state0 && !state1)\n    return SSecurity::getAccessRights();\n\n  accessRights = AccessFull;\n\n  if (state0)\n    accessRights &= state0->getAccessRights();\n  if (state1)\n    accessRights &= state1->getAccessRights();\n\n  return accessRights;\n}\n"
  },
  {
    "path": "common/rfb/SSecurityStack.h",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_SSECURITYSTACK_H__\n#define __RFB_SSECURITYSTACK_H__\n\n#include <rfb/SSecurity.h>\n\nnamespace rfb {\n\n  class SSecurityStack : public SSecurity {\n  public:\n    SSecurityStack(SConnection* sc, int Type,\n                   SSecurity* s0 = nullptr, SSecurity* s1 = nullptr);\n    ~SSecurityStack();\n    bool processMsg() override;\n    int getType() const override { return type; };\n    const char* getUserName() const override;\n    AccessRights getAccessRights() const override;\n  protected:\n    short state;\n    SSecurity* state0;\n    SSecurity* state1;\n    int type;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/SSecurityTLS.cxx",
    "content": "/* \n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright 2012-2025 Pierre Ossman for Cendio AB\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#ifndef HAVE_GNUTLS\n#error \"This source should not be compiled without HAVE_GNUTLS defined\"\n#endif\n\n#include <stdlib.h>\n\n#include <core/LogWriter.h>\n\n#include <rfb/SSecurityTLS.h>\n#include <rfb/SConnection.h>\n#include <rfb/Exception.h>\n\n#include <rdr/TLSException.h>\n#include <rdr/TLSSocket.h>\n\n#include <gnutls/x509.h>\n\n#if defined (SSECURITYTLS__USE_DEPRECATED_DH)\n/* FFDHE (RFC-7919) 2048-bit parameters, PEM-encoded */\nstatic unsigned char ffdhe2048[] =\n  \"-----BEGIN DH PARAMETERS-----\\n\"\n  \"MIIBDAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\\n\"\n  \"+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\\n\"\n  \"87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\\n\"\n  \"YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\\n\"\n  \"7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\\n\"\n  \"ssbzSibBsu/6iGtCOGEoXJf//////////wIBAgICAOE=\\n\"\n  \"-----END DH PARAMETERS-----\\n\";\n\nstatic const gnutls_datum_t ffdhe_pkcs3_param = {\n  ffdhe2048,\n  sizeof(ffdhe2048)\n};\n#endif\n\nusing namespace rfb;\n\ncore::StringParameter SSecurityTLS::X509_CertFile\n(\"X509Cert\", \"Path to the X509 certificate in PEM format\", \"\");\n\ncore::StringParameter SSecurityTLS::X509_KeyFile\n(\"X509Key\", \"Path to the key of the X509 certificate in PEM format\", \"\");\n\nstatic core::LogWriter vlog(\"TLS\");\n\nSSecurityTLS::SSecurityTLS(SConnection* sc_, bool _anon)\n  : SSecurity(sc_), session(nullptr), anon_cred(nullptr),\n    cert_cred(nullptr), anon(_anon), tlssock(nullptr),\n    rawis(nullptr), rawos(nullptr)\n{\n  int ret;\n\n#if defined (SSECURITYTLS__USE_DEPRECATED_DH)\n  dh_params = nullptr;\n#endif\n\n  ret = gnutls_global_init();\n  if (ret != GNUTLS_E_SUCCESS)\n    throw rdr::tls_error(\"gnutls_global_init()\", ret);\n}\n\nvoid SSecurityTLS::shutdown()\n{\n  if (tlssock)\n    tlssock->shutdown();\n\n#if defined (SSECURITYTLS__USE_DEPRECATED_DH)\n  if (dh_params) {\n    gnutls_dh_params_deinit(dh_params);\n    dh_params = nullptr;\n  }\n#endif\n\n  if (anon_cred) {\n    gnutls_anon_free_server_credentials(anon_cred);\n    anon_cred = nullptr;\n  }\n\n  if (cert_cred) {\n    gnutls_certificate_free_credentials(cert_cred);\n    cert_cred = nullptr;\n  }\n\n  if (rawis && rawos) {\n    sc->setStreams(rawis, rawos);\n    rawis = nullptr;\n    rawos = nullptr;\n  }\n\n  if (tlssock) {\n    delete tlssock;\n    tlssock = nullptr;\n  }\n\n  if (session) {\n    gnutls_deinit(session);\n    session = nullptr;\n  }\n}\n\n\nSSecurityTLS::~SSecurityTLS()\n{\n  shutdown();\n\n  gnutls_global_deinit();\n}\n\nbool SSecurityTLS::processMsg()\n{\n  int err;\n\n  vlog.debug(\"Process security message (session %p)\", session);\n\n  if (!session) {\n    rdr::InStream* is = sc->getInStream();\n    rdr::OutStream* os = sc->getOutStream();\n\n    err = gnutls_init(&session, GNUTLS_SERVER);\n    if (err != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_init()\", err);\n\n    err = gnutls_set_default_priority(session);\n    if (err != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_set_default_priority()\", err);\n\n    try {\n      setParams();\n    }\n    catch(...) {\n      os->writeU8(0);\n      throw;\n    }\n\n    os->writeU8(1);\n    os->flush();\n\n    tlssock = new rdr::TLSSocket(is, os, session);\n\n    rawis = is;\n    rawos = os;\n  }\n\n  try {\n    if (!tlssock->handshake())\n      return false;\n  } catch (std::exception&) {\n    shutdown();\n    throw;\n  }\n\n  vlog.debug(\"TLS handshake completed with %s\",\n             gnutls_session_get_desc(session));\n\n  sc->setStreams(&tlssock->inStream(), &tlssock->outStream());\n\n  return true;\n}\n\nvoid SSecurityTLS::setParams()\n{\n  static const char kx_anon_priority[] = \"+ANON-ECDH:+ANON-DH\";\n\n  int ret;\n\n  // Custom priority string specified?\n  if (strcmp(Security::GnuTLSPriority, \"\") != 0) {\n    std::string prio;\n    const char *err;\n\n    prio = (const char*)Security::GnuTLSPriority;\n    if (anon) {\n      prio += \":\";\n      prio += kx_anon_priority;\n    }\n\n    ret = gnutls_priority_set_direct(session, prio.c_str(), &err);\n    if (ret != GNUTLS_E_SUCCESS) {\n      if (ret == GNUTLS_E_INVALID_REQUEST)\n        vlog.error(\"GnuTLS priority syntax error at: %s\", err);\n      throw rdr::tls_error(\"gnutls_set_priority_direct()\", ret);\n    }\n  } else if (anon) {\n    const char *err;\n\n#if GNUTLS_VERSION_NUMBER >= 0x030603\n    ret = gnutls_set_default_priority_append(session, kx_anon_priority, &err, 0);\n    if (ret != GNUTLS_E_SUCCESS) {\n      if (ret == GNUTLS_E_INVALID_REQUEST)\n        vlog.error(\"GnuTLS priority syntax error at: %s\", err);\n      throw rdr::tls_error(\"gnutls_set_default_priority_append()\", ret);\n    }\n#else\n    std::string prio;\n\n    // We don't know what the system default priority is, so we guess\n    // it's what upstream GnuTLS has\n    prio = \"NORMAL\";\n    prio += \":\";\n    prio += kx_anon_priority;\n\n    ret = gnutls_priority_set_direct(session, prio.c_str(), &err);\n    if (ret != GNUTLS_E_SUCCESS) {\n      if (ret == GNUTLS_E_INVALID_REQUEST)\n        vlog.error(\"GnuTLS priority syntax error at: %s\", err);\n      throw rdr::tls_error(\"gnutls_set_priority_direct()\", ret);\n    }\n#endif\n  }\n\n#if defined (SSECURITYTLS__USE_DEPRECATED_DH)\n  ret = gnutls_dh_params_init(&dh_params);\n  if (ret != GNUTLS_E_SUCCESS)\n    throw rdr::tls_error(\"gnutls_dh_params_init()\", ret);\n\n  ret = gnutls_dh_params_import_pkcs3(dh_params, &ffdhe_pkcs3_param,\n                                      GNUTLS_X509_FMT_PEM);\n  if (ret != GNUTLS_E_SUCCESS)\n    throw rdr::tls_error(\"gnutls_dh_params_import_pkcs3()\", ret);\n#endif\n\n  if (anon) {\n    ret = gnutls_anon_allocate_server_credentials(&anon_cred);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_anon_allocate_server_credentials()\", ret);\n\n#if defined (SSECURITYTLS__USE_DEPRECATED_DH)\n    gnutls_anon_set_server_dh_params(anon_cred, dh_params);\n#endif\n\n    ret = gnutls_credentials_set(session, GNUTLS_CRD_ANON, anon_cred);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_credentials_set()\", ret);\n\n    vlog.debug(\"Anonymous session has been set\");\n\n  } else {\n    ret = gnutls_certificate_allocate_credentials(&cert_cred);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_certificate_allocate_credentials()\", ret);\n\n#if defined (SSECURITYTLS__USE_DEPRECATED_DH)\n    gnutls_certificate_set_dh_params(cert_cred, dh_params);\n#endif\n\n    ret = gnutls_certificate_set_x509_key_file(cert_cred, X509_CertFile,\n                                               X509_KeyFile,\n                                               GNUTLS_X509_FMT_PEM);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"Failed to load certificate and key\", ret);\n\n    ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cert_cred);\n    if (ret != GNUTLS_E_SUCCESS)\n      throw rdr::tls_error(\"gnutls_credentials_set()\", ret);\n\n    vlog.debug(\"X509 session has been set\");\n\n  }\n\n}\n"
  },
  {
    "path": "common/rfb/SSecurityTLS.h",
    "content": "/* \n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright 2012-2025 Pierre Ossman for Cendio AB\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __S_SECURITY_TLS_H__\n#define __S_SECURITY_TLS_H__\n\n#ifndef HAVE_GNUTLS\n#error \"This header should not be included without HAVE_GNUTLS defined\"\n#endif\n\n#include <rfb/Security.h>\n#include <rfb/SSecurity.h>\n\n#include <gnutls/gnutls.h>\n\n/* In GnuTLS 3.6.0 DH parameter generation was deprecated. RFC7919 is used instead.\n * GnuTLS before 3.6.0 doesn't know about RFC7919 so we will have to import it.\n */\n#if GNUTLS_VERSION_NUMBER < 0x030600\n#define SSECURITYTLS__USE_DEPRECATED_DH\n#endif\n\nnamespace rdr {\n  class InStream;\n  class OutStream;\n  class TLSSocket;\n}\n\nnamespace rfb {\n\n  class SSecurityTLS : public SSecurity {\n  public:\n    SSecurityTLS(SConnection* sc, bool _anon);\n    virtual ~SSecurityTLS();\n    bool processMsg() override;\n    const char* getUserName() const override {return nullptr;}\n    int getType() const override { return anon ? secTypeTLSNone : secTypeX509None;}\n\n    static core::StringParameter X509_CertFile;\n    static core::StringParameter X509_KeyFile;\n\n  protected:\n    void shutdown();\n    void setParams();\n\n  private:\n    gnutls_session_t session;\n#if defined (SSECURITYTLS__USE_DEPRECATED_DH)\n    gnutls_dh_params_t dh_params;\n#endif\n    gnutls_anon_server_credentials_t anon_cred;\n    gnutls_certificate_credentials_t cert_cred;\n\n    bool anon;\n\n    rdr::TLSSocket* tlssock;\n\n    rdr::InStream* rawis;\n    rdr::OutStream* rawos;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/SSecurityVeNCrypt.cxx",
    "content": "/*\n * Copyright (C) 2005-2006 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n/*\n * SSecurityVeNCrypt\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <rfb/SConnection.h>\n#include <rfb/SecurityServer.h>\n#include <rfb/SSecurityVeNCrypt.h>\n#include <rfb/Exception.h>\n#include <rfb/Security.h>\n\n#include <rdr/InStream.h>\n#include <rdr/OutStream.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"SVeNCrypt\");\n\nSSecurityVeNCrypt::SSecurityVeNCrypt(SConnection* sc_,\n                                     SecurityServer *sec)\n  : SSecurity(sc_), security(sec)\n{\n  ssecurity = nullptr;\n  haveSentVersion = false;\n  haveRecvdMajorVersion = false;\n  haveRecvdMinorVersion = false;\n  majorVersion = 0;\n  minorVersion = 0;\n  haveSentTypes = false;\n  haveChosenType = false;\n  chosenType = secTypeVeNCrypt;\n  numTypes = 0;\n  subTypes = nullptr;\n}\n\nSSecurityVeNCrypt::~SSecurityVeNCrypt()\n{\n  delete ssecurity;\n  delete [] subTypes;\n}\n\nbool SSecurityVeNCrypt::processMsg()\n{\n  rdr::InStream* is = sc->getInStream();\n  rdr::OutStream* os = sc->getOutStream();\n  uint8_t i;\n\n  /* VeNCrypt initialization */\n\n  /* Send the highest version we can support */\n  if (!haveSentVersion) {\n    os->writeU8(0);\n    os->writeU8(2);\n    haveSentVersion = true;\n    os->flush();\n  }\n\n  /* Receive back highest version that client can support (up to and including ours) */\n  if (!haveRecvdMajorVersion) {\n    if (!is->hasData(1))\n      return false;\n\n    majorVersion = is->readU8();\n    haveRecvdMajorVersion = true;\n  }\n\n  if (!haveRecvdMinorVersion) {\n    if (!is->hasData(1))\n      return false;\n\n    minorVersion = is->readU8();\n    haveRecvdMinorVersion = true;\n\n    /* WORD value with major version in upper 8 bits and minor version in lower 8 bits */\n    uint16_t Version = (((uint16_t)majorVersion) << 8) | ((uint16_t)minorVersion);\n\n    switch (Version) {\n    case 0x0000: /* 0.0 - The client cannot support us! */\n    case 0x0001: /* 0.1 Legacy VeNCrypt, not supported */\n      os->writeU8(0xFF); /* This is not OK */\n      os->flush();\n      throw protocol_error(\"The client cannot support the server's \"\n                              \"VeNCrypt version\");\n\n    case 0x0002: /* 0.2 */\n      os->writeU8(0); /* OK */\n      break;\n\n    default:\n      os->writeU8(0xFF); /* Not OK */\n      os->flush();\n      throw protocol_error(\"The client returned an unsupported VeNCrypt version\");\n    }\n  }\n\n  /*\n   * send number of supported VeNCrypt authentication types (uint8_t)\n   * followed by authentication types (uint32_t:s)\n   */\n  if (!haveSentTypes) {\n    std::list<uint32_t> listSubTypes;\n\n    listSubTypes = security->GetEnabledExtSecTypes();\n\n    numTypes = listSubTypes.size();\n    subTypes = new uint32_t[numTypes];\n\n    for (i = 0; i < numTypes; i++) {\n      subTypes[i] = listSubTypes.front();\n      listSubTypes.pop_front();\n    }\n\n    if (numTypes) { \n      os->writeU8(numTypes);\n      for (i = 0; i < numTypes; i++)\n\tos->writeU32(subTypes[i]);\n\n      os->flush(); \n      haveSentTypes = true;\n    } else\n      throw protocol_error(\"There are no VeNCrypt sub-types to send to the client\");\n  }\n\n  /* get type back from client (must be one of the ones we sent) */\n  if (!haveChosenType) {\n    if (!is->hasData(4))\n      return false;\n\n    chosenType = is->readU32();\n\n    for (i = 0; i < numTypes; i++) {\n      if (chosenType == subTypes[i]) {\n\thaveChosenType = true;\n\tbreak;\n      }\n    }\n\n    if (!haveChosenType)\n      chosenType = secTypeInvalid;\n\n    vlog.info(\"Client requests security type %s (%d)\", secTypeName(chosenType),\n\t       chosenType);\n\n    /* Set up the stack according to the chosen type */\n    if (chosenType == secTypeInvalid || chosenType == secTypeVeNCrypt)\n      throw protocol_error(\"No valid VeNCrypt sub-type\");\n\n    ssecurity = security->GetSSecurity(sc, chosenType);\n  }\n\n  /* continue processing the messages */\n  return ssecurity->processMsg();\n}\n\nconst char* SSecurityVeNCrypt::getUserName() const\n{\n  if (ssecurity == nullptr)\n    return nullptr;\n  return ssecurity->getUserName();\n}\n\nAccessRights SSecurityVeNCrypt::getAccessRights() const\n{\n  if (ssecurity == nullptr)\n    return SSecurity::getAccessRights();\n  return ssecurity->getAccessRights();\n}\n"
  },
  {
    "path": "common/rfb/SSecurityVeNCrypt.h",
    "content": "/*\n * Copyright (C) 2005-2006 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// SSecurityVeNCrypt\n//\n\n#ifndef __SSECURITYVENCRYPT_H__\n#define __SSECURITYVENCRYPT_H__\n\n#include <rfb/SSecurity.h>\n\nnamespace rfb {\n\n  class SConnection;\n  class SecurityServer;\n\n  class SSecurityVeNCrypt : public SSecurity {\n  public:\n    SSecurityVeNCrypt(SConnection* sc, SecurityServer *sec);\n    ~SSecurityVeNCrypt();\n    bool processMsg() override;\n    int getType() const override { return chosenType; }\n    const char* getUserName() const override;\n    AccessRights getAccessRights() const override;\n\n  protected:\n    SSecurity *ssecurity;\n    SecurityServer *security;\n    bool haveSentVersion, haveRecvdMajorVersion, haveRecvdMinorVersion;\n    bool haveSentTypes, haveChosenType;\n    uint8_t majorVersion, minorVersion, numTypes;\n    uint32_t *subTypes, chosenType;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/SSecurityVncAuth.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// SSecurityVncAuth\n//\n// XXX not thread-safe, because d3des isn't - do we need to worry about this?\n//\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Configuration.h>\n#include <core/LogWriter.h>\n\n#include <rdr/OutStream.h>\n\n#include <rfb/SSecurityVncAuth.h>\n#include <rdr/RandomStream.h>\n#include <rfb/SConnection.h>\n#include <rfb/Exception.h>\n#include <rfb/obfuscate.h>\n\n#include <assert.h>\n#include <string.h>\n#include <stdio.h>\nextern \"C\" {\n#include <rfb/d3des.h>\n}\n\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"SVncAuth\");\n\ncore::StringParameter SSecurityVncAuth::vncAuthPasswdFile\n(\"PasswordFile\", \"Password file for VNC authentication\", \"\");\ncore::AliasParameter rfbauth(\"rfbauth\", \"Alias for PasswordFile\",\n\t\t       &SSecurityVncAuth::vncAuthPasswdFile);\nVncAuthPasswdParameter SSecurityVncAuth::vncAuthPasswd\n(\"Password\", \"Obfuscated binary encoding of the password which clients must supply to \"\n \"access the server\", &SSecurityVncAuth::vncAuthPasswdFile);\n\nSSecurityVncAuth::SSecurityVncAuth(SConnection* sc_)\n  : SSecurity(sc_), sentChallenge(false),\n    pg(&vncAuthPasswd), accessRights(AccessNone)\n{\n}\n\nbool SSecurityVncAuth::verifyResponse(const char* password)\n{\n  uint8_t expectedResponse[vncAuthChallengeSize];\n\n  // Calculate the expected response\n  uint8_t key[8];\n  int pwdLen = strlen(password);\n  for (int i=0; i<8; i++)\n    key[i] = i<pwdLen ? password[i] : 0;\n  deskey(key, EN0);\n  for (int j = 0; j < vncAuthChallengeSize; j += 8)\n    des(challenge+j, expectedResponse+j);\n\n  // Check the actual response\n  return memcmp(response, expectedResponse, vncAuthChallengeSize) == 0;\n}\n\nbool SSecurityVncAuth::processMsg()\n{\n  rdr::InStream* is = sc->getInStream();\n  rdr::OutStream* os = sc->getOutStream();\n\n  if (!sentChallenge) {\n    rdr::RandomStream rs;\n    if (!rs.hasData(vncAuthChallengeSize))\n      throw std::runtime_error(\"Could not generate random data for VNC auth challenge\");\n    rs.readBytes(challenge, vncAuthChallengeSize);\n    os->writeBytes(challenge, vncAuthChallengeSize);\n    os->flush();\n    sentChallenge = true;\n    return false;\n  }\n\n  if (!is->hasData(vncAuthChallengeSize))\n    return false;\n\n  is->readBytes(response, vncAuthChallengeSize);\n\n  std::string passwd, passwdReadOnly;\n  pg->getVncAuthPasswd(&passwd, &passwdReadOnly);\n\n  if (passwd.empty())\n    throw std::runtime_error(\"No password configured\");\n\n  if (verifyResponse(passwd.c_str())) {\n    accessRights = AccessDefault;\n    return true;\n  }\n\n  if (!passwdReadOnly.empty() &&\n      verifyResponse(passwdReadOnly.c_str())) {\n    accessRights = AccessView;\n    return true;\n  }\n\n  throw auth_error(\"Authentication failed\");\n}\n\nVncAuthPasswdParameter::VncAuthPasswdParameter(const char* name_,\n                                               const char* desc,\n                                               core::StringParameter* passwdFile_)\n: core::BinaryParameter(name_, desc, nullptr, 0),\n  passwdFile(passwdFile_)\n{\n}\n\nvoid VncAuthPasswdParameter::getVncAuthPasswd(std::string *password, std::string *readOnlyPassword) {\n  std::vector<uint8_t> obfuscated, obfuscatedReadOnly;\n  obfuscated = getData();\n\n  if (obfuscated.size() == 0) {\n    if (passwdFile) {\n      const char *fname = *passwdFile;\n      if (!fname[0]) {\n        vlog.info(\"Neither %s nor %s params set\", getName(), passwdFile->getName());\n        return;\n      }\n\n      FILE* fp = fopen(fname, \"r\");\n      if (!fp) {\n        vlog.error(\"Opening password file '%s' failed\", fname);\n        return;\n      }\n\n      vlog.debug(\"Reading password file\");\n      obfuscated.resize(8);\n      obfuscated.resize(fread(obfuscated.data(), 1, 8, fp));\n      obfuscatedReadOnly.resize(8);\n      obfuscatedReadOnly.resize(fread(obfuscatedReadOnly.data(), 1, 8, fp));\n      fclose(fp);\n    } else {\n      vlog.info(\"%s parameter not set\", getName());\n    }\n  }\n\n  assert(password != nullptr);\n  assert(readOnlyPassword != nullptr);\n\n  try {\n    *password = deobfuscate(obfuscated.data(), obfuscated.size());\n    *readOnlyPassword = deobfuscate(obfuscatedReadOnly.data(), obfuscatedReadOnly.size());\n  } catch (...) {\n  }\n}\n\n"
  },
  {
    "path": "common/rfb/SSecurityVncAuth.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n// SSecurityVncAuth - legacy VNC authentication protocol.\n// The getPasswd call can be overridden if you wish to store\n// the VncAuth password in an implementation-specific place.\n// Otherwise, the password is read from a BinaryParameter\n// called Password.\n\n#ifndef __RFB_SSECURITYVNCAUTH_H__\n#define __RFB_SSECURITYVNCAUTH_H__\n\n#include <stdint.h>\n\n#include <core/Configuration.h>\n\n#include <rfb/SSecurity.h>\n#include <rfb/Security.h>\n\nnamespace rfb {\n\n  class VncAuthPasswdGetter {\n  public:\n    // getVncAuthPasswd() fills buffer of given password and readOnlyPassword.\n    // If there was no read only password in the file, readOnlyPassword buffer is null.\n    virtual void getVncAuthPasswd(std::string *password, std::string *readOnlyPassword)=0;\n\n    virtual ~VncAuthPasswdGetter() { }\n  };\n\n  class VncAuthPasswdParameter : public VncAuthPasswdGetter, core::BinaryParameter {\n  public:\n    VncAuthPasswdParameter(const char* name, const char* desc, core::StringParameter* passwdFile_);\n    void getVncAuthPasswd(std::string *password, std::string *readOnlyPassword) override;\n  protected:\n    core::StringParameter* passwdFile;\n  };\n\n  class SSecurityVncAuth : public SSecurity {\n  public:\n    SSecurityVncAuth(SConnection* sc);\n    bool processMsg() override;\n    int getType() const override {return secTypeVncAuth;}\n    const char* getUserName() const override {return nullptr;}\n    AccessRights getAccessRights() const override { return accessRights; }\n    static core::StringParameter vncAuthPasswdFile;\n    static VncAuthPasswdParameter vncAuthPasswd;\n  private:\n    bool verifyResponse(const char* password);\n    enum {vncAuthChallengeSize = 16};\n    uint8_t challenge[vncAuthChallengeSize];\n    uint8_t response[vncAuthChallengeSize];\n    bool sentChallenge;\n    VncAuthPasswdGetter* pg;\n    AccessRights accessRights;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/ScreenSet.h",
    "content": "/* Copyright 2009 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// Management class for the RFB virtual screens\n\n#ifndef __RFB_SCREENSET_INCLUDED__\n#define __RFB_SCREENSET_INCLUDED__\n\n#include <stdio.h>\n#include <string.h>\n#include <stdint.h>\n\n#include <list>\n#include <set>\n\n#include <core/Rect.h>\n\nnamespace rfb {\n\n  // rfb::Screen\n  //\n  // Represents a single RFB virtual screen, which includes\n  // coordinates, an id and flags.\n\n  struct Screen {\n    Screen(void) : id(0), flags(0) {};\n    Screen(uint32_t id_, int x_, int y_, int w_, int h_, uint32_t flags_) :\n      id(id_), dimensions(x_, y_, x_+w_, y_+h_), flags(flags_) {};\n\n    inline bool operator==(const Screen& r) const {\n      if (id != r.id)\n        return false;\n      if (dimensions != r.dimensions)\n        return false;\n      if (flags != r.flags)\n        return false;\n      return true;\n    }\n\n    uint32_t id;\n    core::Rect dimensions;\n    uint32_t flags;\n  };\n\n  // rfb::ScreenSet\n  //\n  // Represents a complete screen configuration, excluding framebuffer\n  // dimensions.\n\n  struct ScreenSet {\n    ScreenSet(void) {};\n\n    typedef std::list<Screen>::iterator iterator;\n    typedef std::list<Screen>::const_iterator const_iterator;\n\n    inline iterator begin(void) { return screens.begin(); };\n    inline const_iterator begin(void) const { return screens.begin(); };\n    inline iterator end(void) { return screens.end(); };\n    inline const_iterator end(void) const { return screens.end(); };\n\n    inline int num_screens(void) const { return screens.size(); };\n\n    inline void add_screen(const Screen screen) { screens.push_back(screen); };\n    inline void remove_screen(uint32_t id) {\n      std::list<Screen>::iterator iter, nextiter;\n      for (iter = screens.begin();iter != screens.end();iter = nextiter) {\n        nextiter = iter; nextiter++;\n        if (iter->id == id)\n            screens.erase(iter);\n      }\n    }\n\n    inline bool validate(int fb_width, int fb_height) const {\n      std::list<Screen>::const_iterator iter;\n      std::set<uint32_t> seen_ids;\n      core::Rect fb_rect;\n\n      if (screens.empty())\n        return false;\n      if (num_screens() > 255)\n        return false;\n\n      fb_rect.setXYWH(0, 0, fb_width, fb_height);\n\n      for (iter = screens.begin();iter != screens.end();++iter) {\n        if (iter->dimensions.is_empty())\n          return false;\n        if (!iter->dimensions.enclosed_by(fb_rect))\n          return false;\n        if (seen_ids.find(iter->id) != seen_ids.end())\n          return false;\n        seen_ids.insert(iter->id);\n      }\n\n      return true;\n    };\n\n    inline void print(char* str, size_t len) const {\n      char buffer[128];\n      std::list<Screen>::const_iterator iter;\n      snprintf(buffer, sizeof(buffer), \"%d screen(s)\\n\", num_screens());\n      str[0] = '\\0';\n      strncat(str, buffer, len - 1 - strlen(str));\n      for (iter = screens.begin();iter != screens.end();++iter) {\n        snprintf(buffer, sizeof(buffer),\n                 \"    %10d (0x%08x): %dx%d+%d+%d (flags 0x%08x)\\n\",\n                 (int)iter->id, (unsigned)iter->id,\n                 iter->dimensions.width(), iter->dimensions.height(),\n                 iter->dimensions.tl.x, iter->dimensions.tl.y,\n                 (unsigned)iter->flags);\n        strncat(str, buffer, len - 1 - strlen(str));\n      }\n    };\n\n    inline bool operator==(const ScreenSet& r) const {\n      std::list<Screen> a = screens;\n      a.sort(compare_screen);\n      std::list<Screen> b = r.screens;\n      b.sort(compare_screen);\n      return a == b;\n    };\n    inline bool operator!=(const ScreenSet& r) const { return !operator==(r); }\n\n    std::list<Screen> screens;\n\n  private:\n    static inline bool compare_screen(const Screen& first, const Screen& second)\n    {\n      return first.id < second.id;\n    }\n\n  };\n\n};\n\n#endif\n\n"
  },
  {
    "path": "common/rfb/Security.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string.h>\n\n#include <algorithm>\n#include <stdexcept>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb/Security.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"Security\");\n\n#ifdef HAVE_GNUTLS\ncore::StringParameter Security::GnuTLSPriority(\"GnuTLSPriority\",\n  \"GnuTLS priority string that controls the TLS session’s handshake algorithms\",\n  \"\");\n#endif\n\nSecurity::Security()\n{\n}\n\nSecurity::Security(core::EnumListParameter &secTypes)\n{\n  for (core::EnumListEntry type : secTypes) {\n    uint32_t typeNum = secTypeNum(type.getValueStr().c_str());\n    // Should have been filtered by EnumListParameter, but let's have\n    // a safety net\n    if (typeNum == secTypeInvalid)\n      throw std::logic_error(\"Unknown security type\");\n    enabledSecTypes.push_back(typeNum);\n  }\n}\n\nconst std::list<uint8_t> Security::GetEnabledSecTypes(void)\n{\n  std::list<uint8_t> result;\n\n  /* Partial workaround for Vino's stupid behaviour. It doesn't allow\n   * the basic authentication types as part of the VeNCrypt handshake,\n   * making it impossible for a client to do opportunistic encryption.\n   * At least make it possible to connect when encryption is explicitly\n   * disabled. */\n  for (uint32_t type : enabledSecTypes) {\n    if (type >= 0x100) {\n      result.push_back(secTypeVeNCrypt);\n      break;\n    }\n  }\n\n  for (uint32_t type : enabledSecTypes)\n    if (type < 0x100)\n      result.push_back(type);\n\n  return result;\n}\n\nconst std::list<uint32_t> Security::GetEnabledExtSecTypes(void)\n{\n  std::list<uint32_t> result;\n\n  for (uint32_t type : enabledSecTypes)\n    if (type != secTypeVeNCrypt) /* Do not include VeNCrypt type to avoid loops */\n      result.push_back(type);\n\n  return result;\n}\n\nvoid Security::EnableSecType(uint32_t secType)\n{\n  if (std::find(enabledSecTypes.begin(), enabledSecTypes.end(),\n                secType) != enabledSecTypes.end())\n    return;\n\n  enabledSecTypes.push_back(secType);\n}\n\nbool Security::IsSupported(uint32_t secType)\n{\n  if (std::find(enabledSecTypes.begin(), enabledSecTypes.end(),\n                secType) != enabledSecTypes.end())\n    return true;\n  if (secType == secTypeVeNCrypt)\n    return true;\n\n  return false;\n}\n\nchar *Security::ToString(void)\n{\n  static char out[128]; /* Should be enough */\n  bool firstpass = true;\n  const char *name;\n\n  memset(out, 0, sizeof(out));\n\n  for (uint32_t type : enabledSecTypes) {\n    name = secTypeName(type);\n    if (name[0] == '[') /* Unknown security type */\n      continue;\n\n    if (!firstpass)\n      strncat(out, \",\", sizeof(out) - 1);\n    else\n      firstpass = false;\n    strncat(out, name, sizeof(out) - 1);\n  }\n\n  return out;\n}\n\nuint32_t rfb::secTypeNum(const char* name)\n{\n  if (strcasecmp(name, \"None\") == 0)       return secTypeNone;\n  if (strcasecmp(name, \"VncAuth\") == 0)    return secTypeVncAuth;\n  if (strcasecmp(name, \"Tight\") == 0)      return secTypeTight;\n  if (strcasecmp(name, \"RA2\") == 0)        return secTypeRA2;\n  if (strcasecmp(name, \"RA2ne\") == 0)      return secTypeRA2ne;\n  if (strcasecmp(name, \"RA2_256\") == 0)    return secTypeRA256;\n  if (strcasecmp(name, \"RA2ne_256\") == 0)  return secTypeRAne256;\n  if (strcasecmp(name, \"SSPI\") == 0)       return secTypeSSPI;\n  if (strcasecmp(name, \"SSPIne\") == 0)     return secTypeSSPIne;\n  if (strcasecmp(name, \"VeNCrypt\") == 0)   return secTypeVeNCrypt;\n  if (strcasecmp(name, \"DH\") == 0)         return secTypeDH;\n  if (strcasecmp(name, \"MSLogonII\") == 0)  return secTypeMSLogonII;\n\n  /* VeNCrypt subtypes */\n  if (strcasecmp(name, \"Plain\") == 0)      return secTypePlain;\n  if (strcasecmp(name, \"TLSNone\") == 0)    return secTypeTLSNone;\n  if (strcasecmp(name, \"TLSVnc\") == 0)     return secTypeTLSVnc;\n  if (strcasecmp(name, \"TLSPlain\") == 0)   return secTypeTLSPlain;\n  if (strcasecmp(name, \"X509None\") == 0)   return secTypeX509None;\n  if (strcasecmp(name, \"X509Vnc\") == 0)    return secTypeX509Vnc;\n  if (strcasecmp(name, \"X509Plain\") == 0)  return secTypeX509Plain;\n\n  return secTypeInvalid;\n}\n\nconst char* rfb::secTypeName(uint32_t num)\n{\n  switch (num) {\n  case secTypeNone:       return \"None\";\n  case secTypeVncAuth:    return \"VncAuth\";\n  case secTypeTight:      return \"Tight\";\n  case secTypeRA2:        return \"RA2\";\n  case secTypeRA2ne:      return \"RA2ne\";\n  case secTypeRA256:      return \"RA2_256\";\n  case secTypeRAne256:    return \"RA2ne_256\";\n  case secTypeSSPI:       return \"SSPI\";\n  case secTypeSSPIne:     return \"SSPIne\";\n  case secTypeVeNCrypt:   return \"VeNCrypt\";\n  case secTypeDH:         return \"DH\";\n  case secTypeMSLogonII:  return \"MSLogonII\";\n\n  /* VeNCrypt subtypes */\n  case secTypePlain:      return \"Plain\";\n  case secTypeTLSNone:    return \"TLSNone\";\n  case secTypeTLSVnc:     return \"TLSVnc\";\n  case secTypeTLSPlain:   return \"TLSPlain\";\n  case secTypeX509None:   return \"X509None\";\n  case secTypeX509Vnc:    return \"X509Vnc\";\n  case secTypeX509Plain:  return \"X509Plain\";\n  default:                return \"[unknown secType]\";\n  }\n}\n"
  },
  {
    "path": "common/rfb/Security.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// secTypes.h - constants for the various security types.\n//\n\n#ifndef __RFB_SECTYPES_H__\n#define __RFB_SECTYPES_H__\n\n#include <stdint.h>\n\n#include <list>\n\nnamespace core {\n  class EnumListParameter;\n  class StringParameter;\n}\n\nnamespace rfb {\n\n  const uint8_t secTypeInvalid    = 0;\n  const uint8_t secTypeNone       = 1;\n  const uint8_t secTypeVncAuth    = 2;\n\n  const uint8_t secTypeRA2        = 5;\n  const uint8_t secTypeRA2ne      = 6;\n\n  const uint8_t secTypeSSPI       = 7;\n  const uint8_t secTypeSSPIne     = 8;\n\n  const uint8_t secTypeTight      = 16;\n  const uint8_t secTypeUltra      = 17;\n  const uint8_t secTypeTLS        = 18;\n  const uint8_t secTypeVeNCrypt   = 19;\n\n  const uint8_t secTypeDH         = 30;\n\n  const uint8_t secTypeMSLogonII  = 113;\n\n  const uint8_t secTypeRA256      = 129;\n  const uint8_t secTypeRAne256    = 130;\n\n  /* VeNCrypt subtypes */\n  const int secTypePlain          = 256;\n  const int secTypeTLSNone        = 257;\n  const int secTypeTLSVnc         = 258;\n  const int secTypeTLSPlain       = 259;\n  const int secTypeX509None       = 260;\n  const int secTypeX509Vnc        = 261;\n  const int secTypeX509Plain      = 262;\n\n  /* RSA-AES subtypes */\n  const int secTypeRA2UserPass    = 1;\n  const int secTypeRA2Pass        = 2;\n\n  // result types\n\n  const uint32_t secResultOK = 0;\n  const uint32_t secResultFailed = 1;\n  const uint32_t secResultTooMany = 2; // deprecated\n\n  class Security {\n  public:\n    /*\n     * Create Security instance.\n     */\n    Security();\n    Security(core::EnumListParameter& secTypes);\n\n    /*\n     * Note about security types.\n     *\n     * Although RFB protocol specifies security types as U8 values,\n     * we map VeNCrypt subtypes (U32) into the standard security types\n     * to simplify user configuration. With this mapping user can configure\n     * both VeNCrypt subtypes and security types with only one option.\n     */\n\n    /* Enable/Disable certain security type */\n    void EnableSecType(uint32_t secType);\n    void DisableSecType(uint32_t secType) { enabledSecTypes.remove(secType); }\n\n    void SetSecTypes(std::list<uint32_t> &secTypes) { enabledSecTypes = secTypes; }\n\n    /* Check if certain type is supported */\n    bool IsSupported(uint32_t secType);\n\n    /* Get list of enabled security types without VeNCrypt subtypes */\n    const std::list<uint8_t> GetEnabledSecTypes(void);\n    /* Get list of enabled VeNCrypt subtypes */\n    const std::list<uint32_t> GetEnabledExtSecTypes(void);\n\n    /* Output char* is stored in static array */\n    char *ToString(void);\n\n#ifdef HAVE_GNUTLS\n    static core::StringParameter GnuTLSPriority;\n#endif\n\n  private:\n    std::list<uint32_t> enabledSecTypes;\n  };\n\n  const char* secTypeName(uint32_t num);\n  uint32_t secTypeNum(const char* name);\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/SecurityClient.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <stdexcept>\n\n#include <core/Configuration.h>\n\n#include <rfb/CSecurityNone.h>\n#include <rfb/CSecurityStack.h>\n#include <rfb/CSecurityVeNCrypt.h>\n#include <rfb/CSecurityVncAuth.h>\n#include <rfb/CSecurityPlain.h>\n#include <rfb/Security.h>\n#include <rfb/SecurityClient.h>\n#ifdef HAVE_GNUTLS\n#include <rfb/CSecurityTLS.h>\n#endif\n#ifdef HAVE_NETTLE\n#include <rfb/CSecurityRSAAES.h>\n#include <rfb/CSecurityDH.h>\n#include <rfb/CSecurityMSLogonII.h>\n#endif\n\nusing namespace rfb;\n\ncore::EnumListParameter SecurityClient::secTypes\n(\"SecurityTypes\",\n \"Specify which security scheme to use (None, VncAuth, Plain\"\n#ifdef HAVE_GNUTLS\n \", TLSNone, TLSVnc, TLSPlain, X509None, X509Vnc, X509Plain\"\n#endif\n#ifdef HAVE_NETTLE\n \", RA2, RA2ne, RA2_256, RA2ne_256, DH, MSLogonII\"\n#endif\n \")\",\n { \"None\", \"VncAuth\", \"Plain\",\n#ifdef HAVE_GNUTLS\n \"TLSNone\", \"TLSVnc\", \"TLSPlain\", \"X509None\", \"X509Vnc\", \"X509Plain\",\n#endif\n#ifdef HAVE_NETTLE\n \"RA2\", \"RA2ne\", \"RA2_256\", \"RA2ne_256\", \"DH\", \"MSLogonII\",\n#endif\n },\n { \"None\", \"VncAuth\", \"Plain\",\n#ifdef HAVE_GNUTLS\n \"TLSNone\", \"TLSVnc\", \"TLSPlain\", \"X509None\", \"X509Vnc\", \"X509Plain\",\n#endif\n#ifdef HAVE_NETTLE\n \"RA2\", \"RA2ne\", \"RA2_256\", \"RA2ne_256\", \"DH\", \"MSLogonII\",\n#endif\n });\n\nCSecurity* SecurityClient::GetCSecurity(CConnection* cc, uint32_t secType)\n{\n  if (!IsSupported(secType))\n    goto bail;\n\n  switch (secType) {\n  case secTypeNone: return new CSecurityNone(cc);\n  case secTypeVncAuth: return new CSecurityVncAuth(cc);\n  case secTypeVeNCrypt: return new CSecurityVeNCrypt(cc, this);\n  case secTypePlain: return new CSecurityPlain(cc);\n#ifdef HAVE_GNUTLS\n  case secTypeTLSNone:\n    return new CSecurityStack(cc, secTypeTLSNone,\n                              new CSecurityTLS(cc, true));\n  case secTypeTLSVnc:\n    return new CSecurityStack(cc, secTypeTLSVnc,\n                              new CSecurityTLS(cc, true),\n                              new CSecurityVncAuth(cc));\n  case secTypeTLSPlain:\n    return new CSecurityStack(cc, secTypeTLSPlain,\n                              new CSecurityTLS(cc, true),\n                              new CSecurityPlain(cc));\n  case secTypeX509None:\n    return new CSecurityStack(cc, secTypeX509None,\n                              new CSecurityTLS(cc, false));\n  case secTypeX509Vnc:\n    return new CSecurityStack(cc, secTypeX509Vnc,\n                              new CSecurityTLS(cc, false),\n                              new CSecurityVncAuth(cc));\n  case secTypeX509Plain:\n    return new CSecurityStack(cc, secTypeX509Plain,\n                              new CSecurityTLS(cc, false),\n                              new CSecurityPlain(cc));\n#endif\n#ifdef HAVE_NETTLE\n  case secTypeRA2:\n    return new CSecurityRSAAES(cc, secTypeRA2, 128, true);\n  case secTypeRA2ne:\n    return new CSecurityRSAAES(cc, secTypeRA2ne, 128, false);\n  case secTypeRA256:\n    return new CSecurityRSAAES(cc, secTypeRA256, 256, true);\n  case secTypeRAne256:\n    return new CSecurityRSAAES(cc, secTypeRAne256, 256, false);\n  case secTypeDH:\n    return new CSecurityDH(cc);\n  case secTypeMSLogonII:\n    return new CSecurityMSLogonII(cc);\n#endif\n  }\n\nbail:\n  throw std::invalid_argument(\"Security type not supported\");\n}\n"
  },
  {
    "path": "common/rfb/SecurityClient.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// secTypes.h - constants for the various security types.\n//\n\n#ifndef __RFB_SECURITYCLIENT_H__\n#define __RFB_SECURITYCLIENT_H__\n\n#include <rfb/Security.h>\n\nnamespace rfb {\n\n  class CConnection;\n  class CSecurity;\n\n  class SecurityClient : public Security {\n  public:\n    SecurityClient(void) : Security(secTypes) {}\n\n    /* Create client side CSecurity class instance */\n    CSecurity* GetCSecurity(CConnection* cc, uint32_t secType);\n\n    static core::EnumListParameter secTypes;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/SecurityServer.cxx",
    "content": "/* \n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdexcept>\n\n#include <rfb/Security.h>\n#include <rfb/SecurityServer.h>\n\n#include <rfb/SSecurityNone.h>\n#include <rfb/SSecurityStack.h>\n#include <rfb/SSecurityPlain.h>\n#include <rfb/SSecurityVncAuth.h>\n#include <rfb/SSecurityVeNCrypt.h>\n#ifdef HAVE_GNUTLS\n#include <rfb/SSecurityTLS.h>\n#endif\n#ifdef HAVE_NETTLE\n#include <rfb/SSecurityRSAAES.h>\n#endif\n\nusing namespace rfb;\n\ncore::EnumListParameter SecurityServer::secTypes\n(\"SecurityTypes\",\n \"Specify which security scheme to use (None, VncAuth, Plain\"\n#ifdef HAVE_GNUTLS\n \", TLSNone, TLSVnc, TLSPlain, X509None, X509Vnc, X509Plain\"\n#endif\n#ifdef HAVE_NETTLE\n \", RA2, RA2ne, RA2_256, RA2ne_256\"\n#endif\n \")\",\n { \"None\", \"VncAuth\", \"Plain\",\n#ifdef HAVE_GNUTLS\n \"TLSNone\", \"TLSVnc\", \"TLSPlain\", \"X509None\", \"X509Vnc\", \"X509Plain\",\n#endif\n#ifdef HAVE_NETTLE\n \"RA2\", \"RA2ne\", \"RA2_256\", \"RA2ne_256\",\n#endif\n },\n {\n#ifdef HAVE_GNUTLS\n \"TLSVnc\",\n#endif\n \"VncAuth\"});\n\nSSecurity* SecurityServer::GetSSecurity(SConnection* sc, uint32_t secType)\n{\n  if (!IsSupported(secType))\n    goto bail;\n\n  switch (secType) {\n  case secTypeNone: return new SSecurityNone(sc);\n  case secTypeVncAuth: return new SSecurityVncAuth(sc);\n  case secTypeVeNCrypt: return new SSecurityVeNCrypt(sc, this);\n  case secTypePlain: return new SSecurityPlain(sc);\n#ifdef HAVE_GNUTLS\n  case secTypeTLSNone:\n    return new SSecurityStack(sc, secTypeTLSNone, new SSecurityTLS(sc, true));\n  case secTypeTLSVnc:\n    return new SSecurityStack(sc, secTypeTLSVnc, new SSecurityTLS(sc, true), new SSecurityVncAuth(sc));\n  case secTypeTLSPlain:\n    return new SSecurityStack(sc, secTypeTLSPlain, new SSecurityTLS(sc, true), new SSecurityPlain(sc));\n  case secTypeX509None:\n    return new SSecurityStack(sc, secTypeX509None, new SSecurityTLS(sc, false));\n  case secTypeX509Vnc:\n    return new SSecurityStack(sc, secTypeX509None, new SSecurityTLS(sc, false), new SSecurityVncAuth(sc));\n  case secTypeX509Plain:\n    return new SSecurityStack(sc, secTypeX509Plain, new SSecurityTLS(sc, false), new SSecurityPlain(sc));\n#endif\n#ifdef HAVE_NETTLE\n  case secTypeRA2:\n    return new SSecurityRSAAES(sc, secTypeRA2, 128, true);\n  case secTypeRA2ne:\n    return new SSecurityRSAAES(sc, secTypeRA2ne, 128, false);\n  case secTypeRA256:\n    return new SSecurityRSAAES(sc, secTypeRA256, 256, true);\n  case secTypeRAne256:\n    return new SSecurityRSAAES(sc, secTypeRAne256, 256, false);\n#endif\n  }\n\nbail:\n  throw std::invalid_argument(\"Security type not supported\");\n}\n\n"
  },
  {
    "path": "common/rfb/SecurityServer.h",
    "content": "/* \n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_SECURITYSERVER_H__\n#define __RFB_SECURITYSERVER_H__\n\n#include <rfb/Security.h>\n\nnamespace rfb {\n\n  class SConnection;\n  class SSecurity;\n\n  class SecurityServer : public Security {\n  public:\n    SecurityServer(void) : Security(secTypes) {}\n\n    /* Create server side SSecurity class instance */\n    SSecurity* GetSSecurity(SConnection* sc, uint32_t secType);\n\n    static core::EnumListParameter secTypes;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/ServerCore.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- ServerCore.cxx\n\n// This header will define the Server interface, from which ServerMT and\n// ServerST will be derived.\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string.h>\n#include <rfb/ServerCore.h>\n\ncore::IntParameter rfb::Server::idleTimeout\n(\"IdleTimeout\",\n \"The number of seconds after which an idle VNC connection will be dropped \"\n \"(zero means no timeout)\",\n 0, 0, INT_MAX);\ncore::IntParameter rfb::Server::maxDisconnectionTime\n(\"MaxDisconnectionTime\",\n \"Terminate when no client has been connected for s seconds\", \n 0, 0, INT_MAX);\ncore::IntParameter rfb::Server::maxConnectionTime\n(\"MaxConnectionTime\",\n \"Terminate when a client has been connected for s seconds\", \n 0, 0, INT_MAX);\ncore::IntParameter rfb::Server::maxIdleTime\n(\"MaxIdleTime\",\n \"Terminate after s seconds of user inactivity\", \n 0, 0, INT_MAX);\ncore::IntParameter rfb::Server::compareFB\n(\"CompareFB\",\n \"Perform pixel comparison on framebuffer to reduce unnecessary updates \"\n \"(0: never, 1: always, 2: auto)\",\n 2, 0, 2);\ncore::IntParameter rfb::Server::frameRate\n(\"FrameRate\",\n \"The maximum number of updates per second sent to each client\",\n 60, 0, INT_MAX);\ncore::BoolParameter rfb::Server::protocol3_3\n(\"Protocol3.3\",\n \"Always use protocol version 3.3 for backwards compatibility with \"\n \"badly-behaved clients\",\n false);\ncore::BoolParameter rfb::Server::alwaysShared\n(\"AlwaysShared\",\n \"Always treat incoming connections as shared, regardless of the client-\"\n \"specified setting\",\n false);\ncore::BoolParameter rfb::Server::neverShared\n(\"NeverShared\",\n \"Never treat incoming connections as shared, regardless of the client-\"\n \"specified setting\",\n false);\ncore::BoolParameter rfb::Server::disconnectClients\n(\"DisconnectClients\",\n \"Disconnect existing clients if an incoming connection is non-shared. \"\n \"If combined with NeverShared then new connections will be refused \"\n \"while there is a client active\",\n true);\ncore::BoolParameter rfb::Server::acceptKeyEvents\n(\"AcceptKeyEvents\",\n \"Accept key press and release events from clients.\",\n true);\ncore::BoolParameter rfb::Server::acceptPointerEvents\n(\"AcceptPointerEvents\",\n \"Accept pointer movement and button events from clients.\",\n true);\ncore::BoolParameter rfb::Server::acceptCutText\n(\"AcceptCutText\",\n \"Accept clipboard updates from clients.\",\n true);\ncore::BoolParameter rfb::Server::sendCutText\n(\"SendCutText\",\n \"Send clipboard changes to clients.\",\n true);\ncore::BoolParameter rfb::Server::acceptSetDesktopSize\n(\"AcceptSetDesktopSize\",\n \"Accept set desktop size events from clients.\",\n true);\ncore::BoolParameter rfb::Server::queryConnect\n(\"QueryConnect\",\n \"Prompt the local user to accept or reject incoming connections.\",\n false);\n"
  },
  {
    "path": "common/rfb/ServerCore.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- ServerCore.h\n\n// This header will define the Server interface, from which ServerMT and\n// ServerST will be derived.\n\n#ifndef __RFB_SERVER_CORE_H__\n#define __RFB_SERVER_CORE_H__\n\n#include <core/Configuration.h>\n\nnamespace rfb {\n\n  class Server {\n  public:\n\n    static core::IntParameter idleTimeout;\n    static core::IntParameter maxDisconnectionTime;\n    static core::IntParameter maxConnectionTime;\n    static core::IntParameter maxIdleTime;\n    static core::IntParameter compareFB;\n    static core::IntParameter frameRate;\n    static core::BoolParameter protocol3_3;\n    static core::BoolParameter alwaysShared;\n    static core::BoolParameter neverShared;\n    static core::BoolParameter disconnectClients;\n    static core::BoolParameter acceptKeyEvents;\n    static core::BoolParameter acceptPointerEvents;\n    static core::BoolParameter acceptCutText;\n    static core::BoolParameter sendCutText;\n    static core::BoolParameter acceptSetDesktopSize;\n    static core::BoolParameter queryConnect;\n\n  };\n\n};\n\n#endif // __RFB_SERVER_CORE_H__\n\n"
  },
  {
    "path": "common/rfb/ServerParams.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdexcept>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb/ledStates.h>\n#include <rfb/Cursor.h>\n#include <rfb/ScreenSet.h>\n#include <rfb/ServerParams.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"ServerParams\");\n\nServerParams::ServerParams()\n  : majorVersion(0), minorVersion(0),\n    supportsQEMUKeyEvent(false),\n    supportsSetDesktopSize(false), supportsFence(false),\n    supportsContinuousUpdates(false), supportsExtendedMouseButtons(false),\n    width_(0), height_(0),\n    ledState_(ledUnknown)\n{\n  setName(\"\");\n\n  screenLayout_ = new ScreenSet();\n\n  pf_ = new PixelFormat();\n\n  cursor_ = new Cursor(0, 0, {}, nullptr);\n\n  clipFlags = 0;\n  memset(clipSizes, 0, sizeof(clipSizes));\n}\n\nServerParams::~ServerParams()\n{\n  delete cursor_;\n}\n\nvoid ServerParams::setDimensions(int width, int height)\n{\n  ScreenSet layout;\n  layout.add_screen(rfb::Screen(0, 0, 0, width, height, 0));\n  setDimensions(width, height, layout);\n}\n\nvoid ServerParams::setDimensions(int width, int height, const ScreenSet& layout)\n{\n  if (!layout.validate(width, height)) {\n    char buffer[2048];\n    vlog.debug(\"Invalid screen layout for %dx%d:\", width, height);\n    layout.print(buffer, sizeof(buffer));\n    vlog.debug(\"%s\", buffer);\n\n    throw std::invalid_argument(\"Attempted to configure an invalid screen layout\");\n  }\n\n  width_ = width;\n  height_ = height;\n  delete screenLayout_;\n  screenLayout_ = new ScreenSet(layout);\n}\n\nvoid ServerParams::setPF(const PixelFormat& pf)\n{\n  delete pf_;\n  pf_ = new PixelFormat(pf);\n\n  if (pf.bpp != 8 && pf.bpp != 16 && pf.bpp != 32)\n    throw std::invalid_argument(\"setPF: Not 8, 16 or 32 bpp?\");\n}\n\nvoid ServerParams::setName(const char* name)\n{\n  name_ = name;\n}\n\nvoid ServerParams::setCursor(const Cursor& other)\n{\n  delete cursor_;\n  cursor_ = new Cursor(other);\n}\n\nvoid ServerParams::setLEDState(unsigned int state)\n{\n  ledState_ = state;\n}\n\nuint32_t ServerParams::clipboardSize(unsigned int format) const\n{\n  int i;\n\n  for (i = 0;i < 16;i++) {\n    if (((unsigned)1 << i) == format)\n      return clipSizes[i];\n  }\n\n  throw std::invalid_argument(\n    core::format(\"Invalid clipboard format 0x%x\", format));\n}\n\nvoid ServerParams::setClipboardCaps(uint32_t flags, const uint32_t* lengths)\n{\n  int i, num;\n\n  clipFlags = flags;\n\n  num = 0;\n  for (i = 0;i < 16;i++) {\n    if (!(flags & (1 << i)))\n      continue;\n    clipSizes[i] = lengths[num++];\n  }\n}\n"
  },
  {
    "path": "common/rfb/ServerParams.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// ServerParams - structure describing the current state of the remote server\n//\n\n#ifndef __RFB_SERVERPARAMS_H__\n#define __RFB_SERVERPARAMS_H__\n\n#include <string>\n\nnamespace rfb {\n\n  class Cursor;\n  class PixelFormat;\n  struct ScreenSet;\n\n  class ServerParams {\n  public:\n    ServerParams();\n    ~ServerParams();\n\n    int majorVersion;\n    int minorVersion;\n\n    void setVersion(int major, int minor) {\n      majorVersion = major; minorVersion = minor;\n    }\n    bool isVersion(int major, int minor) const {\n      return majorVersion == major && minorVersion == minor;\n    }\n    bool beforeVersion(int major, int minor) const {\n      return (majorVersion < major ||\n              (majorVersion == major && minorVersion < minor));\n    }\n    bool afterVersion(int major, int minor) const {\n      return !beforeVersion(major,minor+1);\n    }\n\n    int width() const { return width_; }\n    int height() const { return height_; }\n    const ScreenSet& screenLayout() const { return *screenLayout_; }\n    void setDimensions(int width, int height);\n    void setDimensions(int width, int height, const ScreenSet& layout);\n\n    const PixelFormat& pf() const { return *pf_; }\n    void setPF(const PixelFormat& pf);\n\n    const char* name() const { return name_.c_str(); }\n    void setName(const char* name);\n\n    const Cursor& cursor() const { return *cursor_; }\n    void setCursor(const Cursor& cursor);\n\n    unsigned int ledState() { return ledState_; }\n    void setLEDState(unsigned int state);\n\n    uint32_t clipboardFlags() const { return clipFlags; }\n    uint32_t clipboardSize(unsigned int format) const;\n    void setClipboardCaps(uint32_t flags, const uint32_t* lengths);\n\n    bool supportsQEMUKeyEvent;\n    bool supportsSetDesktopSize;\n    bool supportsFence;\n    bool supportsContinuousUpdates;\n    bool supportsExtendedMouseButtons;\n\n  private:\n\n    int width_;\n    int height_;\n    ScreenSet* screenLayout_;\n\n    PixelFormat* pf_;\n    std::string name_;\n    Cursor* cursor_;\n    unsigned int ledState_;\n    uint32_t clipFlags;\n    uint32_t clipSizes[16];\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/TightConstants.h",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_TIGHTCONSTANTS_H__\n#define __RFB_TIGHTCONSTANTS_H__\nnamespace rfb {\n  // Compression control \n  const unsigned int tightExplicitFilter = 0x04;\n  const unsigned int tightFill = 0x08;\n  const unsigned int tightJpeg = 0x09;\n  const unsigned int tightMaxSubencoding = 0x09;\n\n  // Filters to improve compression efficiency\n  const unsigned int tightFilterCopy = 0x00;\n  const unsigned int tightFilterPalette = 0x01;\n  const unsigned int tightFilterGradient = 0x02;\n}\n#endif\n"
  },
  {
    "path": "common/rfb/TightDecoder.cxx",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright 2004-2005 Cendio AB.\n * Copyright 2009-2022 Pierre Ossman for Cendio AB\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <vector>\n\n#include <core/string.h>\n\n#include <rdr/InStream.h>\n#include <rdr/MemInStream.h>\n#include <rdr/OutStream.h>\n\n#include <rfb/ServerParams.h>\n#include <rfb/Exception.h>\n#include <rfb/JpegDecompressor.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/TightConstants.h>\n#include <rfb/TightDecoder.h>\n\nusing namespace rfb;\n\nstatic const int TIGHT_MAX_WIDTH = 2048;\nstatic const int TIGHT_MIN_TO_COMPRESS = 12;\n\nTightDecoder::TightDecoder()\n  : Decoder(DecoderPartiallyOrdered), readState(IDLE)\n{\n}\n\nTightDecoder::~TightDecoder()\n{\n}\n\nbool TightDecoder::readRect(const core::Rect& r, rdr::InStream* is,\n                            const ServerParams& server, rdr::OutStream* os)\n{\n  if (readState == IDLE) {\n    uint8_t comp_ctl;\n\n    if (!is->hasData(1))\n      return false;\n\n    comp_ctl = is->readU8();\n    os->writeU8(comp_ctl);\n\n    comp_ctl >>= 4;\n\n    // Quit on unsupported compression type.\n    if (comp_ctl > tightMaxSubencoding)\n      throw protocol_error(\"TightDecoder: Bad subencoding value received\");\n\n    if (comp_ctl == tightFill)\n      readState = FILL;\n    else if (comp_ctl == tightJpeg)\n      readState = JPEG;\n    else {\n      readPalSize = 0;\n      if ((comp_ctl & tightExplicitFilter) != 0)\n        readState = FILTER;\n      else\n        readState = PIXELS;\n    }\n  }\n\n  // \"Fill\" compression type.\n  if (readState == FILL) {\n    if (server.pf().is888()) {\n      if (!is->hasData(3))\n        return false;\n      os->copyBytes(is, 3);\n    } else {\n      if (!is->hasData(server.pf().bpp/8))\n        return false;\n      os->copyBytes(is, server.pf().bpp/8);\n    }\n    readState = IDLE;\n    return true;\n  }\n\n  // FIXME: This check should be for all Tight types, but TigerVNC\n  //        servers until 1.16.0 were buggy and sent larger rects for\n  //        fill type rectangles.\n  if (r.width() > TIGHT_MAX_WIDTH)\n    throw protocol_error(core::format(\n      \"TightDecoder: Too large rectangle (%d pixels)\", r.width()));\n\n  // \"JPEG\" compression type.\n  if (readState == JPEG) {\n    uint32_t len;\n\n    // FIXME: Might be less than 3 bytes\n    if (!is->hasData(3))\n      return false;\n\n    is->setRestorePoint();\n\n    len = readCompact(is);\n\n    if (!is->hasDataOrRestore(len))\n      return false;\n\n    os->writeOpaque32(len);\n    os->copyBytes(is, len);\n\n    is->clearRestorePoint();\n\n    readState = IDLE;\n    return true;\n  }\n\n  // \"Basic\" compression type.\n\n  // Possible palette\n  if (readState == FILTER) {\n    uint8_t filterId;\n\n    if (!is->hasData(1))\n      return false;\n\n    filterId = is->readU8();\n    os->writeU8(filterId);\n\n    switch (filterId) {\n    case tightFilterPalette:\n      readState = PALETTE;\n      break;\n    case tightFilterGradient:\n      if (server.pf().bpp == 8)\n        throw protocol_error(\"TightDecoder: Invalid BPP for gradient filter\");\n      readState = PIXELS;\n      break;\n    case tightFilterCopy:\n      readState = PIXELS;\n      break;\n    default:\n      throw protocol_error(\"TightDecoder: Unknown filter code received\");\n    }\n  }\n\n  if (readState == PALETTE) {\n    if (!is->hasData(1))\n      return false;\n\n    is->setRestorePoint();\n\n    readPalSize = is->readU8() + 1;\n\n    if (server.pf().is888()) {\n      if (!is->hasDataOrRestore(readPalSize * 3))\n        return false;\n      os->writeU8(readPalSize - 1);\n      os->copyBytes(is, readPalSize * 3);\n    } else {\n      if (!is->hasDataOrRestore(readPalSize * server.pf().bpp/8))\n        return false;\n      os->writeU8(readPalSize - 1);\n      os->copyBytes(is, readPalSize * server.pf().bpp/8);\n    }\n\n    is->clearRestorePoint();\n\n    readState = PIXELS;\n  }\n\n  assert(readState == PIXELS);\n\n  size_t rowSize, dataSize;\n\n  if (readPalSize != 0) {\n    if (readPalSize <= 2)\n      rowSize = (r.width() + 7) / 8;\n    else\n      rowSize = r.width();\n  } else if (server.pf().is888()) {\n    rowSize = r.width() * 3;\n  } else {\n    rowSize = r.width() * server.pf().bpp/8;\n  }\n\n  dataSize = r.height() * rowSize;\n\n  if (dataSize < TIGHT_MIN_TO_COMPRESS) {\n    if (!is->hasData(dataSize))\n      return false;\n    os->copyBytes(is, dataSize);\n  } else {\n    uint32_t len;\n\n    // FIXME: Might be less than 3 bytes\n    if (!is->hasData(3))\n      return false;\n\n    is->setRestorePoint();\n\n    len = readCompact(is);\n\n    if (!is->hasDataOrRestore(len))\n      return false;\n\n    os->writeOpaque32(len);\n    os->copyBytes(is, len);\n\n    is->clearRestorePoint();\n  }\n\n  readState = IDLE;\n  return true;\n}\n\nbool TightDecoder::doRectsConflict(const core::Rect& /*rectA*/,\n                                   const uint8_t* bufferA,\n                                   size_t buflenA,\n                                   const core::Rect& /*rectB*/,\n                                   const uint8_t* bufferB,\n                                   size_t buflenB,\n                                   const ServerParams& /*server*/)\n{\n  uint8_t comp_ctl_a, comp_ctl_b;\n\n  assert(buflenA >= 1);\n  assert(buflenB >= 1);\n\n  comp_ctl_a = *(const uint8_t*)bufferA;\n  comp_ctl_b = *(const uint8_t*)bufferB;\n\n  // Resets or use of zlib pose the same problem, so merge them\n  if ((comp_ctl_a & 0x80) == 0x00)\n    comp_ctl_a |= 1 << ((comp_ctl_a >> 4) & 0x03);\n  if ((comp_ctl_b & 0x80) == 0x00)\n    comp_ctl_b |= 1 << ((comp_ctl_b >> 4) & 0x03);\n\n  if (((comp_ctl_a & 0x0f) & (comp_ctl_b & 0x0f)) != 0)\n    return true;\n\n  return false;\n}\n\nvoid TightDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,\n                              size_t buflen, const ServerParams& server,\n                              ModifiablePixelBuffer* pb)\n{\n  const uint8_t* bufptr;\n  const PixelFormat& pf = server.pf();\n\n  uint8_t comp_ctl;\n\n  bufptr = (const uint8_t*)buffer;\n\n  assert(buflen >= 1);\n\n  comp_ctl = *bufptr;\n  bufptr += 1;\n  buflen -= 1;\n\n  // Reset zlib streams if we are told by the server to do so.\n  for (int i = 0; i < 4; i++) {\n    if (comp_ctl & 1) {\n      zis[i].reset();\n    }\n    comp_ctl >>= 1;\n  }\n\n  // \"Fill\" compression type.\n  if (comp_ctl == tightFill) {\n    if (pf.is888()) {\n      uint8_t pix[4];\n\n      assert(buflen >= 3);\n\n      pf.bufferFromRGB(pix, bufptr, 1);\n      pb->fillRect(pf, r, pix);\n    } else {\n      assert(buflen >= (size_t)pf.bpp/8);\n      pb->fillRect(pf, r, bufptr);\n    }\n    return;\n  }\n\n  // \"JPEG\" compression type.\n  if (comp_ctl == tightJpeg) {\n    uint32_t len;\n\n    int stride;\n    uint8_t *buf;\n\n    JpegDecompressor jd;\n\n    assert(buflen >= 4);\n\n    memcpy(&len, bufptr, 4);\n    bufptr += 4;\n    buflen -= 4;\n\n    // We always use direct decoding with JPEG images\n    buf = pb->getBufferRW(r, &stride);\n    jd.decompress(bufptr, len, buf, stride, r, pb->getPF());\n    pb->commitBufferRW(r);\n    return;\n  }\n\n  // Quit on unsupported compression type.\n  assert(comp_ctl <= tightMaxSubencoding);\n\n  // \"Basic\" compression type.\n\n  int palSize = 0;\n  uint8_t palette[256 * 4];\n  bool useGradient = false;\n\n  if ((comp_ctl & tightExplicitFilter) != 0) {\n    uint8_t filterId;\n\n    assert(buflen >= 1);\n\n    filterId = *bufptr;\n    bufptr += 1;\n    buflen -= 1;\n\n    switch (filterId) {\n    case tightFilterPalette:\n      assert(buflen >= 1);\n\n      palSize = *bufptr + 1;\n      bufptr += 1;\n      buflen -= 1;\n\n      if (pf.is888()) {\n        size_t len = palSize * 3;\n        std::vector<uint8_t> tightPalette(len);\n\n        assert(buflen >= len);\n\n        memcpy(tightPalette.data(), bufptr, len);\n        bufptr += len;\n        buflen -= len;\n\n        pf.bufferFromRGB(palette, tightPalette.data(), palSize);\n      } else {\n        size_t len;\n\n        len = palSize * pf.bpp/8;\n\n        assert(buflen >= len);\n\n        memcpy(palette, bufptr, len);\n        bufptr += len;\n        buflen -= len;\n      }\n      break;\n    case tightFilterGradient:\n      useGradient = true;\n      break;\n    case tightFilterCopy:\n      break;\n    default:\n      assert(false);\n    }\n  }\n\n  // Determine if the data should be decompressed or just copied.\n  size_t rowSize, dataSize;\n  uint8_t* netbuf;\n\n  netbuf = nullptr;\n\n  if (palSize != 0) {\n    if (palSize <= 2)\n      rowSize = (r.width() + 7) / 8;\n    else\n      rowSize = r.width();\n  } else if (pf.is888()) {\n    rowSize = r.width() * 3;\n  } else {\n    rowSize = r.width() * pf.bpp/8;\n  }\n\n  dataSize = r.height() * rowSize;\n\n  if (dataSize < TIGHT_MIN_TO_COMPRESS)\n    assert(buflen >= dataSize);\n  else {\n    uint32_t len;\n    int streamId;\n    rdr::MemInStream* ms;\n\n    assert(buflen >= 4);\n\n    memcpy(&len, bufptr, 4);\n    bufptr += 4;\n    buflen -= 4;\n\n    assert(buflen >= len);\n\n    streamId = comp_ctl & 0x03;\n    ms = new rdr::MemInStream(bufptr, len);\n    zis[streamId].setUnderlying(ms, len);\n\n    // Allocate buffer and decompress the data\n    netbuf = new uint8_t[dataSize];\n\n    if (!zis[streamId].hasData(dataSize))\n      throw protocol_error(\"Tight decode error\");\n    zis[streamId].readBytes(netbuf, dataSize);\n\n    zis[streamId].flushUnderlying();\n    zis[streamId].setUnderlying(nullptr, 0);\n    delete ms;\n\n    bufptr = netbuf;\n    buflen = dataSize;\n  }\n\n  // Time to decode the actual data\n  bool directDecode;\n\n  uint8_t* outbuf;\n  int stride;\n\n  if (pb->getPF() == pf) {\n    // Decode directly into the framebuffer (fast path)\n    directDecode = true;\n  } else {\n    // Decode into an intermediate buffer and use pixel translation\n    directDecode = false;\n  }\n\n  if (directDecode)\n    outbuf = pb->getBufferRW(r, &stride);\n  else {\n    outbuf = new uint8_t[r.area() * (pf.bpp/8)];\n    stride = r.width();\n  }\n\n  if (palSize == 0) {\n    // Truecolor data\n    if (useGradient) {\n      if (pf.is888())\n        FilterGradient24(bufptr, pf, (uint32_t*)outbuf, stride, r);\n      else {\n        switch (pf.bpp) {\n        case 8:\n          assert(false);\n          break;\n        case 16:\n          FilterGradient(bufptr, pf, (uint16_t*)outbuf, stride, r);\n          break;\n        case 32:\n          FilterGradient(bufptr, pf, (uint32_t*)outbuf, stride, r);\n          break;\n        }\n      }\n    } else {\n      // Copy\n      uint8_t* ptr = outbuf;\n      const uint8_t* srcPtr = bufptr;\n      int w = r.width();\n      int h = r.height();\n      if (pf.is888()) {\n        while (h > 0) {\n          pf.bufferFromRGB(ptr, srcPtr, w);\n          ptr += stride * pf.bpp/8;\n          srcPtr += w * 3;\n          h--;\n        }\n      } else {\n        while (h > 0) {\n          memcpy(ptr, srcPtr, w * pf.bpp/8);\n          ptr += stride * pf.bpp/8;\n          srcPtr += w * pf.bpp/8;\n          h--;\n        }\n      }\n    }\n  } else {\n    // Indexed color\n    switch (pf.bpp) {\n    case 8:\n      FilterPalette((const uint8_t*)palette, palSize,\n                    bufptr, (uint8_t*)outbuf, stride, r);\n      break;\n    case 16:\n      FilterPalette((const uint16_t*)palette, palSize,\n                    bufptr, (uint16_t*)outbuf, stride, r);\n      break;\n    case 32:\n      FilterPalette((const uint32_t*)palette, palSize,\n                    bufptr, (uint32_t*)outbuf, stride, r);\n      break;\n    }\n  }\n\n  if (directDecode)\n    pb->commitBufferRW(r);\n  else {\n    pb->imageRect(pf, r, outbuf);\n    delete [] outbuf;\n  }\n\n  delete [] netbuf;\n}\n\nuint32_t TightDecoder::readCompact(rdr::InStream* is)\n{\n  uint8_t b;\n  uint32_t result;\n\n  b = is->readU8();\n  result = (int)b & 0x7F;\n  if (b & 0x80) {\n    b = is->readU8();\n    result |= ((int)b & 0x7F) << 7;\n    if (b & 0x80) {\n      b = is->readU8();\n      result |= ((int)b & 0xFF) << 14;\n    }\n  }\n\n  return result;\n}\n\nvoid\nTightDecoder::FilterGradient24(const uint8_t *inbuf,\n                               const PixelFormat& pf, uint32_t* outbuf,\n                               int stride, const core::Rect& r)\n{\n  int x, y, c;\n  uint8_t prevRow[TIGHT_MAX_WIDTH*3];\n  uint8_t thisRow[TIGHT_MAX_WIDTH*3];\n  uint8_t pix[3]; \n  int est[3]; \n\n  memset(prevRow, 0, sizeof(prevRow));\n\n  // Set up shortcut variables\n  int rectHeight = r.height();\n  int rectWidth = r.width();\n\n  for (y = 0; y < rectHeight; y++) {\n    for (x = 0; x < rectWidth; x++) {\n      /* First pixel in a row */\n      if (x == 0) {\n        for (c = 0; c < 3; c++) {\n          pix[c] = inbuf[y*rectWidth*3+c] + prevRow[c];\n          thisRow[c] = pix[c];\n        }\n        pf.bufferFromRGB((uint8_t*)&outbuf[y*stride], pix, 1);\n        continue;\n      }\n\n      for (c = 0; c < 3; c++) {\n        est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];\n        if (est[c] > 0xff) {\n          est[c] = 0xff;\n        } else if (est[c] < 0) {\n          est[c] = 0;\n        }\n        pix[c] = inbuf[(y*rectWidth+x)*3+c] + est[c];\n        thisRow[x*3+c] = pix[c];\n      }\n      pf.bufferFromRGB((uint8_t*)&outbuf[y*stride+x], pix, 1);\n    }\n\n    memcpy(prevRow, thisRow, sizeof(prevRow));\n  }\n}\n\ntemplate<class T>\nvoid TightDecoder::FilterGradient(const uint8_t* inbuf,\n                                  const PixelFormat& pf, T* outbuf,\n                                  int stride, const core::Rect& r)\n{\n  int x, y, c;\n  static uint8_t prevRow[TIGHT_MAX_WIDTH*3];\n  static uint8_t thisRow[TIGHT_MAX_WIDTH*3];\n  uint8_t pix[3]; \n  int est[3]; \n\n  memset(prevRow, 0, sizeof(prevRow));\n\n  // Set up shortcut variables\n  int rectHeight = r.height();\n  int rectWidth = r.width();\n\n  for (y = 0; y < rectHeight; y++) {\n    for (x = 0; x < rectWidth; x++) {\n      /* First pixel in a row */\n      if (x == 0) {\n        pf.rgbFromBuffer(pix, &inbuf[y*rectWidth], 1);\n        for (c = 0; c < 3; c++)\n          pix[c] += prevRow[c];\n\n        memcpy(thisRow, pix, sizeof(pix));\n\n        pf.bufferFromRGB((uint8_t*)&outbuf[y*stride], pix, 1);\n\n        continue;\n      }\n\n      for (c = 0; c < 3; c++) {\n        est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];\n        if (est[c] > 255) {\n          est[c] = 255;\n        } else if (est[c] < 0) {\n          est[c] = 0;\n        }\n      }\n\n      pf.rgbFromBuffer(pix, &inbuf[y*rectWidth+x], 1);\n      for (c = 0; c < 3; c++)\n        pix[c] += est[c];\n\n      memcpy(&thisRow[x*3], pix, sizeof(pix));\n\n      pf.bufferFromRGB((uint8_t*)&outbuf[y*stride+x], pix, 1);\n    }\n\n    memcpy(prevRow, thisRow, sizeof(prevRow));\n  }\n}\n\ntemplate<class T>\nvoid TightDecoder::FilterPalette(const T* palette, int palSize,\n                                 const uint8_t* inbuf, T* outbuf,\n                                 int stride, const core::Rect& r)\n{\n  // Indexed color\n  int x, h = r.height(), w = r.width(), b, pad = stride - w;\n  T* ptr = outbuf;\n  uint8_t bits;\n  const uint8_t* srcPtr = inbuf;\n  if (palSize <= 2) {\n    // 2-color palette\n    while (h > 0) {\n      for (x = 0; x < w / 8; x++) {\n        bits = *srcPtr++;\n        for (b = 7; b >= 0; b--) {\n          *ptr++ = palette[bits >> b & 1];\n        }\n      }\n      if (w % 8 != 0) {\n        bits = *srcPtr++;\n        for (b = 7; b >= 8 - w % 8; b--) {\n          *ptr++ = palette[bits >> b & 1];\n        }\n      }\n      ptr += pad;\n      h--;\n    }\n  } else {\n    // 256-color palette\n    while (h > 0) {\n      T *endOfRow = ptr + w;\n      while (ptr < endOfRow) {\n        *ptr++ = palette[*srcPtr++];\n      }\n      ptr += pad;\n      h--;\n    }\n  }\n}\n"
  },
  {
    "path": "common/rfb/TightDecoder.h",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2009-2022 Pierre Ossman for Cendio AB\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_TIGHTDECODER_H__\n#define __RFB_TIGHTDECODER_H__\n\n#include <rdr/ZlibInStream.h>\n#include <rfb/Decoder.h>\n\nnamespace rfb {\n\n  class TightDecoder : public Decoder {\n\n  public:\n    TightDecoder();\n    virtual ~TightDecoder();\n    bool readRect(const core::Rect& r, rdr::InStream* is,\n                  const ServerParams& server,\n                  rdr::OutStream* os) override;\n    bool doRectsConflict(const core::Rect& rectA,\n                         const uint8_t* bufferA, size_t buflenA,\n                         const core::Rect& rectB,\n                         const uint8_t* bufferB, size_t buflenB,\n                         const ServerParams& server) override;\n    void decodeRect(const core::Rect& r, const uint8_t* buffer,\n                    size_t buflen, const ServerParams& server,\n                    ModifiablePixelBuffer* pb) override;\n\n  private:\n    uint32_t readCompact(rdr::InStream* is);\n\n    void FilterGradient24(const uint8_t* inbuf, const PixelFormat& pf,\n                          uint32_t* outbuf, int stride, const core::Rect& r);\n\n    template<class T>\n    void FilterGradient(const uint8_t* inbuf, const PixelFormat& pf,\n                        T* outbuf, int stride, const core::Rect& r);\n\n    template<class T>\n    void FilterPalette(const T* palette, int palSize,\n                       const uint8_t* inbuf, T* outbuf,\n                       int stride, const core::Rect& r);\n\n  private:\n    enum {\n      IDLE,\n      FILL,\n      JPEG,\n      FILTER,\n      PALETTE,\n      PIXELS,\n    } readState;\n    int readPalSize;\n\n    rdr::ZlibInStream zis[4];\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/TightEncoder.cxx",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <rdr/OutStream.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/Palette.h>\n#include <rfb/encodings.h>\n#include <rfb/SConnection.h>\n#include <rfb/TightEncoder.h>\n#include <rfb/TightConstants.h>\n\nusing namespace rfb;\n\nstatic const int TIGHT_MAX_WIDTH = 2048;\n\nstruct TightConf {\n  int idxZlibLevel, monoZlibLevel, rawZlibLevel;\n};\n\n//\n// Compression level stuff. The following array contains zlib\n// settings for each of 10 compression levels (0..9).\n//\n// NOTE: The parameters used in this encoder are the result of painstaking\n// research by The VirtualGL project using RFB session captures from a variety\n// of both 2D and 3D applications.  See http://www.VirtualGL.org for the full\n// reports.\n\nstatic const TightConf conf[10] = {\n  { 0, 0, 0 }, // 0\n  { 1, 1, 1 }, // 1\n  { 3, 3, 2 }, // 2\n  { 5, 5, 2 }, // 3\n  { 6, 7, 3 }, // 4\n  { 7, 8, 4 }, // 5\n  { 7, 8, 5 }, // 6\n  { 8, 9, 6 }, // 7\n  { 9, 9, 7 }, // 8\n  { 9, 9, 9 }  // 9\n};\n\nTightEncoder::TightEncoder(SConnection* conn_) :\n  Encoder(conn_, encodingTight, EncoderPlain, 256)\n{\n  setCompressLevel(-1);\n}\n\nTightEncoder::~TightEncoder()\n{\n}\n\nbool TightEncoder::isSupported()\n{\n  return conn->client.supportsEncoding(encodingTight);\n}\n\nvoid TightEncoder::setCompressLevel(int level)\n{\n  if (level < 0 || level > 9)\n    level = 2;\n\n  idxZlibLevel = conf[level].idxZlibLevel;\n  monoZlibLevel = conf[level].monoZlibLevel;\n  rawZlibLevel = conf[level].rawZlibLevel;\n}\n\nvoid TightEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)\n{\n  assert(pb->width() <= TIGHT_MAX_WIDTH);\n\n  switch (palette.size()) {\n  case 0:\n    writeFullColourRect(pb);\n    break;\n  case 1:\n    Encoder::writeSolidRect(pb, palette);\n    break;\n  case 2:\n    writeMonoRect(pb, palette);\n    break;\n  default:\n    writeIndexedRect(pb, palette);\n  }\n}\n\nvoid TightEncoder::writeSolidRect(int width, int /*height*/,\n                                  const PixelFormat& pf,\n                                  const uint8_t* colour)\n{\n  rdr::OutStream* os;\n\n  assert(width <= TIGHT_MAX_WIDTH);\n\n  os = conn->getOutStream();\n\n  os->writeU8(tightFill << 4);\n  writePixels(colour, pf, 1, os);\n}\n\nvoid TightEncoder::writeMonoRect(const PixelBuffer* pb, const Palette& palette)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  buffer = pb->getBuffer(pb->getRect(), &stride);\n\n  switch (pb->getPF().bpp) {\n  case 32:\n    writeMonoRect(pb->width(), pb->height(), (uint32_t*)buffer, stride,\n                  pb->getPF(), palette);\n    break;\n  case 16:\n    writeMonoRect(pb->width(), pb->height(), (uint16_t*)buffer, stride,\n                  pb->getPF(), palette);\n    break;\n  default:\n    writeMonoRect(pb->width(), pb->height(), (uint8_t*)buffer, stride,\n                  pb->getPF(), palette);\n  }\n}\n\nvoid TightEncoder::writeIndexedRect(const PixelBuffer* pb, const Palette& palette)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  buffer = pb->getBuffer(pb->getRect(), &stride);\n\n  switch (pb->getPF().bpp) {\n  case 32:\n    writeIndexedRect(pb->width(), pb->height(), (uint32_t*)buffer, stride,\n                     pb->getPF(), palette);\n    break;\n  case 16:\n    writeIndexedRect(pb->width(), pb->height(), (uint16_t*)buffer, stride,\n                     pb->getPF(), palette);\n    break;\n  default:\n    // It's more efficient to just do raw pixels\n    writeFullColourRect(pb);\n  }\n}\n\nvoid TightEncoder::writeFullColourRect(const PixelBuffer* pb)\n{\n  const int streamId = 0;\n\n  rdr::OutStream* os;\n  rdr::OutStream* zos;\n  int length;\n\n  const uint8_t* buffer;\n  int stride, h;\n\n  os = conn->getOutStream();\n\n  os->writeU8(streamId << 4);\n\n  // Set up compression\n  if ((pb->getPF().bpp != 32) || !pb->getPF().is888())\n    length = pb->getRect().area() * pb->getPF().bpp/8;\n  else\n    length = pb->getRect().area() * 3;\n\n  zos = getZlibOutStream(streamId, rawZlibLevel, length);\n\n  // And then just dump all the raw pixels\n  buffer = pb->getBuffer(pb->getRect(), &stride);\n  h = pb->height();\n\n  while (h--) {\n    writePixels(buffer, pb->getPF(), pb->width(), zos);\n    buffer += stride * pb->getPF().bpp/8;\n  }\n\n  // Finish the zlib stream\n  flushZlibOutStream(zos);\n}\n\nvoid TightEncoder::writePixels(const uint8_t* buffer, const PixelFormat& pf,\n                               unsigned int count, rdr::OutStream* os)\n{\n  uint8_t rgb[2048];\n\n  if ((pf.bpp != 32) || !pf.is888()) {\n    os->writeBytes(buffer, count * pf.bpp/8);\n    return;\n  }\n\n  while (count) {\n    unsigned int iter_count;\n\n    iter_count = sizeof(rgb)/3;\n    if (iter_count > count)\n      iter_count = count;\n\n    pf.rgbFromBuffer(rgb, buffer, iter_count);\n    os->writeBytes(rgb, iter_count * 3);\n\n    buffer += iter_count * pf.bpp/8;\n    count -= iter_count;\n  }\n}\n\nvoid TightEncoder::writeCompact(rdr::OutStream* os, uint32_t value)\n{\n  uint8_t b;\n  b = value & 0x7F;\n  if (value <= 0x7F) {\n    os->writeU8(b);\n  } else {\n    os->writeU8(b | 0x80);\n    b = value >> 7 & 0x7F;\n    if (value <= 0x3FFF) {\n      os->writeU8(b);\n    } else {\n      os->writeU8(b | 0x80);\n      os->writeU8(value >> 14 & 0xFF);\n    }\n  }\n}\n\nrdr::OutStream* TightEncoder::getZlibOutStream(int streamId, int level, size_t length)\n{\n  // Minimum amount of data to be compressed. This value should not be\n  // changed, doing so will break compatibility with existing clients.\n  if (length < 12)\n    return conn->getOutStream();\n\n  assert(streamId >= 0);\n  assert(streamId < 4);\n\n  zlibStreams[streamId].setUnderlying(&memStream);\n  zlibStreams[streamId].setCompressionLevel(level);\n  zlibStreams[streamId].cork(true);\n\n  return &zlibStreams[streamId];\n}\n\nvoid TightEncoder::flushZlibOutStream(rdr::OutStream* os_)\n{\n  rdr::OutStream* os;\n  rdr::ZlibOutStream* zos;\n\n  zos = dynamic_cast<rdr::ZlibOutStream*>(os_);\n  if (zos == nullptr)\n    return;\n\n  zos->cork(false);\n  zos->flush();\n  zos->setUnderlying(nullptr);\n\n  os = conn->getOutStream();\n\n  writeCompact(os, memStream.length());\n  os->writeBytes(memStream.data(), memStream.length());\n  memStream.clear();\n}\n\ntemplate<class T>\nvoid TightEncoder::writeMonoRect(int width, int height,\n                                 const T* buffer, int stride,\n                                 const PixelFormat& pf,\n                                 const Palette& palette)\n{\n  rdr::OutStream* os;\n\n  const int streamId = 1;\n  T pal[2];\n\n  int length;\n  rdr::OutStream* zos;\n\n  assert(palette.size() == 2);\n\n  os = conn->getOutStream();\n\n  os->writeU8((streamId | tightExplicitFilter) << 4);\n  os->writeU8(tightFilterPalette);\n\n  // Write the palette\n  pal[0] = (T)palette.getColour(0);\n  pal[1] = (T)palette.getColour(1);\n\n  os->writeU8(1);\n  writePixels((uint8_t*)pal, pf, 2, os);\n\n  // Set up compression\n  length = (width + 7)/8 * height;\n  zos = getZlibOutStream(streamId, monoZlibLevel, length);\n\n  // Encode the data\n  T bg;\n  unsigned int value, mask;\n  int pad, aligned_width;\n  int x, y, bg_bits;\n\n  bg = pal[0];\n  aligned_width = width - width % 8;\n  pad = stride - width;\n\n  for (y = 0; y < height; y++) {\n    for (x = 0; x < aligned_width; x += 8) {\n      for (bg_bits = 0; bg_bits < 8; bg_bits++) {\n        if (*buffer++ != bg)\n          break;\n      }\n      if (bg_bits == 8) {\n        zos->writeU8(0);\n        continue;\n      }\n      mask = 0x80 >> bg_bits;\n      value = mask;\n      for (bg_bits++; bg_bits < 8; bg_bits++) {\n        mask >>= 1;\n        if (*buffer++ != bg) {\n          value |= mask;\n        }\n      }\n      zos->writeU8(value);\n    }\n\n    if (x < width) {\n      mask = 0x80;\n      value = 0;\n\n      for (; x < width; x++) {\n        if (*buffer++ != bg) {\n          value |= mask;\n        }\n        mask >>= 1;\n      }\n      zos->writeU8(value);\n    }\n\n    buffer += pad;\n  }\n\n  // Finish the zlib stream\n  flushZlibOutStream(zos);\n}\n\ntemplate<class T>\nvoid TightEncoder::writeIndexedRect(int width, int height,\n                                    const T* buffer, int stride,\n                                    const PixelFormat& pf,\n                                    const Palette& palette)\n{\n  rdr::OutStream* os;\n\n  const int streamId = 2;\n  T pal[256];\n\n  rdr::OutStream* zos;\n\n  int pad;\n  T prevColour;\n  unsigned char idx;\n\n  assert(palette.size() > 0);\n  assert(palette.size() <= 256);\n\n  os = conn->getOutStream();\n\n  os->writeU8((streamId | tightExplicitFilter) << 4);\n  os->writeU8(tightFilterPalette);\n\n  // Write the palette\n  for (int i = 0; i < palette.size(); i++)\n    pal[i] = (T)palette.getColour(i);\n\n  os->writeU8(palette.size() - 1);\n  writePixels((uint8_t*)pal, pf, palette.size(), os);\n\n  // Set up compression\n  zos = getZlibOutStream(streamId, idxZlibLevel, width * height);\n\n  // Encode the data\n  pad = stride - width;\n\n  prevColour = *buffer;\n  idx = palette.lookup(*buffer);\n\n  while (height--) {\n    int w = width;\n    while (w--) {\n      if (*buffer != prevColour) {\n        prevColour = *buffer;\n        idx = palette.lookup(*buffer);\n      }\n      zos->writeU8(idx);\n      buffer++;\n    }\n    buffer += pad;\n  }\n\n  // Finish the zlib stream\n  flushZlibOutStream(zos);\n}\n"
  },
  {
    "path": "common/rfb/TightEncoder.h",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_TIGHTENCODER_H__\n#define __RFB_TIGHTENCODER_H__\n\n#include <rdr/MemOutStream.h>\n#include <rdr/ZlibOutStream.h>\n#include <rfb/Encoder.h>\n\nnamespace rfb {\n\n  class TightEncoder : public Encoder {\n  public:\n    TightEncoder(SConnection* conn);\n    virtual ~TightEncoder();\n\n    bool isSupported() override;\n\n    void setCompressLevel(int level) override;\n\n    void writeRect(const PixelBuffer* pb,\n                   const Palette& palette) override;\n    void writeSolidRect(int width, int height, const PixelFormat& pf,\n                        const uint8_t* colour) override;\n\n  protected:\n    void writeMonoRect(const PixelBuffer* pb, const Palette& palette);\n    void writeIndexedRect(const PixelBuffer* pb, const Palette& palette);\n    void writeFullColourRect(const PixelBuffer* pb);\n\n    void writePixels(const uint8_t* buffer, const PixelFormat& pf,\n                     unsigned int count, rdr::OutStream* os);\n\n    void writeCompact(rdr::OutStream* os, uint32_t value);\n\n    rdr::OutStream* getZlibOutStream(int streamId, int level, size_t length);\n    void flushZlibOutStream(rdr::OutStream* os);\n\n  protected:\n    // Templated, optimised methods\n    template<class T>\n    void writeMonoRect(int width, int height,\n                       const T* buffer, int stride,\n                       const PixelFormat& pf, const Palette& palette);\n    template<class T>\n    void writeIndexedRect(int width, int height,\n                          const T* buffer, int stride,\n                          const PixelFormat& pf, const Palette& palette);\n\n    rdr::ZlibOutStream zlibStreams[4];\n    rdr::MemOutStream memStream;\n\n    int idxZlibLevel, monoZlibLevel, rawZlibLevel;\n  };\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/TightJPEGEncoder.cxx",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rdr/OutStream.h>\n#include <rfb/encodings.h>\n#include <rfb/SConnection.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/TightJPEGEncoder.h>\n#include <rfb/TightConstants.h>\n\nusing namespace rfb;\n\nTightJPEGEncoder::TightJPEGEncoder(SConnection* conn_) :\n  Encoder(conn_, encodingTight,\n          (EncoderFlags)(EncoderUseNativePF | EncoderLossy), -1, 9)\n{\n}\n\nTightJPEGEncoder::~TightJPEGEncoder()\n{\n}\n\nbool TightJPEGEncoder::isSupported()\n{\n  if (!conn->client.supportsEncoding(encodingTight))\n    return false;\n\n  // JPEG doesn't really care about the pixel format, but the\n  // specification requires it to be at least 16bpp\n  if (conn->client.pf().bpp < 16)\n    return false;\n\n  // Any one of these indicates support for JPEG\n  if (conn->client.qualityLevel != -1)\n    return true;\n  if (conn->client.fineQualityLevel != -1)\n    return true;\n  if (conn->client.subsampling != -1)\n    return true;\n\n  // Tight support, but not JPEG\n  return false;\n}\n\nvoid TightJPEGEncoder::setQualityLevel(int level)\n{\n  jc.setQualityLevel(level);\n}\n\nvoid TightJPEGEncoder::setFineQualityLevel(int quality, int subsampling)\n{\n  jc.setFineQualityLevel(quality, subsampling);\n}\n\nint TightJPEGEncoder::getQualityLevel()\n{\n  return jc.getQualityLevel();\n}\n\nvoid TightJPEGEncoder::writeRect(const PixelBuffer* pb,\n                                 const Palette& /*palette*/)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  rdr::OutStream* os;\n\n  buffer = pb->getBuffer(pb->getRect(), &stride);\n\n  jc.clear();\n  jc.compress(buffer, stride, pb->getRect(), pb->getPF());\n\n  os = conn->getOutStream();\n\n  os->writeU8(tightJpeg << 4);\n\n  writeCompact(jc.length(), os);\n  os->writeBytes(jc.data(), jc.length());\n}\n\nvoid TightJPEGEncoder::writeSolidRect(int width, int height,\n                                      const PixelFormat& pf,\n                                      const uint8_t* colour)\n{\n  // FIXME: Add a shortcut in the JPEG compressor to handle this case\n  //        without having to use the default fallback which is very slow.\n  Encoder::writeSolidRect(width, height, pf, colour);\n}\n\nvoid TightJPEGEncoder::writeCompact(uint32_t value, rdr::OutStream* os)\n{\n  // Copied from TightEncoder as it's overkill to inherit just for this\n  uint8_t b;\n\n  b = value & 0x7F;\n  if (value <= 0x7F) {\n    os->writeU8(b);\n  } else {\n    os->writeU8(b | 0x80);\n    b = value >> 7 & 0x7F;\n    if (value <= 0x3FFF) {\n      os->writeU8(b);\n    } else {\n      os->writeU8(b | 0x80);\n      os->writeU8(value >> 14 & 0xFF);\n    }\n  }\n}\n"
  },
  {
    "path": "common/rfb/TightJPEGEncoder.h",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander\n * Copyright 2014 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_TIGHTJPEGENCODER_H__\n#define __RFB_TIGHTJPEGENCODER_H__\n\n#include <rfb/Encoder.h>\n#include <rfb/JpegCompressor.h>\n\nnamespace rfb {\n\n  class TightJPEGEncoder : public Encoder {\n  public:\n    TightJPEGEncoder(SConnection* conn);\n    virtual ~TightJPEGEncoder();\n\n    bool isSupported() override;\n\n    void setQualityLevel(int level) override;\n    void setFineQualityLevel(int quality, int subsampling) override;\n\n    int getQualityLevel() override;\n\n    void writeRect(const PixelBuffer* pb,\n                   const Palette& palette) override;\n    void writeSolidRect(int width, int height, const PixelFormat& pf,\n                        const uint8_t* colour) override;\n\n  protected:\n    void writeCompact(uint32_t value, rdr::OutStream* os);\n\n  protected:\n    JpegCompressor jc;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/UnixPasswordValidator.cxx",
    "content": "/* \n * Copyright (C) 2006 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <string.h>\n#include <security/pam_appl.h>\n\n#include <core/Configuration.h>\n#include <core/LogWriter.h>\n\n#include <rfb/UnixPasswordValidator.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"UnixPasswordValidator\");\n\nstatic core::StringParameter pamService\n  (\"PAMService\", \"Service name for PAM password validation\", \"vnc\");\ncore::AliasParameter pam_service(\"pam_service\", \"Alias for PAMService\",\n                                 &pamService);\n\nstd::string UnixPasswordValidator::displayName;\n\ntypedef struct\n{\n  const char *username;\n  const char *password;\n  std::string &msg;\n} AuthData;\n\n#if defined(__sun)\nstatic int pam_callback(int count, struct pam_message **in,\n                        struct pam_response **out, void *ptr)\n#else\nstatic int pam_callback(int count, const struct pam_message **in,\n                        struct pam_response **out, void *ptr)\n#endif\n{\n  int i;\n  AuthData *auth = (AuthData *) ptr;\n  struct pam_response *resp =\n    (struct pam_response *) malloc (sizeof (struct pam_response) * count);\n\n  if (!resp && count)\n    return PAM_CONV_ERR;\n\n  for (i = 0; i < count; i++) {\n    resp[i].resp_retcode = PAM_SUCCESS;\n    switch (in[i]->msg_style) {\n    case PAM_TEXT_INFO:\n      auth->msg = in[i]->msg;\n      resp[i].resp = nullptr;\n      break;\n    case PAM_ERROR_MSG:\n      auth->msg = in[i]->msg;\n      resp[i].resp = nullptr;\n      break;\n    case PAM_PROMPT_ECHO_ON:\t/* Send Username */\n      resp[i].resp = strdup(auth->username);\n      break;\n    case PAM_PROMPT_ECHO_OFF:\t/* Send Password */\n      resp[i].resp = strdup(auth->password);\n      break;\n    default:\n      free(resp);\n      return PAM_CONV_ERR;\n    }\n  }\n\n  *out = resp;\n  return PAM_SUCCESS;\n}\n\nbool UnixPasswordValidator::validateInternal(SConnection * /* sc */,\n\t\t\t\t\t     const char *username,\n\t\t\t\t\t     const char *password,\n\t\t\t\t\t     std::string &msg)\n{\n  int ret;\n  AuthData auth = { username, password, msg };\n  struct pam_conv conv = {\n    pam_callback,\n    &auth\n  };\n  pam_handle_t *pamh = nullptr;\n  ret = pam_start(pamService, username, &conv, &pamh);\n  if (ret != PAM_SUCCESS) {\n    /* Can't call pam_strerror() here because the content of pamh undefined */\n    vlog.error(\"pam_start(%s) failed: %d\", (const char *) pamService, ret);\n    return false;\n  }\n#ifdef PAM_XDISPLAY\n  /* displayName set set for X but not Wayland sessions */\n  if (displayName.length() > 0) {\n    /* Pass the display name to PAM modules but PAM_XDISPLAY may not be\n    * recognized by modules built with old versions of PAM */\n    ret = pam_set_item(pamh, PAM_XDISPLAY, displayName.c_str());\n    if (ret != PAM_SUCCESS && ret != PAM_BAD_ITEM) {\n      vlog.error(\"pam_set_item(PAM_XDISPLAY) failed: %d (%s)\", ret, pam_strerror(pamh, ret));\n      goto error;\n    }\n  }\n#endif\n  ret = pam_authenticate(pamh, 0);\n  if (ret != PAM_SUCCESS) {\n    vlog.error(\"pam_authenticate() failed: %d (%s)\", ret, pam_strerror(pamh, ret));\n    goto error;\n  }\n  ret = pam_acct_mgmt(pamh, 0);\n  if (ret != PAM_SUCCESS) {\n    vlog.error(\"pam_acct_mgmt() failed: %d (%s)\", ret, pam_strerror(pamh, ret));\n    goto error;\n  }\n  return true;\nerror:\n  pam_end(pamh, ret);\n  return false;\n}\n"
  },
  {
    "path": "common/rfb/UnixPasswordValidator.h",
    "content": "/* \n * Copyright (C) 2006 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __PASSWORD_VALIDATOR_H__\n#define __PASSWORD_VALIDATOR_H__\n\n#include <rfb/SSecurityPlain.h>\n\nnamespace rfb\n{\n  class UnixPasswordValidator: public PasswordValidator {\n  public:\n    static void setDisplayName(const std::string& display) {\n      displayName = display;\n    }\n\n  protected:\n    bool validateInternal(SConnection *sc,\n                          const char *username,\n                          const char *password,\n                          std::string &msg) override;\n\n  private:\n    static std::string displayName;\n  };\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/UpdateTracker.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- rfbUpdateTracker.cpp\n//\n// Tracks updated regions and a region-copy event, too\n//\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <rfb/UpdateTracker.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"UpdateTracker\");\n\n\n// -=- ClippingUpdateTracker\n\nvoid ClippingUpdateTracker::add_changed(const core::Region& region)\n{\n  ut->add_changed(region.intersect(clipRect));\n}\n\nvoid ClippingUpdateTracker::add_copied(const core::Region& dest,\n                                       const core::Point& delta)\n{\n  // Clip the destination to the display area\n  core::Region clipdest = dest.intersect(clipRect);\n  if (clipdest.is_empty())  return;\n\n  // Clip the source to the screen\n  core::Region tmp = clipdest;\n  tmp.translate(delta.negate());\n  tmp.assign_intersect(clipRect);\n  if (!tmp.is_empty()) {\n    // Translate the source back to a destination region\n    tmp.translate(delta);\n\n    // Pass the copy region to the child tracker\n    ut->add_copied(tmp, delta);\n  }\n\n  // And add any bits that we had to remove to the changed region\n  tmp = clipdest.subtract(tmp);\n  if (!tmp.is_empty())\n    ut->add_changed(tmp);\n}\n\n// SimpleUpdateTracker\n\nSimpleUpdateTracker::SimpleUpdateTracker() {\n}\n\nSimpleUpdateTracker::~SimpleUpdateTracker() {\n}\n\nvoid SimpleUpdateTracker::add_changed(const core::Region& region)\n{\n  changed.assign_union(region);\n}\n\nvoid SimpleUpdateTracker::add_copied(const core::Region& dest,\n                                     const core::Point& delta)\n{\n  // Is there anything to do?\n  if (dest.is_empty()) return;\n\n  // Calculate whether any of this copy can be treated as a continuation\n  // of an earlier one\n  core::Region src = dest;\n  src.translate(delta.negate());\n  core::Region overlap = src.intersect(copied);\n\n  if (overlap.is_empty()) {\n    // There is no overlap\n\n    core::Rect newbr = dest.get_bounding_rect();\n    core::Rect oldbr = copied.get_bounding_rect();\n    if (oldbr.area() > newbr.area()) {\n      // Old copyrect is (probably) bigger - use it\n      changed.assign_union(dest);\n    } else {\n      // New copyrect is probably bigger\n      // Use the new one\n      // But be careful not to copy stuff that still needs\n      // to be updated.\n      core::Region invalid_src = src.intersect(changed);\n      invalid_src.translate(delta);\n      changed.assign_union(invalid_src);\n      changed.assign_union(copied);\n      copied = dest;\n      copy_delta = delta;\n    }\n    return;\n  }\n\n  core::Region invalid_src = overlap.intersect(changed);\n  invalid_src.translate(delta);\n  changed.assign_union(invalid_src);\n  \n  overlap.translate(delta);\n\n  core::Region nonoverlapped_copied = dest.union_(copied).subtract(overlap);\n  changed.assign_union(nonoverlapped_copied);\n\n  copied = overlap;\n  copy_delta = copy_delta.translate(delta);\n\n  return;\n}\n\nvoid SimpleUpdateTracker::subtract(const core::Region& region)\n{\n  copied.assign_subtract(region);\n  changed.assign_subtract(region);\n}\n\nvoid SimpleUpdateTracker::getUpdateInfo(UpdateInfo* info,\n                                        const core::Region& clip)\n{\n  copied.assign_subtract(changed);\n  info->changed = changed.intersect(clip);\n  info->copied = copied.intersect(clip);\n  info->copy_delta = copy_delta;\n}\n\nvoid SimpleUpdateTracker::copyTo(UpdateTracker* to) const {\n  if (!copied.is_empty())\n    to->add_copied(copied, copy_delta);\n  if (!changed.is_empty())\n    to->add_changed(changed);\n}\n"
  },
  {
    "path": "common/rfb/UpdateTracker.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_UPDATETRACKER_INCLUDED__\n#define __RFB_UPDATETRACKER_INCLUDED__\n\n#include <core/Rect.h>\n#include <core/Region.h>\n\nnamespace rfb {\n\n  class UpdateInfo {\n  public:\n    core::Region changed;\n    core::Region copied;\n    core::Point copy_delta;\n    bool is_empty() const {\n      return copied.is_empty() && changed.is_empty();\n    }\n    // NOTE: We do not ever use UpdateInfo::numRects(), because Tight encoding\n    //       complicates computing the number of rectangles.\n    /*\n    int numRects() const {\n      return copied.numRects() + changed.numRects();\n    }\n    */\n  };\n\n  class UpdateTracker {\n  public:\n    UpdateTracker() {};\n    virtual ~UpdateTracker() {};\n\n    virtual void add_changed(const core::Region& region) = 0;\n    virtual void add_copied(const core::Region& dest,\n                            const core::Point& delta) = 0;\n  };\n\n  class ClippingUpdateTracker : public UpdateTracker {\n  public:\n    ClippingUpdateTracker() : ut(nullptr) {}\n    ClippingUpdateTracker(UpdateTracker* ut_, const core::Rect& r={}) : ut(ut_), clipRect(r) {}\n    \n    void setUpdateTracker(UpdateTracker* ut_) {ut = ut_;}\n    void setClipRect(const core::Rect& cr) {clipRect = cr;}\n\n    void add_changed(const core::Region& region) override;\n    void add_copied(const core::Region& dest,\n                    const core::Point& delta) override;\n  protected:\n    UpdateTracker* ut;\n    core::Rect clipRect;\n  };\n\n  class SimpleUpdateTracker : public UpdateTracker {\n  public:\n    SimpleUpdateTracker();\n    virtual ~SimpleUpdateTracker();\n\n    void add_changed(const core::Region& region) override;\n    void add_copied(const core::Region& dest,\n                    const core::Point& delta) override;\n    virtual void subtract(const core::Region& region);\n\n    // Fill the supplied UpdateInfo structure with update information\n    // FIXME: Provide getUpdateInfo() with no clipping, for better efficiency.\n    virtual void getUpdateInfo(UpdateInfo* info,\n                               const core::Region& cliprgn);\n\n    // Copy the contained updates to another tracker\n    virtual void copyTo(UpdateTracker* to) const;\n\n    // Move the entire update region by an offset\n    void translate(const core::Point& p) {changed.translate(p); copied.translate(p);}\n\n    virtual bool is_empty() const {return changed.is_empty() && copied.is_empty();}\n\n    virtual void clear() {changed.clear(); copied.clear();};\n  protected:\n    core::Region changed;\n    core::Region copied;\n    core::Point copy_delta;\n  };\n\n}\n\n#endif // __RFB_UPDATETRACKER_INCLUDED__\n"
  },
  {
    "path": "common/rfb/VNCSConnectionST.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * Copyright 2018 Peter Astrand for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n#include <core/time.h>\n\n#include <rdr/FdInStream.h>\n#include <rdr/FdOutStream.h>\n\n#include <network/TcpSocket.h>\n\n#include <rfb/ComparingUpdateTracker.h>\n#include <rfb/Encoder.h>\n#include <rfb/Exception.h>\n#include <rfb/KeyRemapper.h>\n#include <rfb/KeysymStr.h>\n#include <rfb/Security.h>\n#include <rfb/ServerCore.h>\n#include <rfb/SMsgWriter.h>\n#include <rfb/VNCServerST.h>\n#include <rfb/VNCSConnectionST.h>\n#include <rfb/encodings.h>\n#include <rfb/screenTypes.h>\n#include <rfb/fenceTypes.h>\n#include <rfb/ledStates.h>\n#define XK_LATIN1\n#define XK_MISCELLANY\n#define XK_XKB_KEYS\n#include <rfb/keysymdef.h>\n\nusing namespace rfb;\n\n// Number of seconds allowed for authentication\nstatic const unsigned LOGIN_GRACE_TIME = 120;\n// Number of seconds allowed to flush a closing socket\nstatic const unsigned CLOSE_GRACE_TIME = 5;\n\nstatic core::LogWriter vlog(\"VNCSConnST\");\n\nstatic Cursor emptyCursor(0, 0, {0, 0}, nullptr);\n\nVNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,\n                                   bool reverse, AccessRights ar)\n  : SConnection(ar),\n    sock(s), socketTimer(this), reverseConnection(reverse),\n    inProcessMessages(false),\n    pendingSyncFence(false), syncFence(false), fenceFlags(0),\n    fenceDataLen(0), fenceData(nullptr), congestionTimer(this),\n    losslessTimer(this), server(server_),\n    updateRenderedCursor(false), removeRenderedCursor(false),\n    continuousUpdates(false), encodeManager(this), idleTimer(this),\n    pointerEventTime(0), clientHasCursor(false)\n{\n  socketTimer.start(core::secsToMillis(LOGIN_GRACE_TIME));\n\n  setStreams(&sock->inStream(), &sock->outStream());\n  peerEndpoint = sock->getPeerEndpoint();\n}\n\n\nVNCSConnectionST::~VNCSConnectionST()\n{\n  // If we reach here then VNCServerST is deleting us!\n  if (!closeReason.empty())\n    vlog.info(\"Closing %s: %s\", peerEndpoint.c_str(),\n              closeReason.c_str());\n\n  // Release any keys the client still had pressed\n  while (!pressedKeys.empty()) {\n    uint32_t keysym, keycode;\n\n    keysym = pressedKeys.begin()->second;\n    keycode = pressedKeys.begin()->first;\n    pressedKeys.erase(pressedKeys.begin());\n\n    vlog.debug(\"Releasing key 0x%04x / XK_%s (0x%04x) on client disconnect\",\n               keycode, KeySymName(keysym), keysym);\n    server->keyEvent(keysym, keycode, false);\n  }\n\n  delete [] fenceData;\n}\n\n\n// SConnection methods\n\nbool VNCSConnectionST::accessCheck(AccessRights ar) const\n{\n  // Reverse connections are user initiated, so they are implicitly\n  // allowed to bypass the query\n  if (reverseConnection)\n    ar &= ~AccessNoQuery;\n\n  return SConnection::accessCheck(ar);\n}\n\nvoid VNCSConnectionST::close(const char* reason)\n{\n  SConnection::close(reason);\n\n  // Log the reason for the close\n  if (closeReason.empty())\n    closeReason = reason;\n  else\n    vlog.debug(\"Second close: %s (%s)\", peerEndpoint.c_str(), reason);\n\n  // Just shutdown the socket and mark our state as closing.  Eventually the\n  // calling code will call VNCServerST's removeSocket() method causing us to\n  // be deleted.\n  sock->shutdownWrite();\n  socketTimer.start(core::secsToMillis(CLOSE_GRACE_TIME));\n}\n\n\n// Methods called from VNCServerST\n\nbool VNCSConnectionST::init()\n{\n  try {\n    initialiseProtocol();\n  } catch (std::exception& e) {\n    close(e.what());\n    return false;\n  }\n  return true;\n}\n\n\nvoid VNCSConnectionST::processSocketReadEvent()\n{\n  // Are we flushing remaining incoming data?\n  if (state() == RFBSTATE_CLOSING) {\n    assert(getSock()->isShutdownWrite());\n\n    // Shouldn't really get called if we've already finished reading,\n    // but let's be lenient\n    if (getSock()->isShutdownRead())\n      return;\n\n    // Do a graceful close by waiting for the peer to close their end\n    while (true) {\n      try {\n        getInStream()->skip(getInStream()->avail());\n        if (!getInStream()->hasData(1))\n          break;\n      } catch (std::exception&) {\n        // Handle both graceful close and resets\n        getSock()->shutdownRead();\n        break;\n      }\n    }\n\n    return;\n  }\n\n  try {\n    inProcessMessages = true;\n\n    // Get the underlying transport to build large packets if we send\n    // multiple small responses.\n    getOutStream()->cork(true);\n\n    while (true) {\n      if (pendingSyncFence)\n        syncFence = true;\n\n      if (!processMsg())\n        break;\n\n      if (syncFence) {\n        writer()->writeFence(fenceFlags, fenceDataLen, fenceData);\n        syncFence = false;\n        pendingSyncFence = false;\n      }\n    }\n\n    // Flush out everything in case we go idle after this.\n    getOutStream()->cork(false);\n\n    inProcessMessages = false;\n\n    // If there were anything requiring an update, try to send it here.\n    // We wait until now with this to aggregate responses and to give \n    // higher priority to user actions such as keyboard and pointer events.\n    writeFramebufferUpdate();\n  } catch (rdr::end_of_stream&) {\n    close(\"Clean disconnection\");\n  } catch (std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::processSocketWriteEvent()\n{\n  if (state() == RFBSTATE_CLOSING) return;\n  try {\n    sock->outStream().flush();\n    // Flushing the socket might release an update that was previously\n    // delayed because of congestion.\n    if (!sock->outStream().hasBufferedData())\n      writeFramebufferUpdate();\n  } catch (std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::pixelBufferChange()\n{\n  try {\n    if (state() != RFBSTATE_NORMAL)\n      return;\n    if (client.width() && client.height() &&\n        (server->getPixelBuffer()->width() != client.width() ||\n         server->getPixelBuffer()->height() != client.height()))\n    {\n      // We need to clip the next update to the new size, but also add any\n      // extra bits if it's bigger.  If we wanted to do this exactly, something\n      // like the code below would do it, but at the moment we just update the\n      // entire new size.  However, we do need to clip the damagedCursorRegion\n      // because that might be added to updates in writeFramebufferUpdate().\n\n      //updates.intersect(server->pb->getRect());\n      //\n      //if (server->pb->width() > client.width())\n      //  updates.add_changed({client.width(), 0, server->pb->width(),\n      //                       server->pb->height()});\n      //if (server->pb->height() > client.height())\n      //  updates.add_changed({0, client.height(), client.width(),\n      //                       server->pb->height()});\n\n      damagedCursorRegion.assign_intersect(server->getPixelBuffer()->getRect());\n\n      client.setDimensions(server->getPixelBuffer()->width(),\n                           server->getPixelBuffer()->height(),\n                           server->getScreenLayout());\n      if (state() == RFBSTATE_NORMAL) {\n        if (!client.supportsDesktopSize()) {\n          close(\"Client does not support desktop resize\");\n          return;\n        }\n        writer()->writeDesktopSize(reasonServer);\n      }\n\n      // Drop any lossy tracking that is now outside the framebuffer\n      encodeManager.pruneLosslessRefresh(server->getPixelBuffer()->getRect());\n    }\n    // Just update the whole screen at the moment because we're too lazy to\n    // work out what's actually changed.\n    updates.clear();\n    updates.add_changed(server->getPixelBuffer()->getRect());\n    writeFramebufferUpdate();\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::writeFramebufferUpdateOrClose()\n{\n  try {\n    writeFramebufferUpdate();\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::screenLayoutChangeOrClose(uint16_t reason)\n{\n  try {\n    screenLayoutChange(reason);\n    writeFramebufferUpdate();\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::bellOrClose()\n{\n  try {\n    if (state() == RFBSTATE_NORMAL) writer()->writeBell();\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::setDesktopNameOrClose(const char *name)\n{\n  try {\n    setDesktopName(name);\n    writeFramebufferUpdate();\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::setCursorOrClose()\n{\n  try {\n    setCursor();\n    writeFramebufferUpdate();\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::setLEDStateOrClose(unsigned int state)\n{\n  try {\n    setLEDState(state);\n    writeFramebufferUpdate();\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::requestClipboardOrClose()\n{\n  try {\n    if (state() != RFBSTATE_NORMAL) return;\n    requestClipboard();\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::announceClipboardOrClose(bool available)\n{\n  try {\n    if (state() != RFBSTATE_NORMAL) return;\n    announceClipboard(available);\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::sendClipboardDataOrClose(const char* data)\n{\n  try {\n    if (state() != RFBSTATE_NORMAL) return;\n    sendClipboardData(data);\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nvoid VNCSConnectionST::desktopReadyOrClose()\n{\n  try {\n    if (state() != RFBSTATE_CLIENT_READY) return;\n    desktopReady();\n  } catch(std::exception& e) {\n    close(e.what());\n  }\n}\n\nbool VNCSConnectionST::getComparerState()\n{\n  // We interpret a low compression level as an indication that the client\n  // wants to prioritise CPU usage over bandwidth, and hence disable the\n  // comparing update tracker.\n  return (client.compressLevel == -1) || (client.compressLevel > 1);\n}\n\n\n// renderedCursorChange() is called whenever the server-side rendered cursor\n// changes shape or position.  It ensures that the next update will clean up\n// the old rendered cursor and if necessary draw the new rendered cursor.\n\nvoid VNCSConnectionST::renderedCursorChange()\n{\n  if (state() != RFBSTATE_NORMAL) return;\n  // Are we switching between client-side and server-side cursor?\n  if (clientHasCursor == needRenderedCursor())\n    setCursorOrClose();\n  bool hasRenderedCursor = !damagedCursorRegion.is_empty();\n  if (hasRenderedCursor)\n    removeRenderedCursor = true;\n  if (needRenderedCursor()) {\n    updateRenderedCursor = true;\n    writeFramebufferUpdateOrClose();\n  }\n}\n\n// cursorPositionChange() is called whenever the cursor has changed position by\n// the server.  If the client supports being informed about these changes then\n// it will arrange for the new cursor position to be sent to the client.\n\nvoid VNCSConnectionST::cursorPositionChange()\n{\n  setCursorPos();\n}\n\n// needRenderedCursor() returns true if this client needs the server-side\n// rendered cursor.  This may be because it does not support local cursor or\n// because the current cursor position has not been set by this client.\n// Unfortunately we can't know for sure when the current cursor position has\n// been set by this client.  We guess that this is the case when the current\n// cursor position is the same as the last pointer event from this client, or\n// if it is a very short time since this client's last pointer event (up to a\n// second).  [ Ideally we should do finer-grained timing here and make the time\n// configurable, but I don't think it's that important. ]\n\nbool VNCSConnectionST::needRenderedCursor()\n{\n  if (state() != RFBSTATE_NORMAL)\n    return false;\n\n  if (!client.supportsLocalCursor())\n    return true;\n  if ((server->getCursorPos() != pointerEventPos) &&\n      (time(nullptr) - pointerEventTime) > 0)\n    return true;\n\n  return false;\n}\n\nvoid VNCSConnectionST::desktopReady()\n{\n  if (state() != RFBSTATE_CLIENT_READY)\n    return;\n\n  // - Set the connection parameters appropriately\n  client.setDimensions(server->getPixelBuffer()->width(),\n                       server->getPixelBuffer()->height(),\n                       server->getScreenLayout());\n  client.setName(server->getName());\n  client.setLEDState(server->getLEDState());\n  \n  // - Set the default pixel format\n  client.setPF(server->getPixelBuffer()->getPF());\n  char buffer[256];\n  client.pf().print(buffer, 256);\n  vlog.info(\"Server default pixel format %s\", buffer);\n\n  // - Mark the entire display as \"dirty\"\n  updates.add_changed(server->getPixelBuffer()->getRect());\n\n  SConnection::desktopReady();\n}\n\n\nvoid VNCSConnectionST::approveConnectionOrClose(bool accept,\n                                                const char* reason)\n{\n  try {\n    approveConnection(accept, reason);\n  } catch (std::exception& e) {\n    close(e.what());\n  }\n}\n\n\n\n// -=- Callbacks from SConnection\n\nvoid VNCSConnectionST::authSuccess()\n{\n  socketTimer.stop();\n\n  if (rfb::Server::idleTimeout)\n    idleTimer.start(core::secsToMillis(rfb::Server::idleTimeout));\n}\n\nvoid VNCSConnectionST::queryConnection(const char* userName)\n{\n  server->queryConnection(this, userName);\n}\n\nvoid VNCSConnectionST::clientReady(bool shared)\n{\n  if (rfb::Server::idleTimeout)\n    idleTimer.start(core::secsToMillis(rfb::Server::idleTimeout));\n\n  if (rfb::Server::alwaysShared || reverseConnection) shared = true;\n  if (!accessCheck(AccessNonShared)) shared = true;\n  if (rfb::Server::neverShared) shared = false;\n  server->clientReady(this, shared);\n\n  if (server->isDesktopReady())\n    desktopReady();\n}\n\nvoid VNCSConnectionST::setPixelFormat(const PixelFormat& pf)\n{\n  SConnection::setPixelFormat(pf);\n  char buffer[256];\n  pf.print(buffer, 256);\n  vlog.info(\"Client pixel format %s\", buffer);\n  setCursor();\n  encodeManager.forceRefresh(server->getPixelBuffer()->getRect());\n}\n\nvoid VNCSConnectionST::pointerEvent(const core::Point& pos,\n                                    uint16_t buttonMask)\n{\n  if (rfb::Server::idleTimeout)\n    idleTimer.start(core::secsToMillis(rfb::Server::idleTimeout));\n  pointerEventTime = time(nullptr);\n  if (!accessCheck(AccessPtrEvents)) return;\n  pointerEventPos = pos;\n  server->pointerEvent(this, pointerEventPos, buttonMask);\n}\n\n\nclass VNCSConnectionSTShiftPresser {\npublic:\n  VNCSConnectionSTShiftPresser(VNCServerST* server_)\n    : server(server_), pressed(false) {}\n  ~VNCSConnectionSTShiftPresser() {\n    if (pressed) {\n      vlog.debug(\"Releasing fake Shift_L\");\n      server->keyEvent(XK_Shift_L, 0x2a, false);\n    }\n  }\n  void press() {\n    vlog.debug(\"Pressing fake Shift_L\");\n    server->keyEvent(XK_Shift_L, 0x2a, true);\n    pressed = true;\n  }\n  VNCServerST* server;\n  bool pressed;\n};\n\n// keyEvent() - record in the pressedKeys which keys were pressed.  Allow\n// multiple down events (for autorepeat), but only allow a single up event.\nvoid VNCSConnectionST::keyEvent(uint32_t keysym, uint32_t keycode, bool down) {\n  uint32_t lookup;\n\n  if (rfb::Server::idleTimeout)\n    idleTimer.start(core::secsToMillis(rfb::Server::idleTimeout));\n  if (!accessCheck(AccessKeyEvents)) return;\n  // FIXME: This check isn't strictly needed, but we get a lot of\n  //        confusing debug logging without it\n  if (!rfb::Server::acceptKeyEvents) return;\n\n  if (down)\n    vlog.debug(\"Key pressed: 0x%04x / XK_%s (0x%04x)\",\n               keycode, KeySymName(keysym), keysym);\n  else\n    vlog.debug(\"Key released: 0x%04x / XK_%s (0x%04x)\",\n               keycode, KeySymName(keysym), keysym);\n\n  // Avoid lock keys if we don't know the server state\n  if ((server->getLEDState() == ledUnknown) &&\n      ((keysym == XK_Caps_Lock) ||\n       (keysym == XK_Num_Lock))) {\n    vlog.debug(\"Ignoring lock key (e.g. caps lock)\");\n    return;\n  }\n\n  // Lock key heuristics\n  // (only for clients that do not support the LED state extension)\n  if (!client.supportsLEDState()) {\n    if (down && (server->getLEDState() != ledUnknown)) {\n      // CapsLock synchronisation heuristic\n      // (this assumes standard interaction between CapsLock the Shift\n      // keys and normal characters)\n      if (((keysym >= XK_A) && (keysym <= XK_Z)) ||\n          ((keysym >= XK_a) && (keysym <= XK_z))) {\n        bool uppercase, shift, lock;\n\n        uppercase = (keysym >= XK_A) && (keysym <= XK_Z);\n        shift = isShiftPressed();\n        lock = server->getLEDState() & ledCapsLock;\n\n        if (lock == (uppercase == shift)) {\n          vlog.debug(\"Inserting fake CapsLock to get in sync with client\");\n          server->keyEvent(XK_Caps_Lock, 0x3a, true);\n          server->keyEvent(XK_Caps_Lock, 0x3a, false);\n        }\n      }\n\n      // NumLock synchronisation heuristic\n      // (this is more cautious because of the differences between Unix,\n      // Windows and macOS)\n      if (((keysym >= XK_KP_Home) && (keysym <= XK_KP_Delete)) ||\n          ((keysym >= XK_KP_0) && (keysym <= XK_KP_9)) ||\n          (keysym == XK_KP_Separator) || (keysym == XK_KP_Decimal)) {\n        bool number, shift, lock;\n\n        number = ((keysym >= XK_KP_0) && (keysym <= XK_KP_9)) ||\n                  (keysym == XK_KP_Separator) || (keysym == XK_KP_Decimal);\n        shift = isShiftPressed();\n        lock = server->getLEDState() & ledNumLock;\n\n        if (shift) {\n          // We don't know the appropriate NumLock state for when Shift\n          // is pressed as it could be one of:\n          //\n          // a) A Unix client where Shift negates NumLock\n          //\n          // b) A Windows client where Shift only cancels NumLock\n          //\n          // c) A macOS client where Shift doesn't have any effect\n          //\n        } else if (lock == (number == shift)) {\n          vlog.debug(\"Inserting fake NumLock to get in sync with client\");\n          server->keyEvent(XK_Num_Lock, 0x45, true);\n          server->keyEvent(XK_Num_Lock, 0x45, false);\n        }\n      }\n    }\n  }\n\n  // Turn ISO_Left_Tab into shifted Tab.\n  VNCSConnectionSTShiftPresser shiftPresser(server);\n  if (keysym == XK_ISO_Left_Tab) {\n    if (!isShiftPressed())\n      shiftPresser.press();\n    keysym = XK_Tab;\n  }\n\n  // We need to be able to track keys, so generate a fake index when we\n  // aren't given a keycode\n  if (keycode == 0)\n    lookup = 0x80000000 | keysym;\n  else\n    lookup = keycode;\n\n  // We force the same keysym for an already down key for the\n  // sake of sanity\n  if (pressedKeys.find(lookup) != pressedKeys.end())\n    keysym = pressedKeys[lookup];\n\n  if (down) {\n    pressedKeys[lookup] = keysym;\n  } else {\n    if (!pressedKeys.erase(lookup))\n      return;\n  }\n\n  server->keyEvent(keysym, keycode, down);\n}\n\nvoid VNCSConnectionST::framebufferUpdateRequest(const core::Rect& r,\n                                                bool incremental)\n{\n  core::Rect safeRect;\n\n  if (!accessCheck(AccessView)) return;\n\n  SConnection::framebufferUpdateRequest(r, incremental);\n\n  // Check that the client isn't sending crappy requests\n  if (!r.enclosed_by({0, 0, client.width(), client.height()})) {\n    vlog.error(\"FramebufferUpdateRequest %dx%d at %d,%d exceeds framebuffer %dx%d\",\n               r.width(), r.height(), r.tl.x, r.tl.y,\n               client.width(), client.height());\n    safeRect = r.intersect({0, 0, client.width(), client.height()});\n  } else {\n    safeRect = r;\n  }\n\n  // Just update the requested region.\n  // Framebuffer update will be sent a bit later, see processMessages().\n  core::Region reqRgn(safeRect);\n  if (!incremental || !continuousUpdates)\n    requested.assign_union(reqRgn);\n\n  if (!incremental) {\n    // Non-incremental update - treat as if area requested has changed\n    updates.add_changed(reqRgn);\n\n    // And send the screen layout to the client (which, unlike the\n    // framebuffer dimensions, the client doesn't get during init)\n    if (client.supportsEncoding(pseudoEncodingExtendedDesktopSize))\n      writer()->writeDesktopSize(reasonServer);\n\n    // We do not send a DesktopSize since it only contains the\n    // framebuffer size (which the client already should know) and\n    // because some clients don't handle extra DesktopSize events\n    // very well.\n  }\n}\n\nvoid VNCSConnectionST::setDesktopSize(int fb_width, int fb_height,\n                                      const ScreenSet& layout)\n{\n  unsigned int result;\n  char buffer[2048];\n\n  vlog.debug(\"Got request for framebuffer resize to %dx%d\",\n             fb_width, fb_height);\n  layout.print(buffer, sizeof(buffer));\n  vlog.debug(\"%s\", buffer);\n\n  if (!accessCheck(AccessSetDesktopSize)) {\n    vlog.debug(\"Rejecting unauthorized framebuffer resize request\");\n    result = resultProhibited;\n  } else {\n    result = server->setDesktopSize(this, fb_width, fb_height, layout);\n  }\n\n  writer()->writeDesktopSize(reasonClient, result);\n}\n\nvoid VNCSConnectionST::fence(uint32_t flags, unsigned len, const uint8_t data[])\n{\n  uint8_t type;\n\n  if (flags & fenceFlagRequest) {\n    if (flags & fenceFlagSyncNext) {\n      pendingSyncFence = true;\n\n      fenceFlags = flags & (fenceFlagBlockBefore | fenceFlagBlockAfter | fenceFlagSyncNext);\n      fenceDataLen = len;\n      delete [] fenceData;\n      fenceData = nullptr;\n      if (len > 0) {\n        fenceData = new uint8_t[len];\n        memcpy(fenceData, data, len);\n      }\n\n      return;\n    }\n\n    // We handle everything synchronously so we trivially honor these modes\n    flags = flags & (fenceFlagBlockBefore | fenceFlagBlockAfter);\n\n    writer()->writeFence(flags, len, data);\n    return;\n  }\n\n  if (len < 1) {\n    vlog.error(\"Fence response of unexpected size received\");\n    return;\n  }\n\n  type = data[0];\n\n  switch (type) {\n  case 0:\n    // Initial dummy fence;\n    break;\n  case 1:\n    congestion.gotPong();\n    break;\n  default:\n    vlog.error(\"Fence response of unexpected type received\");\n  }\n}\n\nvoid VNCSConnectionST::enableContinuousUpdates(bool enable,\n                                               int x, int y, int w, int h)\n{\n  core::Rect rect;\n\n  if (!accessCheck(AccessView))\n    return;\n\n  if (!client.supportsFence() || !client.supportsContinuousUpdates())\n    throw protocol_error(\"Client tried to enable continuous updates when not allowed\");\n\n  continuousUpdates = enable;\n\n  rect.setXYWH(x, y, w, h);\n  cuRegion.reset(rect);\n\n  if (enable) {\n    requested.clear();\n  } else {\n    writer()->writeEndOfContinuousUpdates();\n  }\n}\n\nvoid VNCSConnectionST::handleClipboardRequest()\n{\n  server->handleClipboardRequest(this);\n}\n\nvoid VNCSConnectionST::handleClipboardAnnounce(bool available)\n{\n  server->handleClipboardAnnounce(this, available);\n}\n\nvoid VNCSConnectionST::handleClipboardData(const char* data)\n{\n  server->handleClipboardData(this, data);\n}\n\n// supportsLocalCursor() is called whenever the status of\n// client.supportsLocalCursor() has changed.  If the client does now support local\n// cursor, we make sure that the old server-side rendered cursor is cleaned up\n// and the cursor is sent to the client.\n\nvoid VNCSConnectionST::supportsLocalCursor()\n{\n  bool hasRenderedCursor = !damagedCursorRegion.is_empty();\n  if (hasRenderedCursor && !needRenderedCursor())\n    removeRenderedCursor = true;\n  setCursor();\n}\n\nvoid VNCSConnectionST::supportsFence()\n{\n  uint8_t type = 0;\n  writer()->writeFence(fenceFlagRequest, sizeof(type), &type);\n}\n\nvoid VNCSConnectionST::supportsContinuousUpdates()\n{\n  // We refuse to use continuous updates if we cannot monitor the buffer\n  // usage using fences.\n  if (!client.supportsFence())\n    return;\n\n  writer()->writeEndOfContinuousUpdates();\n}\n\nvoid VNCSConnectionST::supportsLEDState()\n{\n  if (client.ledState() == ledUnknown)\n    return;\n\n  writer()->writeLEDState();\n}\n\nvoid VNCSConnectionST::handleTimeout(core::Timer* t)\n{\n  if (t == &socketTimer) {\n    if (state() == RFBSTATE_CLOSING)\n      getSock()->shutdownRead();\n    else\n      close(\"Authentication timeout\");\n  }\n\n  try {\n    if ((t == &congestionTimer) ||\n        (t == &losslessTimer))\n      writeFramebufferUpdate();\n  } catch (std::exception& e) {\n    close(e.what());\n  }\n\n  if (t == &idleTimer)\n    close(\"Idle timeout\");\n}\n\nbool VNCSConnectionST::isShiftPressed()\n{\n    std::map<uint32_t, uint32_t>::const_iterator iter;\n\n    for (iter = pressedKeys.begin(); iter != pressedKeys.end(); ++iter) {\n      if (iter->second == XK_Shift_L)\n        return true;\n      if (iter->second == XK_Shift_R)\n        return true;\n    }\n\n  return false;\n}\n\nvoid VNCSConnectionST::writeRTTPing()\n{\n  uint8_t type;\n\n  if (!client.supportsFence())\n    return;\n\n  congestion.updatePosition(sock->outStream().length());\n\n  // We need to make sure any old update are already processed by the\n  // time we get the response back. This allows us to reliably throttle\n  // back on client overload, as well as network overload.\n  type = 1;\n  writer()->writeFence(fenceFlagRequest | fenceFlagBlockBefore,\n                       sizeof(type), &type);\n\n  congestion.sentPing();\n}\n\nbool VNCSConnectionST::isCongested()\n{\n  int eta;\n\n  congestionTimer.stop();\n\n  // Stuff still waiting in the send buffer?\n  sock->outStream().flush();\n  congestion.debugTrace(\"congestion-trace.csv\", sock->getFd());\n  if (sock->outStream().hasBufferedData())\n    return true;\n\n  if (!client.supportsFence())\n    return false;\n\n  congestion.updatePosition(sock->outStream().length());\n  if (!congestion.isCongested())\n    return false;\n\n  eta = congestion.getUncongestedETA();\n  if (eta >= 0)\n    congestionTimer.start(eta);\n\n  return true;\n}\n\n\nvoid VNCSConnectionST::writeFramebufferUpdate()\n{\n  congestion.updatePosition(sock->outStream().length());\n\n  // We're in the middle of processing a command that's supposed to be\n  // synchronised. Allowing an update to slip out right now might violate\n  // that synchronisation.\n  if (syncFence)\n    return;\n\n  // We try to aggregate responses, so don't send out anything whilst we\n  // still have incoming messages. processMessages() will give us another\n  // chance to run once things are idle.\n  if (inProcessMessages)\n    return;\n\n  if (state() != RFBSTATE_NORMAL)\n    return;\n  if (requested.is_empty() && !continuousUpdates)\n    return;\n\n  // Check that we actually have some space on the link and retry in a\n  // bit if things are congested.\n  if (isCongested())\n    return;\n\n  // Updates often consists of many small writes, and in continuous\n  // mode, we will also have small fence messages around the update. We\n  // need to aggregate these in order to not clog up TCP's congestion\n  // window.\n  getOutStream()->cork(true);\n\n  // First take care of any updates that cannot contain framebuffer data\n  // changes.\n  writeNoDataUpdate();\n\n  // Then real data (if possible)\n  writeDataUpdate();\n\n  getOutStream()->cork(false);\n\n  congestion.updatePosition(sock->outStream().length());\n}\n\nvoid VNCSConnectionST::writeNoDataUpdate()\n{\n  if (!writer()->needNoDataUpdate())\n    return;\n\n  writer()->writeNoDataUpdate();\n\n  // Make sure no data update is sent until next request\n  requested.clear();\n}\n\nvoid VNCSConnectionST::writeDataUpdate()\n{\n  core::Region req;\n  UpdateInfo ui;\n  bool needNewUpdateInfo;\n  const RenderedCursor *cursor;\n\n  // See what the client has requested (if anything)\n  if (continuousUpdates)\n    req = cuRegion.union_(requested);\n  else\n    req = requested;\n\n  if (req.is_empty())\n    return;\n\n  // Get the lists of updates. Prior to exporting the data to the `ui' object,\n  // getUpdateInfo() will normalize the `updates' object such way that its\n  // `changed' and `copied' regions would not intersect.\n  updates.getUpdateInfo(&ui, req);\n  needNewUpdateInfo = false;\n\n  // If the previous position of the rendered cursor overlaps the source of the\n  // copy, then when the copy happens the corresponding rectangle in the\n  // destination will be wrong, so add it to the changed region.\n\n  if (!ui.copied.is_empty() && !damagedCursorRegion.is_empty()) {\n    core::Region bogusCopiedCursor;\n\n    bogusCopiedCursor = damagedCursorRegion;\n    bogusCopiedCursor.translate(ui.copy_delta);\n    bogusCopiedCursor.assign_intersect(server->getPixelBuffer()->getRect());\n    if (!ui.copied.intersect(bogusCopiedCursor).is_empty()) {\n      updates.add_changed(bogusCopiedCursor);\n      needNewUpdateInfo = true;\n    }\n  }\n\n  // If we need to remove the old rendered cursor, just add the region to\n  // the changed region.\n\n  if (removeRenderedCursor) {\n    updates.add_changed(damagedCursorRegion);\n    needNewUpdateInfo = true;\n    damagedCursorRegion.clear();\n    removeRenderedCursor = false;\n  }\n\n  // If we need a full cursor update then make sure its entire region\n  // is marked as changed.\n\n  if (updateRenderedCursor) {\n    updates.add_changed(server->getRenderedCursor()->getEffectiveRect());\n    needNewUpdateInfo = true;\n    updateRenderedCursor = false;\n  }\n\n  // The `updates' object could change, make sure we have valid update info.\n\n  if (needNewUpdateInfo)\n    updates.getUpdateInfo(&ui, req);\n\n  // If there are queued updates then we cannot safely send an update\n  // without risking a partially updated screen\n  if (!server->getPendingRegion().is_empty()) {\n    req.clear();\n    ui.changed.clear();\n    ui.copied.clear();\n  }\n\n  // Does the client need a server-side rendered cursor?\n\n  cursor = nullptr;\n  if (needRenderedCursor()) {\n    core::Rect renderedCursorRect;\n\n    cursor = server->getRenderedCursor();\n    renderedCursorRect = cursor->getEffectiveRect();\n\n    // Check that we don't try to copy over the cursor area, and\n    // if that happens we need to treat it as changed so that we can\n    // re-render it\n    if (!ui.copied.intersect(renderedCursorRect).is_empty()) {\n      ui.changed.assign_union(ui.copied.intersect(renderedCursorRect));\n      ui.copied.assign_subtract(renderedCursorRect);\n    }\n\n    // Track where we've rendered the cursor\n    damagedCursorRegion.assign_union(ui.changed.intersect(renderedCursorRect));\n  }\n\n  // If we don't have a normal update, then try a lossless refresh\n  if (ui.is_empty() && !writer()->needFakeUpdate()) {\n    writeLosslessRefresh();\n    return;\n  }\n\n  // We have something to send, so let's get to it\n\n  writeRTTPing();\n\n  encodeManager.writeUpdate(ui, server->getPixelBuffer(), cursor);\n\n  writeRTTPing();\n\n  // The request might be for just part of the screen, so we cannot\n  // just clear the entire update tracker.\n  updates.subtract(req);\n\n  requested.clear();\n}\n\nvoid VNCSConnectionST::writeLosslessRefresh()\n{\n  core::Region req, pending;\n  const RenderedCursor *cursor;\n\n  int nextRefresh, nextUpdate;\n  size_t bandwidth, maxUpdateSize;\n\n  if (continuousUpdates)\n    req = cuRegion.union_(requested);\n  else\n    req = requested;\n\n  // If there are queued updates then we could not safely send an\n  // update without risking a partially updated screen, however we\n  // might still be able to send a lossless refresh\n  pending = server->getPendingRegion();\n  if (!pending.is_empty()) {\n    UpdateInfo ui;\n\n    // Don't touch the updates pending in the server core\n    req.assign_subtract(pending);\n\n    // Or any updates pending just for this connection\n    updates.getUpdateInfo(&ui, req);\n    req.assign_subtract(ui.changed);\n    req.assign_subtract(ui.copied);\n  }\n\n  // Any lossy area we can refresh?\n  if (!encodeManager.needsLosslessRefresh(req))\n    return;\n\n  // Right away? Or later?\n  nextRefresh = encodeManager.getNextLosslessRefresh(req);\n  if (nextRefresh > 0) {\n    losslessTimer.start(nextRefresh);\n    return;\n  }\n\n  // Prepare the cursor in case it overlaps with a region getting\n  // refreshed\n  cursor = nullptr;\n  if (needRenderedCursor())\n    cursor = server->getRenderedCursor();\n\n  // FIXME: If continuous updates aren't used then the client might\n  //        be slower than frameRate in its requests and we could\n  //        afford a larger update size\n  nextUpdate = server->msToNextUpdate();\n\n  // Don't bother if we're about to send a real update\n  if (nextUpdate == 0)\n    return;\n\n  // FIXME: Bandwidth estimation without congestion control\n  bandwidth = congestion.getBandwidth();\n\n  // FIXME: Hard coded value for maximum CPU throughput\n  if (bandwidth > 5000000)\n    bandwidth = 5000000;\n\n  maxUpdateSize = bandwidth * nextUpdate / 1000;\n\n  writeRTTPing();\n\n  encodeManager.writeLosslessRefresh(req, server->getPixelBuffer(),\n                                     cursor, maxUpdateSize);\n\n  writeRTTPing();\n\n  requested.clear();\n}\n\n\nvoid VNCSConnectionST::screenLayoutChange(uint16_t reason)\n{\n  if (state() != RFBSTATE_NORMAL)\n    return;\n\n  client.setDimensions(client.width(), client.height(),\n                       server->getScreenLayout());\n\n  writer()->writeDesktopSize(reason);\n}\n\n\n// setCursor() is called whenever the cursor has changed shape or pixel format.\n// If the client supports local cursor then it will arrange for the cursor to\n// be sent to the client.\n\nvoid VNCSConnectionST::setCursor()\n{\n  if (state() != RFBSTATE_NORMAL)\n    return;\n\n  // We need to blank out the client's cursor or there will be two\n  if (needRenderedCursor()) {\n    client.setCursor(emptyCursor);\n    clientHasCursor = false;\n  } else {\n    client.setCursor(*server->getCursor());\n    clientHasCursor = true;\n  }\n\n  if (client.supportsLocalCursor())\n    writer()->writeCursor();\n}\n\n// setCursorPos() is called whenever the cursor has changed position by the\n// server.  If the client supports being informed about these changes then it\n// will arrange for the new cursor position to be sent to the client.\n\nvoid VNCSConnectionST::setCursorPos()\n{\n  if (state() != RFBSTATE_NORMAL)\n    return;\n\n  if (client.supportsCursorPosition()) {\n    client.setCursorPos(server->getCursorPos());\n    writer()->writeCursorPos();\n  }\n}\n\nvoid VNCSConnectionST::setDesktopName(const char *name)\n{\n  client.setName(name);\n\n  if (state() != RFBSTATE_NORMAL)\n    return;\n\n  if (client.supportsEncoding(pseudoEncodingDesktopName))\n    writer()->writeSetDesktopName();\n}\n\nvoid VNCSConnectionST::setLEDState(unsigned int ledstate)\n{\n  if (state() != RFBSTATE_NORMAL)\n    return;\n\n  client.setLEDState(ledstate);\n\n  if (client.supportsLEDState())\n    writer()->writeLEDState();\n}\n"
  },
  {
    "path": "common/rfb/VNCSConnectionST.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// VNCSConnectionST is our derived class of SConnection for VNCServerST - there\n// is one for each connected client.  We think of VNCSConnectionST as part of\n// the VNCServerST implementation, so its methods are allowed full access to\n// members of VNCServerST.\n//\n\n#ifndef __RFB_VNCSCONNECTIONST_H__\n#define __RFB_VNCSCONNECTIONST_H__\n\n#include <map>\n\n#include <core/Timer.h>\n\n#include <rfb/Congestion.h>\n#include <rfb/EncodeManager.h>\n#include <rfb/SConnection.h>\n\nnamespace rfb {\n  class VNCServerST;\n\n  class VNCSConnectionST : private SConnection,\n                           public core::Timer::Callback {\n  public:\n    VNCSConnectionST(VNCServerST* server_, network::Socket* s, bool reverse,\n                     AccessRights ar);\n    virtual ~VNCSConnectionST();\n\n    // SConnection methods\n\n    bool accessCheck(AccessRights ar) const override;\n    void close(const char* reason) override;\n\n    using SConnection::authenticated;\n\n    // Methods called from VNCServerST.  None of these methods ever knowingly\n    // throw an exception.\n\n    // init() must be called to initialise the protocol.  If it fails it\n    // returns false, and close() will have been called.\n    bool init();\n\n    // processSocketReadEvent() processes incoming messages from the\n    // client, invoking various callbacks as a result.  It continues to\n    // process messages until reading might block.  shutdown() will be\n    // called on the connection's Socket if an error occurs, via the\n    // close() call.\n    void processSocketReadEvent();\n\n    // processSocketWriteEvent() pushes any unwritten data on to the\n    // network.\n    void processSocketWriteEvent();\n\n    // Called when the underlying pixelbuffer is resized or replaced.\n    void pixelBufferChange();\n\n    // Wrappers to make these methods \"safe\" for VNCServerST.\n    void writeFramebufferUpdateOrClose();\n    void screenLayoutChangeOrClose(uint16_t reason);\n    void setCursorOrClose();\n    void bellOrClose();\n    void setDesktopNameOrClose(const char *name);\n    void setLEDStateOrClose(unsigned int state);\n    void approveConnectionOrClose(bool accept, const char* reason);\n    void requestClipboardOrClose();\n    void announceClipboardOrClose(bool available);\n    void sendClipboardDataOrClose(const char* data);\n    void desktopReadyOrClose();\n\n    // The following methods never throw exceptions\n\n    // getComparerState() returns if this client would like the framebuffer\n    // comparer to be enabled.\n    bool getComparerState();\n\n    // renderedCursorChange() is called whenever the server-side rendered\n    // cursor changes shape or position.  It ensures that the next update will\n    // clean up the old rendered cursor and if necessary draw the new rendered\n    // cursor.\n    void renderedCursorChange();\n\n    // cursorPositionChange() is called whenever the cursor has changed position by\n    // the server.  If the client supports being informed about these changes then\n    // it will arrange for the new cursor position to be sent to the client.\n    void cursorPositionChange();\n\n    // needRenderedCursor() returns true if this client needs the server-side\n    // rendered cursor.  This may be because it does not support local cursor\n    // or because the current cursor position has not been set by this client.\n    bool needRenderedCursor();\n\n    network::Socket* getSock() { return sock; }\n\n    // Change tracking\n\n    void add_changed(const core::Region& region) { updates.add_changed(region); }\n    void add_copied(const core::Region& dest, const core::Point& delta) {\n      updates.add_copied(dest, delta);\n    }\n\n    const char* getPeerEndpoint() const {return peerEndpoint.c_str();}\n\n  private:\n    // SConnection callbacks\n\n    // These methods are invoked as callbacks from processMsg(\n    void authSuccess() override;\n    void queryConnection(const char* userName) override;\n    void clientReady(bool shared) override;\n    void setPixelFormat(const PixelFormat& pf) override;\n    void pointerEvent(const core::Point& pos,\n                      uint16_t buttonMask) override;\n    void keyEvent(uint32_t keysym, uint32_t keycode,\n                  bool down) override;\n    void framebufferUpdateRequest(const core::Rect& r,\n                                  bool incremental) override;\n    void setDesktopSize(int fb_width, int fb_height,\n                        const ScreenSet& layout) override;\n    void fence(uint32_t flags, unsigned len,\n               const uint8_t data[]) override;\n    void enableContinuousUpdates(bool enable,\n                                 int x, int y, int w, int h) override;\n    void handleClipboardRequest() override;\n    void handleClipboardAnnounce(bool available) override;\n    void handleClipboardData(const char* data) override;\n    void supportsLocalCursor() override;\n    void supportsFence() override;\n    void supportsContinuousUpdates() override;\n    void supportsLEDState() override;\n\n    // Timer callbacks\n    void handleTimeout(core::Timer* t) override;\n\n    // Internal methods\n\n    bool isShiftPressed();\n\n    // Congestion control\n    void writeRTTPing();\n    bool isCongested();\n\n    // writeFramebufferUpdate() attempts to write a framebuffer update to the\n    // client.\n\n    void writeFramebufferUpdate();\n    void writeNoDataUpdate();\n    void writeDataUpdate();\n    void writeLosslessRefresh();\n\n    void screenLayoutChange(uint16_t reason);\n    void setCursor();\n    void setCursorPos();\n    void setDesktopName(const char *name);\n    void setLEDState(unsigned int state);\n    void desktopReady() override;\n\n  private:\n    network::Socket* sock;\n    core::Timer socketTimer;\n    std::string peerEndpoint;\n    bool reverseConnection;\n\n    bool inProcessMessages;\n\n    bool pendingSyncFence, syncFence;\n    uint32_t fenceFlags;\n    unsigned fenceDataLen;\n    uint8_t *fenceData;\n\n    Congestion congestion;\n    core::Timer congestionTimer;\n    core::Timer losslessTimer;\n\n    VNCServerST* server;\n    SimpleUpdateTracker updates;\n    core::Region requested;\n    bool updateRenderedCursor, removeRenderedCursor;\n    core::Region damagedCursorRegion;\n    bool continuousUpdates;\n    core::Region cuRegion;\n    EncodeManager encodeManager;\n\n    std::map<uint32_t, uint32_t> pressedKeys;\n\n    core::Timer idleTimer;\n\n    time_t pointerEventTime;\n    core::Point pointerEventPos;\n    bool clientHasCursor;\n\n    std::string closeReason;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/VNCServer.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// VNCServer - abstract interface implemented by the RFB library.  The back-end\n// code calls the relevant methods as appropriate.\n\n#ifndef __RFB_VNCSERVER_H__\n#define __RFB_VNCSERVER_H__\n\n#include <list>\n\n#include <rfb/AccessRights.h>\n#include <rfb/UpdateTracker.h>\n\nnamespace network { class Socket; }\n\nnamespace rfb {\n\n  class PixelBuffer;\n  class SConnection;\n  struct ScreenSet;\n\n  class VNCServer : public UpdateTracker {\n  public:\n    // addSocket() tells the server to serve the Socket.  The caller\n    //   retains ownership of the Socket - the only way for the server\n    //   to discard a Socket is by calling shutdown() on it.\n    //   outgoing is set to true if the socket was created by connecting out\n    //   to another host, or false if the socket was created by accept()ing\n    //   an incoming connection.\n    //   accessRights allows to set the access rights to the server.\n    //   Returns true if the socket was successfully added, and false if\n    //   something went wrong. The socket is in an unknown state at this\n    //   point and should be closed.\n    virtual bool addSocket(network::Socket* sock, bool outgoing=false,\n                           AccessRights accessRights = AccessDefault) = 0;\n\n    // removeSocket() tells the server to stop serving the Socket.  The\n    //   caller retains ownership of the Socket - the server must NOT\n    //   delete the Socket!  This call is used mainly to cause per-Socket\n    //   resources to be freed.\n    virtual void removeSocket(network::Socket* sock) = 0;\n\n    // getSockets() gets a list of sockets.  This can be used to generate an\n    //   fd_set for calling select().\n    virtual void getSockets(std::list<network::Socket*>* sockets) = 0;\n\n    // processSocketReadEvent() tells the server there is a Socket read event.\n    //   The implementation can indicate that the Socket is no longer active\n    //   by calling shutdown() on it.  The caller will then call removeSocket()\n    //   soon after processSocketEvent returns, to allow any pre-Socket\n    //   resources to be tidied up.\n    virtual void processSocketReadEvent(network::Socket* sock) = 0;\n\n    // processSocketReadEvent() tells the server there is a Socket write event.\n    //   This is only necessary if the Socket has been put in non-blocking\n    //   mode and needs this callback to flush the buffer.\n    virtual void processSocketWriteEvent(network::Socket* sock) = 0;\n\n    // blockUpdates()/unblockUpdates() tells the server that the pixel buffer\n    // is currently in flux and may not be accessed. The attributes of the\n    // pixel buffer may still be accessed, but not the frame buffer itself.\n    // Note that access must be unblocked the exact same number of times it\n    // was blocked.\n    virtual void blockUpdates() = 0;\n    virtual void unblockUpdates() = 0;\n\n    virtual uint64_t getMsc() = 0;\n    virtual void queueMsc(uint64_t target) = 0;\n\n    // setPixelBuffer() tells the server to use the given pixel buffer (and\n    // optionally a modified screen layout).  If this differs in size from\n    // the previous pixel buffer, this may result in protocol messages being\n    // sent, or clients being disconnected.\n    virtual void setPixelBuffer(PixelBuffer* pb, const ScreenSet& layout) = 0;\n    virtual void setPixelBuffer(PixelBuffer* pb) = 0;\n\n    // setScreenLayout() modifies the current screen layout without changing\n    // the pixelbuffer. Clients will be notified of the new layout.\n    virtual void setScreenLayout(const ScreenSet& layout) = 0;\n\n    // getPixelBuffer() returns a pointer to the PixelBuffer object.\n    virtual const PixelBuffer* getPixelBuffer() const = 0;\n\n    // requestClipboard() will result in a request to a client to\n    // transfer its clipboard data. A call to\n    // SDesktop::handleClipboardData() will be made once the data is\n    // available.\n    virtual void requestClipboard() = 0;\n\n    // announceClipboard() informs all clients of changes to the\n    // clipboard on the server. A client may later request the\n    // clipboard data via SDesktop::handleClipboardRequest().\n    virtual void announceClipboard(bool available) = 0;\n\n    // sendClipboardData() transfers the clipboard data to a client\n    // and should be called whenever a client has requested the\n    // clipboard via SDesktop::handleClipboardRequest().\n    virtual void sendClipboardData(const char* data) = 0;\n\n    // bell() tells the server that it should make all clients make a bell sound.\n    virtual void bell() = 0;\n\n    // approveConnection() is called some time after\n    // SDesktop::queryConnection() has been called, to accept or reject\n    // the connection.  The accept argument should be true for\n    // acceptance, or false for rejection, in which case a string\n    // reason may also be given.\n    virtual void approveConnection(network::Socket* sock, bool accept,\n                                   const char* reason = nullptr) = 0;\n\n    // - Close all currently-connected clients, by calling\n    //   their close() method with the supplied reason.\n    virtual void closeClients(const char* reason) = 0;\n\n    // getConnection() gets the SConnection for a particular Socket.  If\n    // the Socket is not recognised then null is returned.\n    virtual SConnection* getConnection(network::Socket* sock) = 0;\n\n    // setCursor() tells the server that the cursor has changed.  The\n    // cursorData argument contains width*height rgba quadruplets with\n    // non-premultiplied alpha.\n    virtual void setCursor(int width, int height,\n                           const core::Point& hotspot,\n                           const uint8_t* cursorData) = 0;\n\n    // setCursorPos() tells the server the current position of the cursor, and\n    // whether the server initiated that change (e.g. through another X11\n    // client calling XWarpPointer()).\n    virtual void setCursorPos(const core::Point& p, bool warped) = 0;\n\n    // setName() tells the server what desktop title to supply to clients\n    virtual void setName(const char* name) = 0;\n\n    // setLEDState() tells the server what the current lock keys LED\n    // state is\n    virtual void setLEDState(unsigned int state) = 0;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/VNCServerST.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Single-Threaded VNC server implementation\n\n\n// Note about how sockets get closed:\n//\n// Closing sockets to clients is non-trivial because the code which calls\n// VNCServerST must explicitly know about all the sockets (so that it can block\n// on them appropriately).  However, VNCServerST may want to close clients for\n// a number of reasons, and from a variety of entry points.  The simplest is\n// when processSocketEvent() is called for a client, and the remote end has\n// closed its socket.  A more complex reason is when processSocketEvent() is\n// called for a client which has just sent a ClientInit with the shared flag\n// set to false - in this case we want to close all other clients.  Yet another\n// reason for disconnecting clients is when the desktop size has changed as a\n// result of a call to setPixelBuffer().\n//\n// The responsibility for creating and deleting sockets is entirely with the\n// calling code.  When VNCServerST wants to close a connection to a client it\n// calls the VNCSConnectionST's close() method which calls shutdown() on the\n// socket.  Eventually the calling code will notice that the socket has been\n// shut down and call removeSocket() so that we can delete the\n// VNCSConnectionST.  Note that the socket must not be deleted by the calling\n// code until after removeSocket() has been called.\n//\n// One minor complication is that we don't allocate a VNCSConnectionST object\n// for a blacklisted host (since we want to minimise the resources used for\n// dealing with such a connection).  In order to properly implement the\n// getSockets function, we must maintain a separate closingSockets list,\n// otherwise blacklisted connections might be \"forgotten\".\n\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <stdlib.h>\n\n#include <core/LogWriter.h>\n#include <core/time.h>\n\n#include <rdr/FdOutStream.h>\n\n#include <network/Socket.h>\n\n#include <rfb/ComparingUpdateTracker.h>\n#include <rfb/KeyRemapper.h>\n#include <rfb/KeysymStr.h>\n#include <rfb/SDesktop.h>\n#include <rfb/Security.h>\n#include <rfb/ServerCore.h>\n#include <rfb/VNCServerST.h>\n#include <rfb/VNCSConnectionST.h>\n#include <rfb/ledStates.h>\n\n\nusing namespace rfb;\n\nstatic core::LogWriter slog(\"VNCServerST\");\nstatic core::LogWriter connectionsLog(\"Connections\");\n\n//\n// -=- VNCServerST Implementation\n//\n\n// -=- Constructors/Destructor\n\nVNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)\n  : desktop(desktop_), desktopStarted(false),\n    desktopStarting(false), blockCounter(0), pb(nullptr),\n    ledState(ledUnknown), name(name_), pointerClient(nullptr),\n    clipboardClient(nullptr), pointerClientTime(0),\n    comparer(nullptr), cursor(new Cursor(0, 0, {}, nullptr)),\n    renderedCursorInvalid(false),\n    keyRemapper(&KeyRemapper::defInstance),\n    idleTimer(this), disconnectTimer(this), connectTimer(this),\n    msc(0), queuedMsc(0), frameTimer(this)\n{\n  slog.debug(\"Creating single-threaded server %s\", name.c_str());\n\n  desktop_->init(this);\n\n  // FIXME: Do we really want to kick off these right away?\n  if (rfb::Server::maxIdleTime)\n    idleTimer.start(core::secsToMillis(rfb::Server::maxIdleTime));\n  if (rfb::Server::maxDisconnectionTime)\n    disconnectTimer.start(core::secsToMillis(rfb::Server::maxDisconnectionTime));\n}\n\nVNCServerST::~VNCServerST()\n{\n  slog.debug(\"Shutting down server %s\", name.c_str());\n\n  // Close any active clients, with appropriate logging & cleanup\n  closeClients(\"Server shutdown\");\n\n  // Stop trying to render things\n  stopFrameClock();\n\n  // Delete all the clients, and their sockets, and any closing sockets\n  while (!clients.empty()) {\n    VNCSConnectionST* client;\n    client = clients.front();\n    clients.pop_front();\n    delete client;\n  }\n\n  // Stop the desktop object if active, *only* after deleting all clients!\n  stopDesktop();\n\n  if (comparer)\n    comparer->logStats();\n  delete comparer;\n\n  delete cursor;\n}\n\n\n// VNCServer methods\n\nbool VNCServerST::addSocket(network::Socket* sock, bool outgoing, AccessRights accessRights)\n{\n  // - Check the connection isn't black-marked\n  // *** do this in getSecurity instead?\n  const char *address = sock->getPeerAddress();\n  if (blacklist.isBlackmarked(address)) {\n    connectionsLog.error(\"Blacklisted: %s\", address);\n    try {\n      rdr::OutStream& os = sock->outStream();\n\n      // Shortest possible way to tell a client it is not welcome\n      os.writeBytes((const uint8_t*)\"RFB 003.003\\n\", 12);\n      os.writeU32(0);\n      const char* reason = \"Too many security failures\";\n      os.writeU32(strlen(reason));\n      os.writeBytes((const uint8_t*)reason, strlen(reason));\n      os.flush();\n    } catch (std::exception&) {\n    }\n    return false;\n  }\n\n  connectionsLog.status(\"Accepted: %s\", sock->getPeerEndpoint());\n\n  try {\n    VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing, accessRights);\n    clients.push_front(client);\n    client->init();\n  } catch (std::exception& e) {\n    connectionsLog.error(\"Error accepting client: %s\", e.what());\n    return false;\n  }\n\n  return true;\n}\n\nvoid VNCServerST::removeSocket(network::Socket* sock) {\n  // - If the socket has resources allocated to it, delete them\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ci++) {\n    if ((*ci)->getSock() == sock) {\n      // - Remove any references to it\n      if (pointerClient == *ci) {\n        // Release the mouse buttons the client have pressed\n        desktop->pointerEvent(cursorPos, 0);\n        pointerClient = nullptr;\n      }\n      if (clipboardClient == *ci)\n        handleClipboardAnnounce(*ci, false);\n      clipboardRequestors.remove(*ci);\n\n      std::string peer((*ci)->getPeerEndpoint());\n\n      // - Delete the per-Socket resources\n      delete *ci;\n\n      clients.remove(*ci);\n\n      connectionsLog.status(\"Closed: %s\", peer.c_str());\n\n      // - Check that the desktop object is still required\n      if (authClientCount() == 0)\n        stopDesktop();\n\n      if (comparer)\n        comparer->logStats();\n\n      // Adjust the exit timers\n      if (authClientCount() == 0) {\n        connectTimer.stop();\n        if (rfb::Server::maxDisconnectionTime)\n          disconnectTimer.start(core::secsToMillis(rfb::Server::maxDisconnectionTime));\n      }\n\n      return;\n    }\n  }\n\n  throw std::invalid_argument(\"Invalid Socket in VNCServerST\");\n}\n\nvoid VNCServerST::processSocketReadEvent(network::Socket* sock)\n{\n  // - Find the appropriate VNCSConnectionST and process the event\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ci++) {\n    if ((*ci)->getSock() == sock) {\n      (*ci)->processSocketReadEvent();\n      return;\n    }\n  }\n  throw std::invalid_argument(\"Invalid Socket in VNCServerST\");\n}\n\nvoid VNCServerST::processSocketWriteEvent(network::Socket* sock)\n{\n  // - Find the appropriate VNCSConnectionST and process the event\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ci++) {\n    if ((*ci)->getSock() == sock) {\n      (*ci)->processSocketWriteEvent();\n      return;\n    }\n  }\n  throw std::invalid_argument(\"Invalid Socket in VNCServerST\");\n}\n\nvoid VNCServerST::blockUpdates()\n{\n  blockCounter++;\n\n  stopFrameClock();\n}\n\nvoid VNCServerST::unblockUpdates()\n{\n  assert(blockCounter > 0);\n\n  blockCounter--;\n\n  // Restart the frame clock in case we have updates\n  if (blockCounter == 0)\n    startFrameClock();\n}\n\nuint64_t VNCServerST::getMsc()\n{\n  return msc;\n}\n\nvoid VNCServerST::queueMsc(uint64_t target)\n{\n  if (target > queuedMsc)\n    queuedMsc = target;\n\n  startFrameClock();\n}\n\nvoid VNCServerST::setPixelBuffer(PixelBuffer* pb_, const ScreenSet& layout)\n{\n  if (comparer)\n    comparer->logStats();\n\n  pb = pb_;\n  delete comparer;\n  comparer = nullptr;\n\n  if (!pb) {\n    screenLayout = ScreenSet();\n\n    if (desktopStarted)\n      throw std::logic_error(\"setPixelBuffer: Null PixelBuffer when desktopStarted?\");\n\n    return;\n  }\n\n  if (!layout.validate(pb->width(), pb->height()))\n    throw std::invalid_argument(\"setPixelBuffer: Invalid screen layout\");\n\n  screenLayout = layout;\n\n  // Assume the framebuffer contents wasn't saved and reset everything\n  // that tracks its contents\n  comparer = new ComparingUpdateTracker(pb);\n  renderedCursorInvalid = true;\n  add_changed(pb->getRect());\n\n  // The desktop is considered ready after the pixelbuffer is set\n  checkDesktopReady();\n\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ++ci) {\n    (*ci)->pixelBufferChange();\n    // Since the new pixel buffer means an ExtendedDesktopSize needs to\n    // be sent anyway, we don't need to call screenLayoutChange.\n  }\n}\n\nvoid VNCServerST::setPixelBuffer(PixelBuffer* pb_)\n{\n  ScreenSet layout = screenLayout;\n\n  if (!pb_) {\n    setPixelBuffer(nullptr, ScreenSet());\n    return;\n  }\n\n  // Check that the screen layout is still valid\n  if (!layout.validate(pb_->width(), pb_->height())) {\n    core::Rect fbRect;\n    ScreenSet::iterator iter, iter_next;\n\n    fbRect.setXYWH(0, 0, pb_->width(), pb_->height());\n\n    for (iter = layout.begin();iter != layout.end();iter = iter_next) {\n      iter_next = iter; ++iter_next;\n      if (iter->dimensions.enclosed_by(fbRect))\n          continue;\n      iter->dimensions = iter->dimensions.intersect(fbRect);\n      if (iter->dimensions.is_empty()) {\n        slog.info(\"Removing screen %d (%x) as it is completely outside the new framebuffer\",\n                  (int)iter->id, (unsigned)iter->id);\n        layout.remove_screen(iter->id);\n      }\n    }\n  }\n\n  // Make sure that we have at least one screen\n  if (layout.num_screens() == 0)\n    layout.add_screen(Screen(0, 0, 0, pb_->width(), pb_->height(), 0));\n\n  setPixelBuffer(pb_, layout);\n}\n\nvoid VNCServerST::setScreenLayout(const ScreenSet& layout)\n{\n  if (!pb)\n    throw std::logic_error(\"setScreenLayout: New screen layout without a PixelBuffer\");\n  if (!layout.validate(pb->width(), pb->height()))\n    throw std::invalid_argument(\"setScreenLayout: Invalid screen layout\");\n\n  screenLayout = layout;\n\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ++ci)\n    (*ci)->screenLayoutChangeOrClose(reasonServer);\n}\n\nvoid VNCServerST::requestClipboard()\n{\n  if (!rfb::Server::acceptCutText)\n    return;\n\n  if (clipboardClient == nullptr) {\n    slog.debug(\"Got request for client clipboard but no client currently owns the clipboard\");\n    return;\n  }\n\n  clipboardClient->requestClipboardOrClose();\n}\n\nvoid VNCServerST::announceClipboard(bool available)\n{\n  std::list<VNCSConnectionST*>::iterator ci;\n\n  clipboardRequestors.clear();\n\n  if (!rfb::Server::sendCutText)\n    return;\n\n  for (ci = clients.begin(); ci != clients.end(); ++ci)\n    (*ci)->announceClipboardOrClose(available);\n}\n\nvoid VNCServerST::sendClipboardData(const char* data)\n{\n  std::list<VNCSConnectionST*>::iterator ci;\n\n  if (!rfb::Server::sendCutText)\n    return;\n\n  if (strchr(data, '\\r') != nullptr)\n    throw std::invalid_argument(\"Invalid carriage return in clipboard data\");\n\n  for (ci = clipboardRequestors.begin();\n       ci != clipboardRequestors.end(); ++ci)\n    (*ci)->sendClipboardDataOrClose(data);\n\n  clipboardRequestors.clear();\n}\n\nvoid VNCServerST::checkDesktopReady()\n{\n  if (!desktopStarting)\n    return;\n\n  if (!pb)\n    return;\n\n  desktopStarting = false;\n  desktopReady();\n}\n\nvoid VNCServerST::desktopReady()\n{\n  if (!pb)\n      throw std::logic_error(\"desktopReady: Null PixelBuffer when desktop is ready\");\n\n  desktopStarted = true;\n  // The tracker might have accumulated changes whilst we were\n  // stopped, so flush those out\n  assert(comparer != nullptr);\n  if (!comparer->is_empty())\n    writeUpdate();\n  // If the frame clock is running, then it will be running slowly,\n  // so give it a kick to run at normal speed right away\n  if (frameTimer.isStarted()) {\n    stopFrameClock();\n    startFrameClock();\n  }\n\n  // Now that the desktop is ready, client connections can continue\n  for (VNCSConnectionST* client : clients)\n    client->desktopReadyOrClose();\n}\n\nvoid VNCServerST::bell()\n{\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ++ci)\n    (*ci)->bellOrClose();\n}\n\nvoid VNCServerST::setName(const char* name_)\n{\n  name = name_;\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ++ci)\n    (*ci)->setDesktopNameOrClose(name_);\n}\n\nvoid VNCServerST::add_changed(const core::Region& region)\n{\n  if (comparer == nullptr)\n    return;\n\n  comparer->add_changed(region);\n  startFrameClock();\n}\n\nvoid VNCServerST::add_copied(const core::Region& dest,\n                             const core::Point& delta)\n{\n  if (comparer == nullptr)\n    return;\n\n  comparer->add_copied(dest, delta);\n  startFrameClock();\n}\n\nvoid VNCServerST::setCursor(int width, int height,\n                            const core::Point& newHotspot,\n                            const uint8_t* data)\n{\n  delete cursor;\n  cursor = new Cursor(width, height, newHotspot, data);\n  cursor->crop();\n\n  renderedCursorInvalid = true;\n\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ++ci) {\n    (*ci)->renderedCursorChange();\n    (*ci)->setCursorOrClose();\n  }\n}\n\nvoid VNCServerST::setCursorPos(const core::Point& pos, bool warped)\n{\n  if (cursorPos != pos) {\n    cursorPos = pos;\n    renderedCursorInvalid = true;\n    std::list<VNCSConnectionST*>::iterator ci;\n    for (ci = clients.begin(); ci != clients.end(); ci++) {\n      (*ci)->renderedCursorChange();\n      if (warped)\n        (*ci)->cursorPositionChange();\n    }\n  }\n}\n\nvoid VNCServerST::setLEDState(unsigned int state)\n{\n  std::list<VNCSConnectionST*>::iterator ci;\n\n  if (state == ledState)\n    return;\n\n  ledState = state;\n\n  for (ci = clients.begin(); ci != clients.end(); ++ci)\n    (*ci)->setLEDStateOrClose(state);\n}\n\n// Event handlers\n\nvoid VNCServerST::keyEvent(uint32_t keysym, uint32_t keycode, bool down)\n{\n  if (!rfb::Server::acceptKeyEvents)\n    return;\n\n  if (rfb::Server::maxIdleTime)\n    idleTimer.start(core::secsToMillis(rfb::Server::maxIdleTime));\n\n  // Remap the key if required\n  if (keyRemapper) {\n    uint32_t newkey;\n    newkey = keyRemapper->remapKey(keysym);\n    if (newkey != keysym) {\n      slog.debug(\"Key remapped to XK_%s (0x%x)\",\n                 KeySymName(newkey), newkey);\n      keysym = newkey;\n    }\n  }\n\n  desktop->keyEvent(keysym, keycode, down);\n}\n\nvoid VNCServerST::pointerEvent(VNCSConnectionST* client,\n                               const core::Point& pos,\n                               uint16_t buttonMask)\n{\n  time_t now = time(nullptr);\n\n  if (!rfb::Server::acceptPointerEvents)\n    return;\n\n  if (rfb::Server::maxIdleTime)\n    idleTimer.start(core::secsToMillis(rfb::Server::maxIdleTime));\n\n  // Let one client own the cursor whilst buttons are pressed in order\n  // to provide a bit more sane user experience. But limit the time to\n  // prevent locking out all others when e.g. the network is down.\n  if ((pointerClient != nullptr) && (pointerClient != client) &&\n      ((now - pointerClientTime) < 10))\n    return;\n\n  pointerClientTime = now;\n  if (buttonMask)\n    pointerClient = client;\n  else\n    pointerClient = nullptr;\n\n  desktop->pointerEvent(pos, buttonMask);\n}\n\nvoid VNCServerST::handleClipboardRequest(VNCSConnectionST* client)\n{\n  clipboardRequestors.push_back(client);\n  if (clipboardRequestors.size() == 1)\n    desktop->handleClipboardRequest();\n}\n\nvoid VNCServerST::handleClipboardAnnounce(VNCSConnectionST* client,\n                                          bool available)\n{\n  if (available) {\n    if (!rfb::Server::acceptCutText)\n      return;\n    clipboardClient = client;\n  } else {\n    if (client != clipboardClient)\n      return;\n    clipboardClient = nullptr;\n  }\n  desktop->handleClipboardAnnounce(available);\n}\n\nvoid VNCServerST::handleClipboardData(VNCSConnectionST* client,\n                                      const char* data)\n{\n  if (!rfb::Server::acceptCutText)\n    return;\n  if (client != clipboardClient) {\n    slog.debug(\"Ignoring unexpected clipboard data\");\n    return;\n  }\n  desktop->handleClipboardData(data);\n}\n\nunsigned int VNCServerST::setDesktopSize(VNCSConnectionST* requester,\n                                         int fb_width, int fb_height,\n                                         const ScreenSet& layout)\n{\n  unsigned int result;\n  std::list<VNCSConnectionST*>::iterator ci;\n\n  if (!rfb::Server::acceptSetDesktopSize) {\n    slog.debug(\"Rejecting unauthorized framebuffer resize request\");\n    return resultProhibited;\n  }\n\n  // We can't handle a framebuffer larger than this, so don't let a\n  // client set one (see PixelBuffer.cxx)\n  if ((fb_width > 16384) || (fb_height > 16384)) {\n    slog.error(\"Rejecting too large framebuffer resize request\");\n    return resultProhibited;\n  }\n\n  // Don't bother the desktop with an invalid configuration\n  if (!layout.validate(fb_width, fb_height)) {\n    slog.error(\"Invalid screen layout requested by client\");\n    return resultInvalid;\n  }\n\n  // FIXME: the desktop will call back to VNCServerST and an extra set\n  // of ExtendedDesktopSize messages will be sent. This is okay\n  // protocol-wise, but unnecessary.\n  result = desktop->setScreenLayout(fb_width, fb_height, layout);\n  if (result != resultSuccess)\n    return result;\n\n  // Sanity check\n  if (screenLayout != layout)\n    throw std::runtime_error(\"Desktop configured a different screen layout than requested\");\n\n  // Notify other clients\n  for (ci = clients.begin(); ci != clients.end(); ++ci) {\n    if ((*ci) == requester)\n      continue;\n    (*ci)->screenLayoutChangeOrClose(reasonOtherClient);\n  }\n\n  return resultSuccess;\n}\n\n// Other public methods\n\nvoid VNCServerST::approveConnection(network::Socket* sock, bool accept,\n                                    const char* reason)\n{\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ci++) {\n    if ((*ci)->getSock() == sock) {\n      (*ci)->approveConnectionOrClose(accept, reason);\n      return;\n    }\n  }\n}\n\nvoid VNCServerST::closeClients(const char* reason, network::Socket* except)\n{\n  std::list<VNCSConnectionST*>::iterator i;\n  for (i = clients.begin(); i != clients.end(); ++i) {\n    if ((*i)->getSock() != except)\n      (*i)->close(reason);\n  }\n}\n\nvoid VNCServerST::getSockets(std::list<network::Socket*>* sockets)\n{\n  sockets->clear();\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ci++) {\n    sockets->push_back((*ci)->getSock());\n  }\n}\n\nSConnection* VNCServerST::getConnection(network::Socket* sock) {\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ci++) {\n    if ((*ci)->getSock() == sock)\n      return (SConnection*)*ci;\n  }\n  return nullptr;\n}\n\nvoid VNCServerST::handleTimeout(core::Timer* t)\n{\n  if (t == &frameTimer) {\n    int timeout;\n\n    // We keep running until we go a full interval without any updates,\n    // or there are no active clients anymore\n    if (!desktopStarted ||\n        ((comparer != nullptr) && comparer->is_empty())) {\n      // Unless something waits for us to advance the frame count\n      if (queuedMsc < msc)\n        return;\n    }\n\n    // If this is the first iteration then we need to adjust the timeout\n    timeout = 1000/rfb::Server::frameRate;\n\n    // If there are no clients, then slow down the clock\n    if (!desktopStarted)\n      timeout = 1000;\n\n    frameTimer.repeat(timeout);\n\n    if (desktopStarted &&\n        ((comparer != nullptr) && !comparer->is_empty()))\n      writeUpdate();\n\n    msc++;\n    desktop->frameTick(msc);\n  } else if (t == &idleTimer) {\n    slog.info(\"MaxIdleTime reached, exiting\");\n    desktop->terminate();\n  } else if (t == &disconnectTimer) {\n    slog.info(\"MaxDisconnectionTime reached, exiting\");\n    desktop->terminate();\n  } else if (t == &connectTimer) {\n    slog.info(\"MaxConnectionTime reached, exiting\");\n    desktop->terminate();\n  }\n}\n\nvoid VNCServerST::queryConnection(VNCSConnectionST* client,\n                                  const char* userName)\n{\n  // - Authentication succeeded - clear from blacklist\n  blacklist.clearBlackmark(client->getSock()->getPeerAddress());\n\n  // - Prepare the desktop for that the client will start requiring\n  // resources after this\n  startDesktop();\n\n  // - Special case to provide a more useful error message\n  if (rfb::Server::neverShared &&\n      !rfb::Server::disconnectClients &&\n      authClientCount() > 0) {\n    approveConnection(client->getSock(), false,\n                      \"The server is already in use\");\n    return;\n  }\n\n  // - Are we configured to do queries?\n  if (!rfb::Server::queryConnect &&\n      !client->getSock()->requiresQuery()) {\n    approveConnection(client->getSock(), true, nullptr);\n    return;\n  }\n\n  // - Does the client have the right to bypass the query?\n  if (client->accessCheck(AccessNoQuery))\n  {\n    approveConnection(client->getSock(), true, nullptr);\n    return;\n  }\n\n  desktop->queryConnection(client->getSock(), userName);\n}\n\nvoid VNCServerST::clientReady(VNCSConnectionST* client, bool shared)\n{\n  // Adjust the exit timers\n  if (rfb::Server::maxConnectionTime && !connectTimer.isStarted())\n    connectTimer.start(core::secsToMillis(rfb::Server::maxConnectionTime));\n  disconnectTimer.stop();\n\n  if (!shared) {\n    if (rfb::Server::disconnectClients &&\n        client->accessCheck(AccessNonShared)) {\n      // - Close all the other connected clients\n      slog.debug(\"Non-shared connection - closing clients\");\n      closeClients(\"Non-shared connection requested\", client->getSock());\n    } else {\n      // - Refuse this connection if there are existing clients, in addition to\n      // this one\n      if (authClientCount() > 1) {\n        client->close(\"Server is already in use\");\n        return;\n      }\n    }\n  }\n}\n\n// -=- Internal methods\n\nvoid VNCServerST::startDesktop()\n{\n  if (!desktopStarted && !desktopStarting) {\n    slog.debug(\"Starting desktop\");\n    desktopStarting = true;\n    desktop->start();\n    // We might have already been in a ready state\n    checkDesktopReady();\n  }\n}\n\nvoid VNCServerST::stopDesktop()\n{\n  if (desktopStarted || desktopStarting) {\n    slog.debug(\"Stopping desktop\");\n    desktopStarted = false;\n    desktopStarting = false;\n    desktop->stop();\n  }\n}\n\nint VNCServerST::authClientCount() {\n  int count = 0;\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ci++) {\n    if ((*ci)->authenticated())\n      count++;\n  }\n  return count;\n}\n\ninline bool VNCServerST::needRenderedCursor()\n{\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ci++)\n    if ((*ci)->needRenderedCursor()) return true;\n  return false;\n}\n\nvoid VNCServerST::startFrameClock()\n{\n  if (frameTimer.isStarted())\n    return;\n  if (blockCounter > 0)\n    return;\n\n  // Anyone actually interested in frames?\n  if (!desktopStarted ||\n      ((comparer != nullptr) && comparer->is_empty())) {\n    if (queuedMsc < msc)\n      return;\n  }\n\n  // Run the frame clock very slowly if there are no clients to actually\n  // send updates to\n  if (!desktopStarted) {\n    frameTimer.start(1000);\n    return;\n  }\n\n  // The first iteration will be just half a frame as we get a very\n  // unstable update rate if we happen to be perfectly in sync with\n  // the application's update rate\n  frameTimer.start(1000/rfb::Server::frameRate/2);\n}\n\nvoid VNCServerST::stopFrameClock()\n{\n  frameTimer.stop();\n}\n\nint VNCServerST::msToNextUpdate()\n{\n  // FIXME: If the application is updating slower than frameRate then\n  //        we could allow the clients more time here\n\n  if (!frameTimer.isStarted())\n    return 1000/rfb::Server::frameRate/2;\n  else\n    return frameTimer.getRemainingMs();\n}\n\n// writeUpdate() is called on a regular interval in order to see what\n// updates are pending and propagates them to the update tracker for\n// each client. It uses the ComparingUpdateTracker's compare() method\n// to filter out areas of the screen which haven't actually changed. It\n// also checks the state of the (server-side) rendered cursor, if\n// necessary rendering it again with the correct background.\n\nvoid VNCServerST::writeUpdate()\n{\n  UpdateInfo ui;\n  core::Region toCheck;\n\n  std::list<VNCSConnectionST*>::iterator ci;\n\n  assert(blockCounter == 0);\n  assert(desktopStarted);\n  assert(comparer != nullptr);\n\n  comparer->getUpdateInfo(&ui, pb->getRect());\n  toCheck = ui.changed.union_(ui.copied);\n\n  if (needRenderedCursor()) {\n    core::Rect clippedCursorRect = core::Rect(0, 0, cursor->width(), cursor->height())\n                                   .translate(cursorPos.subtract(cursor->hotspot()))\n                                   .intersect(pb->getRect());\n\n    if (!toCheck.intersect(clippedCursorRect).is_empty())\n      renderedCursorInvalid = true;\n  }\n\n  pb->grabRegion(toCheck);\n\n  if (getComparerState())\n    comparer->enable();\n  else\n    comparer->disable();\n\n  if (comparer->compare())\n    comparer->getUpdateInfo(&ui, pb->getRect());\n\n  comparer->clear();\n\n  for (ci = clients.begin(); ci != clients.end(); ++ci) {\n    (*ci)->add_copied(ui.copied, ui.copy_delta);\n    (*ci)->add_changed(ui.changed);\n    (*ci)->writeFramebufferUpdateOrClose();\n  }\n}\n\n// checkUpdate() is called by clients to see if it is safe to read from\n// the framebuffer at this time.\n\ncore::Region VNCServerST::getPendingRegion()\n{\n  UpdateInfo ui;\n\n  // Block clients as the frame buffer cannot be safely accessed\n  if (blockCounter > 0)\n    return pb->getRect();\n\n  assert(comparer != nullptr);\n\n  // Block client from updating if there are pending updates\n  if (comparer->is_empty())\n    return {};\n\n  comparer->getUpdateInfo(&ui, pb->getRect());\n\n  return ui.changed.union_(ui.copied);\n}\n\nconst RenderedCursor* VNCServerST::getRenderedCursor()\n{\n  if (renderedCursorInvalid) {\n    renderedCursor.update(pb, cursor, cursorPos);\n    renderedCursorInvalid = false;\n  }\n\n  return &renderedCursor;\n}\n\nbool VNCServerST::getComparerState()\n{\n  if (rfb::Server::compareFB == 0)\n    return false;\n  if (rfb::Server::compareFB != 2)\n    return true;\n\n  std::list<VNCSConnectionST*>::iterator ci;\n  for (ci = clients.begin(); ci != clients.end(); ++ci) {\n    if ((*ci)->getComparerState())\n      return true;\n  }\n  return false;\n}\n"
  },
  {
    "path": "common/rfb/VNCServerST.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- VNCServerST.h\n\n// Single-threaded VNCServer implementation\n\n#ifndef __RFB_VNCSERVERST_H__\n#define __RFB_VNCSERVERST_H__\n\n#include <sys/time.h>\n\n#include <core/Timer.h>\n\n#include <rfb/VNCServer.h>\n#include <rfb/Blacklist.h>\n#include <rfb/Cursor.h>\n#include <rfb/ScreenSet.h>\n\nnamespace rfb {\n\n  class VNCSConnectionST;\n  class ComparingUpdateTracker;\n  class ListConnInfo;\n  class PixelBuffer;\n  class KeyRemapper;\n  class SDesktop;\n\n  class VNCServerST : public VNCServer,\n                      public core::Timer::Callback {\n  public:\n    // -=- Constructors\n\n    //   Create a server exporting the supplied desktop.\n    VNCServerST(const char* name_, SDesktop* desktop_);\n    virtual ~VNCServerST();\n\n\n    // Methods overridden from VNCServer\n\n    // addSocket\n    //   Causes the server to allocate an RFB-protocol management\n    //   structure for the socket & initialise it.\n    bool addSocket(network::Socket* sock, bool outgoing=false,\n                   AccessRights ar=AccessDefault) override;\n\n    // removeSocket\n    //   Clean up any resources associated with the Socket\n    void removeSocket(network::Socket* sock) override;\n\n    // getSockets() gets a list of sockets.  This can be used to generate an\n    // fd_set for calling select().\n    void getSockets(std::list<network::Socket*>* sockets) override;\n\n    // processSocketReadEvent\n    //   Read more RFB data from the Socket.  If an error occurs during\n    //   processing then shutdown() is called on the Socket, causing\n    //   removeSocket() to be called by the caller at a later time.\n    void processSocketReadEvent(network::Socket* sock) override;\n\n    // processSocketWriteEvent\n    //   Flush pending data from the Socket on to the network.\n    void processSocketWriteEvent(network::Socket* sock) override;\n\n    void blockUpdates() override;\n    void unblockUpdates() override;\n    uint64_t getMsc() override;\n    void queueMsc(uint64_t target) override;\n    void setPixelBuffer(PixelBuffer* pb, const ScreenSet& layout) override;\n    void setPixelBuffer(PixelBuffer* pb) override;\n    void setScreenLayout(const ScreenSet& layout) override;\n    const PixelBuffer* getPixelBuffer() const override { return pb; }\n\n    void requestClipboard() override;\n    void announceClipboard(bool available) override;\n    void sendClipboardData(const char* data) override;\n\n    void approveConnection(network::Socket* sock, bool accept,\n                           const char* reason) override;\n    void closeClients(const char* reason) override {closeClients(reason, nullptr);}\n    SConnection* getConnection(network::Socket* sock) override;\n\n    void add_changed(const core::Region& region) override;\n    void add_copied(const core::Region& dest,\n                    const core::Point& delta) override;\n    void setCursor(int width, int height, const core::Point& hotspot,\n                   const uint8_t* data) override;\n    void setCursorPos(const core::Point& p, bool warped) override;\n    void setName(const char* name_) override;\n    void setLEDState(unsigned state) override;\n\n    void bell() override;\n\n    // VNCServerST-only methods\n\n    // Methods to get the currently set server state\n\n    const ScreenSet& getScreenLayout() const { return screenLayout; }\n    const Cursor* getCursor() const { return cursor; }\n    const core::Point& getCursorPos() const { return cursorPos; }\n    const char* getName() const { return name.c_str(); }\n    unsigned getLEDState() const { return ledState; }\n    bool isDesktopReady() const { return desktopStarted; }\n\n    // Event handlers\n    void keyEvent(uint32_t keysym, uint32_t keycode, bool down);\n    void pointerEvent(VNCSConnectionST* client,\n                      const core::Point& pos, uint16_t buttonMask);\n\n    void handleClipboardRequest(VNCSConnectionST* client);\n    void handleClipboardAnnounce(VNCSConnectionST* client, bool available);\n    void handleClipboardData(VNCSConnectionST* client, const char* data);\n\n    unsigned int setDesktopSize(VNCSConnectionST* requester,\n                                int fb_width, int fb_height,\n                                const ScreenSet& layout);\n\n    // closeClients() closes all RFB sessions, except the specified one (if\n    // any), and logs the specified reason for closure.\n    void closeClients(const char* reason, network::Socket* sock);\n\n    // queryConnection() does some basic checks and then passes on the\n    // request to the desktop.\n    void queryConnection(VNCSConnectionST* client, const char* userName);\n\n    // clientReady() is called by a VNCSConnectionST instance when the\n    // client has completed the handshake and is ready for normal\n    // communication.\n    void clientReady(VNCSConnectionST* client, bool shared);\n\n    // Estimated time until the next time new updates will be pushed\n    // to clients\n    int msToNextUpdate();\n\n    // Part of the framebuffer that has been modified but is not yet\n    // ready to be sent to clients\n    core::Region getPendingRegion();\n\n    // getRenderedCursor() returns an up to date version of the server\n    // side rendered cursor buffer\n    const RenderedCursor* getRenderedCursor();\n\n  protected:\n\n    // Timer callbacks\n    void handleTimeout(core::Timer* t) override;\n\n    // - Internal methods\n\n    void startDesktop();\n    void stopDesktop();\n    void checkDesktopReady();\n    void desktopReady();\n\n    // - Check how many of the clients are authenticated.\n    int authClientCount();\n\n    bool needRenderedCursor();\n    void startFrameClock();\n    void stopFrameClock();\n    void writeUpdate();\n\n    bool getComparerState();\n\n  protected:\n    Blacklist blacklist;\n\n    SDesktop* desktop;\n    bool desktopStarted;\n    bool desktopStarting;\n    int blockCounter;\n    PixelBuffer* pb;\n    ScreenSet screenLayout;\n    unsigned int ledState;\n\n    std::string name;\n\n    std::list<VNCSConnectionST*> clients;\n    VNCSConnectionST* pointerClient;\n    VNCSConnectionST* clipboardClient;\n    std::list<VNCSConnectionST*> clipboardRequestors;\n\n    time_t pointerClientTime;\n\n    ComparingUpdateTracker* comparer;\n\n    core::Point cursorPos;\n    Cursor* cursor;\n    RenderedCursor renderedCursor;\n    bool renderedCursorInvalid;\n\n    KeyRemapper* keyRemapper;\n\n    core::Timer idleTimer;\n    core::Timer disconnectTimer;\n    core::Timer connectTimer;\n\n    uint64_t msc, queuedMsc;\n    core::Timer frameTimer;\n  };\n\n};\n\n#endif\n\n"
  },
  {
    "path": "common/rfb/WinPasswdValidator.cxx",
    "content": "/* Copyright (C) 2005-2006 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <rfb/WinPasswdValidator.h>\n#include <windows.h>\n\nusing namespace rfb;\n\n// This method will only work for Windows NT, 2000, and XP (and possibly Vista)\nbool WinPasswdValidator::validateInternal(rfb::SConnection* /*sc*/,\n\t\t\t\t\t  const char* username,\n\t\t\t\t\t  const char* password,\n\t\t\t\t\t  std::string & /* msg */)\n{\n\tHANDLE handle;\n\n\tBOOL ret = LogonUser(username, \".\", password, LOGON32_LOGON_NETWORK,\n\t\t\t     LOGON32_PROVIDER_DEFAULT, &handle);\n\tif (ret != 0) {\n\t\tCloseHandle(handle);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n"
  },
  {
    "path": "common/rfb/WinPasswdValidator.h",
    "content": "/* Copyright (C) 2005-2006 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2010 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_WINPASSWDVALIDATOR_H__\n#define __RFB_WINPASSWDVALIDATOR_H__\n\n#include <string>\n#include <rfb/SSecurityPlain.h>\n\nnamespace rfb\n{\n  class WinPasswdValidator : public PasswordValidator {\n  public:\n    WinPasswdValidator() {};\n    virtual ~WinPasswdValidator() {};\n  protected:\n    bool validateInternal(SConnection *sc,\n                          const char *username,\n                          const char *password,\n                          std::string &msg) override;\n  };\n}\n\n#endif /* WINPASSWDVALIDATOR_H */\n"
  },
  {
    "path": "common/rfb/XF86keysym.h",
    "content": "/*\n * XFree86 vendor specific keysyms.\n *\n * The XFree86 keysym range is 0x10080001 - 0x1008ffff.\n *\n * The XF86 set of keysyms is a catch-all set of defines for keysyms found\n * on various multimedia keyboards. Originally specific to XFree86 they have\n * been been adopted over time and are considered a \"standard\" part of X\n * keysym definitions.\n * XFree86 never properly commented these keysyms, so we have done our\n * best to explain the semantic meaning of these keys.\n *\n * XFree86 has removed their mail archives of the period, that might have\n * shed more light on some of these definitions. Until/unless we resurrect\n * these archives, these are from memory and usage.\n */\n\n/*\n * ModeLock\n *\n * This one is old, and not really used any more since XKB offers this\n * functionality.\n */\n\n#define XF86XK_ModeLock              0x1008ff01  /* Mode Switch Lock */\n\n/* Backlight controls. */\n#define XF86XK_MonBrightnessUp       0x1008ff02  /* Monitor/panel brightness */\n#define XF86XK_MonBrightnessDown     0x1008ff03  /* Monitor/panel brightness */\n#define XF86XK_KbdLightOnOff         0x1008ff04  /* Keyboards may be lit     */\n#define XF86XK_KbdBrightnessUp       0x1008ff05  /* Keyboards may be lit     */\n#define XF86XK_KbdBrightnessDown     0x1008ff06  /* Keyboards may be lit     */\n#define XF86XK_MonBrightnessCycle    0x1008ff07  /* Monitor/panel brightness */\n\n/*\n * Keys found on some \"Internet\" keyboards.\n */\n#define XF86XK_Standby               0x1008ff10  /* System into standby mode   */\n#define XF86XK_AudioLowerVolume      0x1008ff11  /* Volume control down        */\n#define XF86XK_AudioMute             0x1008ff12  /* Mute sound from the system */\n#define XF86XK_AudioRaiseVolume      0x1008ff13  /* Volume control up          */\n#define XF86XK_AudioPlay             0x1008ff14  /* Start playing of audio >   */\n#define XF86XK_AudioStop             0x1008ff15  /* Stop playing audio         */\n#define XF86XK_AudioPrev             0x1008ff16  /* Previous track             */\n#define XF86XK_AudioNext             0x1008ff17  /* Next track                 */\n#define XF86XK_HomePage              0x1008ff18  /* Display user's home page   */\n#define XF86XK_Mail                  0x1008ff19  /* Invoke user's mail program */\n#define XF86XK_Start                 0x1008ff1a  /* Start application          */\n#define XF86XK_Search                0x1008ff1b  /* Search                     */\n#define XF86XK_AudioRecord           0x1008ff1c  /* Record audio application   */\n\n/* These are sometimes found on PDA's (e.g. Palm, PocketPC or elsewhere)   */\n#define XF86XK_Calculator            0x1008ff1d  /* Invoke calculator program  */\n#define XF86XK_Memo                  0x1008ff1e  /* Invoke Memo taking program */\n#define XF86XK_ToDoList              0x1008ff1f  /* Invoke To Do List program  */\n#define XF86XK_Calendar              0x1008ff20  /* Invoke Calendar program    */\n#define XF86XK_PowerDown             0x1008ff21  /* Deep sleep the system      */\n#define XF86XK_ContrastAdjust        0x1008ff22  /* Adjust screen contrast     */\n#define XF86XK_RockerUp              0x1008ff23  /* Rocker switches exist up   */\n#define XF86XK_RockerDown            0x1008ff24  /* and down                   */\n#define XF86XK_RockerEnter           0x1008ff25  /* and let you press them     */\n\n/* Some more \"Internet\" keyboard symbols */\n#define XF86XK_Back                  0x1008ff26  /* Like back on a browser     */\n#define XF86XK_Forward               0x1008ff27  /* Like forward on a browser  */\n#define XF86XK_Stop                  0x1008ff28  /* Stop current operation     */\n#define XF86XK_Refresh               0x1008ff29  /* Refresh the page           */\n#define XF86XK_PowerOff              0x1008ff2a  /* Power off system entirely  */\n#define XF86XK_WakeUp                0x1008ff2b  /* Wake up system from sleep  */\n#define XF86XK_Eject                 0x1008ff2c  /* Eject device (e.g. DVD)    */\n#define XF86XK_ScreenSaver           0x1008ff2d  /* Invoke screensaver         */\n#define XF86XK_WWW                   0x1008ff2e  /* Invoke web browser         */\n#define XF86XK_Sleep                 0x1008ff2f  /* Put system to sleep        */\n#define XF86XK_Favorites             0x1008ff30  /* Show favorite locations    */\n#define XF86XK_AudioPause            0x1008ff31  /* Pause audio playing        */\n#define XF86XK_AudioMedia            0x1008ff32  /* Launch media collection app */\n#define XF86XK_MyComputer            0x1008ff33  /* Display \"My Computer\" window */\n#define XF86XK_VendorHome            0x1008ff34  /* Display vendor home web site */\n#define XF86XK_LightBulb             0x1008ff35  /* Light bulb keys exist       */\n#define XF86XK_Shop                  0x1008ff36  /* Display shopping web site   */\n#define XF86XK_History               0x1008ff37  /* Show history of web surfing */\n#define XF86XK_OpenURL               0x1008ff38  /* Open selected URL           */\n#define XF86XK_AddFavorite           0x1008ff39  /* Add URL to favorites list   */\n#define XF86XK_HotLinks              0x1008ff3a  /* Show \"hot\" links            */\n#define XF86XK_BrightnessAdjust      0x1008ff3b  /* Invoke brightness adj. UI   */\n#define XF86XK_Finance               0x1008ff3c  /* Display financial site      */\n#define XF86XK_Community             0x1008ff3d  /* Display user's community    */\n#define XF86XK_AudioRewind           0x1008ff3e  /* \"rewind\" audio track        */\n#define XF86XK_BackForward           0x1008ff3f  /* ??? */\n#define XF86XK_Launch0               0x1008ff40  /* Launch Application          */\n#define XF86XK_Launch1               0x1008ff41  /* Launch Application          */\n#define XF86XK_Launch2               0x1008ff42  /* Launch Application          */\n#define XF86XK_Launch3               0x1008ff43  /* Launch Application          */\n#define XF86XK_Launch4               0x1008ff44  /* Launch Application          */\n#define XF86XK_Launch5               0x1008ff45  /* Launch Application          */\n#define XF86XK_Launch6               0x1008ff46  /* Launch Application          */\n#define XF86XK_Launch7               0x1008ff47  /* Launch Application          */\n#define XF86XK_Launch8               0x1008ff48  /* Launch Application          */\n#define XF86XK_Launch9               0x1008ff49  /* Launch Application          */\n#define XF86XK_LaunchA               0x1008ff4a  /* Launch Application          */\n#define XF86XK_LaunchB               0x1008ff4b  /* Launch Application          */\n#define XF86XK_LaunchC               0x1008ff4c  /* Launch Application          */\n#define XF86XK_LaunchD               0x1008ff4d  /* Launch Application          */\n#define XF86XK_LaunchE               0x1008ff4e  /* Launch Application          */\n#define XF86XK_LaunchF               0x1008ff4f  /* Launch Application          */\n\n#define XF86XK_ApplicationLeft       0x1008ff50  /* switch to application, left */\n#define XF86XK_ApplicationRight      0x1008ff51  /* switch to application, right*/\n#define XF86XK_Book                  0x1008ff52  /* Launch bookreader           */\n#define XF86XK_CD                    0x1008ff53  /* Launch CD/DVD player        */\n#define XF86XK_Calculater            0x1008ff54  /* Launch Calculater           */\n#define XF86XK_Clear                 0x1008ff55  /* Clear window, screen        */\n#define XF86XK_Close                 0x1008ff56  /* Close window                */\n#define XF86XK_Copy                  0x1008ff57  /* Copy selection              */\n#define XF86XK_Cut                   0x1008ff58  /* Cut selection               */\n#define XF86XK_Display               0x1008ff59  /* Output switch key           */\n#define XF86XK_DOS                   0x1008ff5a  /* Launch DOS (emulation)      */\n#define XF86XK_Documents             0x1008ff5b  /* Open documents window       */\n#define XF86XK_Excel                 0x1008ff5c  /* Launch spread sheet         */\n#define XF86XK_Explorer              0x1008ff5d  /* Launch file explorer        */\n#define XF86XK_Game                  0x1008ff5e  /* Launch game                 */\n#define XF86XK_Go                    0x1008ff5f  /* Go to URL                   */\n#define XF86XK_iTouch                0x1008ff60  /* Logitech iTouch- don't use  */\n#define XF86XK_LogOff                0x1008ff61  /* Log off system              */\n#define XF86XK_Market                0x1008ff62  /* ??                          */\n#define XF86XK_Meeting               0x1008ff63  /* enter meeting in calendar   */\n#define XF86XK_MenuKB                0x1008ff65  /* distinguish keyboard from PB */\n#define XF86XK_MenuPB                0x1008ff66  /* distinguish PB from keyboard */\n#define XF86XK_MySites               0x1008ff67  /* Favourites                  */\n#define XF86XK_New                   0x1008ff68  /* New (folder, document...    */\n#define XF86XK_News                  0x1008ff69  /* News                        */\n#define XF86XK_OfficeHome            0x1008ff6a  /* Office home (old Staroffice)*/\n#define XF86XK_Open                  0x1008ff6b  /* Open                        */\n#define XF86XK_Option                0x1008ff6c  /* ?? */\n#define XF86XK_Paste                 0x1008ff6d  /* Paste                       */\n#define XF86XK_Phone                 0x1008ff6e  /* Launch phone; dial number   */\n#define XF86XK_Q                     0x1008ff70  /* Compaq's Q - don't use      */\n#define XF86XK_Reply                 0x1008ff72  /* Reply e.g., mail            */\n#define XF86XK_Reload                0x1008ff73  /* Reload web page, file, etc. */\n#define XF86XK_RotateWindows         0x1008ff74  /* Rotate windows e.g. xrandr  */\n#define XF86XK_RotationPB            0x1008ff75  /* don't use                   */\n#define XF86XK_RotationKB            0x1008ff76  /* don't use                   */\n#define XF86XK_Save                  0x1008ff77  /* Save (file, document, state */\n#define XF86XK_ScrollUp              0x1008ff78  /* Scroll window/contents up   */\n#define XF86XK_ScrollDown            0x1008ff79  /* Scrool window/contentd down */\n#define XF86XK_ScrollClick           0x1008ff7a  /* Use XKB mousekeys instead   */\n#define XF86XK_Send                  0x1008ff7b  /* Send mail, file, object     */\n#define XF86XK_Spell                 0x1008ff7c  /* Spell checker               */\n#define XF86XK_SplitScreen           0x1008ff7d  /* Split window or screen      */\n#define XF86XK_Support               0x1008ff7e  /* Get support (??)            */\n#define XF86XK_TaskPane              0x1008ff7f  /* Show tasks */\n#define XF86XK_Terminal              0x1008ff80  /* Launch terminal emulator    */\n#define XF86XK_Tools                 0x1008ff81  /* toolbox of desktop/app.     */\n#define XF86XK_Travel                0x1008ff82  /* ?? */\n#define XF86XK_UserPB                0x1008ff84  /* ?? */\n#define XF86XK_User1KB               0x1008ff85  /* ?? */\n#define XF86XK_User2KB               0x1008ff86  /* ?? */\n#define XF86XK_Video                 0x1008ff87  /* Launch video player       */\n#define XF86XK_WheelButton           0x1008ff88  /* button from a mouse wheel */\n#define XF86XK_Word                  0x1008ff89  /* Launch word processor     */\n#define XF86XK_Xfer                  0x1008ff8a\n#define XF86XK_ZoomIn                0x1008ff8b  /* zoom in view, map, etc.   */\n#define XF86XK_ZoomOut               0x1008ff8c  /* zoom out view, map, etc.  */\n\n#define XF86XK_Away                  0x1008ff8d  /* mark yourself as away     */\n#define XF86XK_Messenger             0x1008ff8e  /* as in instant messaging   */\n#define XF86XK_WebCam                0x1008ff8f  /* Launch web camera app.    */\n#define XF86XK_MailForward           0x1008ff90  /* Forward in mail           */\n#define XF86XK_Pictures              0x1008ff91  /* Show pictures             */\n#define XF86XK_Music                 0x1008ff92  /* Launch music application  */\n\n#define XF86XK_Battery               0x1008ff93  /* Display battery information */\n#define XF86XK_Bluetooth             0x1008ff94  /* Enable/disable Bluetooth    */\n#define XF86XK_WLAN                  0x1008ff95  /* Enable/disable WLAN         */\n#define XF86XK_UWB                   0x1008ff96  /* Enable/disable UWB\t    */\n\n#define XF86XK_AudioForward          0x1008ff97  /* fast-forward audio track    */\n#define XF86XK_AudioRepeat           0x1008ff98  /* toggle repeat mode          */\n#define XF86XK_AudioRandomPlay       0x1008ff99  /* toggle shuffle mode         */\n#define XF86XK_Subtitle              0x1008ff9a  /* cycle through subtitle      */\n#define XF86XK_AudioCycleTrack       0x1008ff9b  /* cycle through audio tracks  */\n#define XF86XK_CycleAngle            0x1008ff9c  /* cycle through angles        */\n#define XF86XK_FrameBack             0x1008ff9d  /* video: go one frame back    */\n#define XF86XK_FrameForward          0x1008ff9e  /* video: go one frame forward */\n#define XF86XK_Time                  0x1008ff9f  /* display, or shows an entry for time seeking */\n#define XF86XK_Select                0x1008ffa0  /* Select button on joypads and remotes */\n#define XF86XK_View                  0x1008ffa1  /* Show a view options/properties */\n#define XF86XK_TopMenu               0x1008ffa2  /* Go to a top-level menu in a video */\n\n#define XF86XK_Red                   0x1008ffa3  /* Red button                  */\n#define XF86XK_Green                 0x1008ffa4  /* Green button                */\n#define XF86XK_Yellow                0x1008ffa5  /* Yellow button               */\n#define XF86XK_Blue                  0x1008ffa6  /* Blue button                 */\n\n#define XF86XK_Suspend               0x1008ffa7  /* Sleep to RAM                */\n#define XF86XK_Hibernate             0x1008ffa8  /* Sleep to disk               */\n#define XF86XK_TouchpadToggle        0x1008ffa9  /* Toggle between touchpad/trackstick */\n#define XF86XK_TouchpadOn            0x1008ffb0  /* The touchpad got switched on */\n#define XF86XK_TouchpadOff           0x1008ffb1  /* The touchpad got switched off */\n\n#define XF86XK_AudioMicMute          0x1008ffb2  /* Mute the Mic from the system */\n\n#define XF86XK_Keyboard              0x1008ffb3  /* User defined keyboard related action */\n\n#define XF86XK_WWAN                  0x1008ffb4  /* Toggle WWAN (LTE, UMTS, etc.) radio */\n#define XF86XK_RFKill                0x1008ffb5  /* Toggle radios on/off */\n\n#define XF86XK_AudioPreset           0x1008ffb6  /* Select equalizer preset, e.g. theatre-mode */\n\n#define XF86XK_RotationLockToggle    0x1008ffb7  /* Toggle screen rotation lock on/off */\n\n#define XF86XK_FullScreen            0x1008ffb8  /* Toggle fullscreen */\n\n/* Keys for special action keys (hot keys) */\n/* Virtual terminals on some operating systems */\n#define XF86XK_Switch_VT_1           0x1008fe01\n#define XF86XK_Switch_VT_2           0x1008fe02\n#define XF86XK_Switch_VT_3           0x1008fe03\n#define XF86XK_Switch_VT_4           0x1008fe04\n#define XF86XK_Switch_VT_5           0x1008fe05\n#define XF86XK_Switch_VT_6           0x1008fe06\n#define XF86XK_Switch_VT_7           0x1008fe07\n#define XF86XK_Switch_VT_8           0x1008fe08\n#define XF86XK_Switch_VT_9           0x1008fe09\n#define XF86XK_Switch_VT_10          0x1008fe0a\n#define XF86XK_Switch_VT_11          0x1008fe0b\n#define XF86XK_Switch_VT_12          0x1008fe0c\n\n#define XF86XK_Ungrab                0x1008fe20  /* force ungrab               */\n#define XF86XK_ClearGrab             0x1008fe21  /* kill application with grab */\n#define XF86XK_Next_VMode            0x1008fe22  /* next video mode available  */\n#define XF86XK_Prev_VMode            0x1008fe23  /* prev. video mode available */\n#define XF86XK_LogWindowTree         0x1008fe24  /* print window tree to log   */\n#define XF86XK_LogGrabInfo           0x1008fe25  /* print all active grabs to log */\n\n\n/*\n * Reserved range for evdev symbols: 0x10081000-0x10081FFF\n *\n * Key syms within this range must match the Linux kernel\n * input-event-codes.h file in the format:\n *     XF86XK_CamelCaseKernelName\t_EVDEVK(kernel value)\n * For example, the kernel\n *   #define KEY_MACRO_RECORD_START\t0x2b0\n * effectively ends up as:\n *   #define XF86XK_MacroRecordStart\t0x100812b0\n *\n * For historical reasons, some keysyms within the reserved range will be\n * missing, most notably all \"normal\" keys that are mapped through default\n * XKB layouts (e.g. KEY_Q).\n *\n * CamelCasing is done with a human control as last authority, e.g. see VOD\n * instead of Vod for the Video on Demand key.\n *\n * The format for #defines is strict:\n *\n * #define XF86XK_FOO<tab...>_EVDEVK(0xABC)<tab><tab> |* kver KEY_FOO *|\n *\n * Where\n * - alignment by tabs\n * - the _EVDEVK macro must be used\n * - the hex code must be in uppercase hex\n * - the kernel version (kver) is in the form v5.10\n * - kver and key name are within a slash-star comment (a pipe is used in\n *   this example for technical reasons)\n * These #defines are parsed by scripts. Do not stray from the given format.\n *\n * Where the evdev keycode is mapped to a different symbol, please add a\n * comment line starting with Use: but otherwise the same format, e.g.\n *  Use: XF86XK_RotationLockToggle\t_EVDEVK(0x231)\t\t   v4.16 KEY_ROTATE_LOCK_TOGGLE\n *\n */\n#define _EVDEVK(_v) (0x10081000 + _v)\n/* Use: XF86XK_Eject                    _EVDEVK(0x0a2)             KEY_EJECTCLOSECD */\n/* Use: XF86XK_New                      _EVDEVK(0x0b5)     v2.6.14 KEY_NEW */\n/* Use: XK_Redo                         _EVDEVK(0x0b6)     v2.6.14 KEY_REDO */\n/* KEY_DASHBOARD has been mapped to LaunchB in xkeyboard-config since 2011 */\n/* Use: XF86XK_LaunchB                  _EVDEVK(0x0cc)     v2.6.28 KEY_DASHBOARD */\n/* Use: XF86XK_Display                  _EVDEVK(0x0e3)     v2.6.12 KEY_SWITCHVIDEOMODE */\n/* Use: XF86XK_KbdLightOnOff            _EVDEVK(0x0e4)     v2.6.12 KEY_KBDILLUMTOGGLE */\n/* Use: XF86XK_KbdBrightnessDown        _EVDEVK(0x0e5)     v2.6.12 KEY_KBDILLUMDOWN */\n/* Use: XF86XK_KbdBrightnessUp          _EVDEVK(0x0e6)     v2.6.12 KEY_KBDILLUMUP */\n/* Use: XF86XK_Send                     _EVDEVK(0x0e7)     v2.6.14 KEY_SEND */\n/* Use: XF86XK_Reply                    _EVDEVK(0x0e8)     v2.6.14 KEY_REPLY */\n/* Use: XF86XK_MailForward              _EVDEVK(0x0e9)     v2.6.14 KEY_FORWARDMAIL */\n/* Use: XF86XK_Save                     _EVDEVK(0x0ea)     v2.6.14 KEY_SAVE */\n/* Use: XF86XK_Documents                _EVDEVK(0x0eb)     v2.6.14 KEY_DOCUMENTS */\n/* Use: XF86XK_Battery                  _EVDEVK(0x0ec)     v2.6.17 KEY_BATTERY */\n/* Use: XF86XK_Bluetooth                _EVDEVK(0x0ed)     v2.6.19 KEY_BLUETOOTH */\n/* Use: XF86XK_WLAN                     _EVDEVK(0x0ee)     v2.6.19 KEY_WLAN */\n/* Use: XF86XK_UWB                      _EVDEVK(0x0ef)     v2.6.24 KEY_UWB */\n/* Use: XF86XK_Next_VMode               _EVDEVK(0x0f1)     v2.6.23 KEY_VIDEO_NEXT */\n/* Use: XF86XK_Prev_VMode               _EVDEVK(0x0f2)     v2.6.23 KEY_VIDEO_PREV */\n/* Use: XF86XK_MonBrightnessCycle       _EVDEVK(0x0f3)     v2.6.23 KEY_BRIGHTNESS_CYCLE */\n#define XF86XK_BrightnessAuto           _EVDEVK(0x0f4)  /* v3.16   KEY_BRIGHTNESS_AUTO */\n#define XF86XK_DisplayOff               _EVDEVK(0x0f5)  /* v2.6.23 KEY_DISPLAY_OFF */\n/* Use: XF86XK_WWAN                     _EVDEVK(0x0f6)     v3.13   KEY_WWAN */\n/* Use: XF86XK_RFKill                   _EVDEVK(0x0f7)     v2.6.33 KEY_RFKILL */\n/* Use: XF86XK_AudioMicMute             _EVDEVK(0x0f8)     v3.1    KEY_MICMUTE */\n#define XF86XK_Info                     _EVDEVK(0x166)  /*         KEY_INFO */\n/* Use: XF86XK_CycleAngle               _EVDEVK(0x173)             KEY_ANGLE */\n/* Use: XF86XK_FullScreen               _EVDEVK(0x174)     v5.1    KEY_FULL_SCREEN */\n#define XF86XK_AspectRatio              _EVDEVK(0x177)  /* v5.1    KEY_ASPECT_RATIO */\n#define XF86XK_DVD                      _EVDEVK(0x185)  /*         KEY_DVD */\n#define XF86XK_Audio                    _EVDEVK(0x188)  /*         KEY_AUDIO */\n/* Use: XF86XK_Video                    _EVDEVK(0x189)             KEY_VIDEO */\n/* Use: XF86XK_Calendar                 _EVDEVK(0x18d)             KEY_CALENDAR */\n#define XF86XK_ChannelUp                _EVDEVK(0x192)  /*         KEY_CHANNELUP */\n#define XF86XK_ChannelDown              _EVDEVK(0x193)  /*         KEY_CHANNELDOWN */\n/* Use: XF86XK_AudioRandomPlay          _EVDEVK(0x19a)             KEY_SHUFFLE */\n#define XF86XK_Break                    _EVDEVK(0x19b)  /*         KEY_BREAK */\n#define XF86XK_VideoPhone               _EVDEVK(0x1a0)  /* v2.6.20 KEY_VIDEOPHONE */\n/* Use: XF86XK_Game                     _EVDEVK(0x1a1)     v2.6.20 KEY_GAMES */\n/* Use: XF86XK_ZoomIn                   _EVDEVK(0x1a2)     v2.6.20 KEY_ZOOMIN */\n/* Use: XF86XK_ZoomOut                  _EVDEVK(0x1a3)     v2.6.20 KEY_ZOOMOUT */\n#define XF86XK_ZoomReset                _EVDEVK(0x1a4)  /* v2.6.20 KEY_ZOOMRESET */\n/* Use: XF86XK_Word                     _EVDEVK(0x1a5)     v2.6.20 KEY_WORDPROCESSOR */\n#define XF86XK_Editor                   _EVDEVK(0x1a6)  /* v2.6.20 KEY_EDITOR */\n/* Use: XF86XK_Excel                    _EVDEVK(0x1a7)     v2.6.20 KEY_SPREADSHEET */\n#define XF86XK_GraphicsEditor           _EVDEVK(0x1a8)  /* v2.6.20 KEY_GRAPHICSEDITOR */\n#define XF86XK_Presentation             _EVDEVK(0x1a9)  /* v2.6.20 KEY_PRESENTATION */\n#define XF86XK_Database                 _EVDEVK(0x1aa)  /* v2.6.20 KEY_DATABASE */\n/* Use: XF86XK_News                     _EVDEVK(0x1ab)     v2.6.20 KEY_NEWS */\n#define XF86XK_Voicemail                _EVDEVK(0x1ac)  /* v2.6.20 KEY_VOICEMAIL */\n#define XF86XK_Addressbook              _EVDEVK(0x1ad)  /* v2.6.20 KEY_ADDRESSBOOK */\n/* Use: XF86XK_Messenger                _EVDEVK(0x1ae)     v2.6.20 KEY_MESSENGER */\n#define XF86XK_DisplayToggle            _EVDEVK(0x1af)  /* v2.6.20 KEY_DISPLAYTOGGLE */\n#define XF86XK_SpellCheck               _EVDEVK(0x1b0)  /* v2.6.24 KEY_SPELLCHECK */\n/* Use: XF86XK_LogOff                   _EVDEVK(0x1b1)     v2.6.24 KEY_LOGOFF */\n/* Use: XK_dollar                       _EVDEVK(0x1b2)     v2.6.24 KEY_DOLLAR */\n/* Use: XK_EuroSign                     _EVDEVK(0x1b3)     v2.6.24 KEY_EURO */\n/* Use: XF86XK_FrameBack                _EVDEVK(0x1b4)     v2.6.24 KEY_FRAMEBACK */\n/* Use: XF86XK_FrameForward             _EVDEVK(0x1b5)     v2.6.24 KEY_FRAMEFORWARD */\n#define XF86XK_ContextMenu              _EVDEVK(0x1b6)  /* v2.6.24 KEY_CONTEXT_MENU */\n#define XF86XK_MediaRepeat              _EVDEVK(0x1b7)  /* v2.6.26 KEY_MEDIA_REPEAT */\n#define XF86XK_10ChannelsUp             _EVDEVK(0x1b8)  /* v2.6.38 KEY_10CHANNELSUP */\n#define XF86XK_10ChannelsDown           _EVDEVK(0x1b9)  /* v2.6.38 KEY_10CHANNELSDOWN */\n#define XF86XK_Images                   _EVDEVK(0x1ba)  /* v2.6.39 KEY_IMAGES */\n#define XF86XK_NotificationCenter       _EVDEVK(0x1bc)  /* v5.10   KEY_NOTIFICATION_CENTER */\n#define XF86XK_PickupPhone              _EVDEVK(0x1bd)  /* v5.10   KEY_PICKUP_PHONE */\n#define XF86XK_HangupPhone              _EVDEVK(0x1be)  /* v5.10   KEY_HANGUP_PHONE */\n#define XF86XK_Fn                       _EVDEVK(0x1d0)  /*         KEY_FN */\n#define XF86XK_Fn_Esc                   _EVDEVK(0x1d1)  /*         KEY_FN_ESC */\n#define XF86XK_FnRightShift             _EVDEVK(0x1e5)  /* v5.10   KEY_FN_RIGHT_SHIFT */\n/* Use: XK_braille_dot_1                _EVDEVK(0x1f1)     v2.6.17 KEY_BRL_DOT1 */\n/* Use: XK_braille_dot_2                _EVDEVK(0x1f2)     v2.6.17 KEY_BRL_DOT2 */\n/* Use: XK_braille_dot_3                _EVDEVK(0x1f3)     v2.6.17 KEY_BRL_DOT3 */\n/* Use: XK_braille_dot_4                _EVDEVK(0x1f4)     v2.6.17 KEY_BRL_DOT4 */\n/* Use: XK_braille_dot_5                _EVDEVK(0x1f5)     v2.6.17 KEY_BRL_DOT5 */\n/* Use: XK_braille_dot_6                _EVDEVK(0x1f6)     v2.6.17 KEY_BRL_DOT6 */\n/* Use: XK_braille_dot_7                _EVDEVK(0x1f7)     v2.6.17 KEY_BRL_DOT7 */\n/* Use: XK_braille_dot_8                _EVDEVK(0x1f8)     v2.6.17 KEY_BRL_DOT8 */\n/* Use: XK_braille_dot_9                _EVDEVK(0x1f9)     v2.6.23 KEY_BRL_DOT9 */\n/* Use: XK_braille_dot_1                _EVDEVK(0x1fa)     v2.6.23 KEY_BRL_DOT10 */\n#define XF86XK_Numeric0                 _EVDEVK(0x200)  /* v2.6.28 KEY_NUMERIC_0 */\n#define XF86XK_Numeric1                 _EVDEVK(0x201)  /* v2.6.28 KEY_NUMERIC_1 */\n#define XF86XK_Numeric2                 _EVDEVK(0x202)  /* v2.6.28 KEY_NUMERIC_2 */\n#define XF86XK_Numeric3                 _EVDEVK(0x203)  /* v2.6.28 KEY_NUMERIC_3 */\n#define XF86XK_Numeric4                 _EVDEVK(0x204)  /* v2.6.28 KEY_NUMERIC_4 */\n#define XF86XK_Numeric5                 _EVDEVK(0x205)  /* v2.6.28 KEY_NUMERIC_5 */\n#define XF86XK_Numeric6                 _EVDEVK(0x206)  /* v2.6.28 KEY_NUMERIC_6 */\n#define XF86XK_Numeric7                 _EVDEVK(0x207)  /* v2.6.28 KEY_NUMERIC_7 */\n#define XF86XK_Numeric8                 _EVDEVK(0x208)  /* v2.6.28 KEY_NUMERIC_8 */\n#define XF86XK_Numeric9                 _EVDEVK(0x209)  /* v2.6.28 KEY_NUMERIC_9 */\n#define XF86XK_NumericStar              _EVDEVK(0x20a)  /* v2.6.28 KEY_NUMERIC_STAR */\n#define XF86XK_NumericPound             _EVDEVK(0x20b)  /* v2.6.28 KEY_NUMERIC_POUND */\n#define XF86XK_NumericA                 _EVDEVK(0x20c)  /* v4.1    KEY_NUMERIC_A */\n#define XF86XK_NumericB                 _EVDEVK(0x20d)  /* v4.1    KEY_NUMERIC_B */\n#define XF86XK_NumericC                 _EVDEVK(0x20e)  /* v4.1    KEY_NUMERIC_C */\n#define XF86XK_NumericD                 _EVDEVK(0x20f)  /* v4.1    KEY_NUMERIC_D */\n#define XF86XK_CameraFocus              _EVDEVK(0x210)  /* v2.6.33 KEY_CAMERA_FOCUS */\n#define XF86XK_WPSButton                _EVDEVK(0x211)  /* v2.6.34 KEY_WPS_BUTTON */\n/* Use: XF86XK_TouchpadToggle           _EVDEVK(0x212)     v2.6.37 KEY_TOUCHPAD_TOGGLE */\n/* Use: XF86XK_TouchpadOn               _EVDEVK(0x213)     v2.6.37 KEY_TOUCHPAD_ON */\n/* Use: XF86XK_TouchpadOff              _EVDEVK(0x214)     v2.6.37 KEY_TOUCHPAD_OFF */\n#define XF86XK_CameraZoomIn             _EVDEVK(0x215)  /* v2.6.39 KEY_CAMERA_ZOOMIN */\n#define XF86XK_CameraZoomOut            _EVDEVK(0x216)  /* v2.6.39 KEY_CAMERA_ZOOMOUT */\n#define XF86XK_CameraUp                 _EVDEVK(0x217)  /* v2.6.39 KEY_CAMERA_UP */\n#define XF86XK_CameraDown               _EVDEVK(0x218)  /* v2.6.39 KEY_CAMERA_DOWN */\n#define XF86XK_CameraLeft               _EVDEVK(0x219)  /* v2.6.39 KEY_CAMERA_LEFT */\n#define XF86XK_CameraRight              _EVDEVK(0x21a)  /* v2.6.39 KEY_CAMERA_RIGHT */\n#define XF86XK_AttendantOn              _EVDEVK(0x21b)  /* v3.10   KEY_ATTENDANT_ON */\n#define XF86XK_AttendantOff             _EVDEVK(0x21c)  /* v3.10   KEY_ATTENDANT_OFF */\n#define XF86XK_AttendantToggle          _EVDEVK(0x21d)  /* v3.10   KEY_ATTENDANT_TOGGLE */\n#define XF86XK_LightsToggle             _EVDEVK(0x21e)  /* v3.10   KEY_LIGHTS_TOGGLE */\n#define XF86XK_ALSToggle                _EVDEVK(0x230)  /* v3.13   KEY_ALS_TOGGLE */\n/* Use: XF86XK_RotationLockToggle       _EVDEVK(0x231)     v4.16   KEY_ROTATE_LOCK_TOGGLE */\n#define XF86XK_Buttonconfig             _EVDEVK(0x240)  /* v3.16   KEY_BUTTONCONFIG */\n#define XF86XK_Taskmanager              _EVDEVK(0x241)  /* v3.16   KEY_TASKMANAGER */\n#define XF86XK_Journal                  _EVDEVK(0x242)  /* v3.16   KEY_JOURNAL */\n#define XF86XK_ControlPanel             _EVDEVK(0x243)  /* v3.16   KEY_CONTROLPANEL */\n#define XF86XK_AppSelect                _EVDEVK(0x244)  /* v3.16   KEY_APPSELECT */\n#define XF86XK_Screensaver              _EVDEVK(0x245)  /* v3.16   KEY_SCREENSAVER */\n#define XF86XK_VoiceCommand             _EVDEVK(0x246)  /* v3.16   KEY_VOICECOMMAND */\n#define XF86XK_Assistant                _EVDEVK(0x247)  /* v4.13   KEY_ASSISTANT */\n/* Use: XK_ISO_Next_Group               _EVDEVK(0x248)     v5.2    KEY_KBD_LAYOUT_NEXT */\n#define XF86XK_EmojiPicker              _EVDEVK(0x249)  /* v5.13   KEY_EMOJI_PICKER */\n#define XF86XK_Dictate                  _EVDEVK(0x24a)  /* v5.17   KEY_DICTATE */\n#define XF86XK_CameraAccessEnable       _EVDEVK(0x24b)  /* v6.2    KEY_CAMERA_ACCESS_ENABLE */\n#define XF86XK_CameraAccessDisable      _EVDEVK(0x24c)  /* v6.2    KEY_CAMERA_ACCESS_DISABLE */\n#define XF86XK_CameraAccessToggle       _EVDEVK(0x24d)  /* v6.2    KEY_CAMERA_ACCESS_TOGGLE */\n#define XF86XK_BrightnessMin            _EVDEVK(0x250)  /* v3.16   KEY_BRIGHTNESS_MIN */\n#define XF86XK_BrightnessMax            _EVDEVK(0x251)  /* v3.16   KEY_BRIGHTNESS_MAX */\n#define XF86XK_KbdInputAssistPrev       _EVDEVK(0x260)  /* v3.18   KEY_KBDINPUTASSIST_PREV */\n#define XF86XK_KbdInputAssistNext       _EVDEVK(0x261)  /* v3.18   KEY_KBDINPUTASSIST_NEXT */\n#define XF86XK_KbdInputAssistPrevgroup  _EVDEVK(0x262)  /* v3.18   KEY_KBDINPUTASSIST_PREVGROUP */\n#define XF86XK_KbdInputAssistNextgroup  _EVDEVK(0x263)  /* v3.18   KEY_KBDINPUTASSIST_NEXTGROUP */\n#define XF86XK_KbdInputAssistAccept     _EVDEVK(0x264)  /* v3.18   KEY_KBDINPUTASSIST_ACCEPT */\n#define XF86XK_KbdInputAssistCancel     _EVDEVK(0x265)  /* v3.18   KEY_KBDINPUTASSIST_CANCEL */\n#define XF86XK_RightUp                  _EVDEVK(0x266)  /* v4.7    KEY_RIGHT_UP */\n#define XF86XK_RightDown                _EVDEVK(0x267)  /* v4.7    KEY_RIGHT_DOWN */\n#define XF86XK_LeftUp                   _EVDEVK(0x268)  /* v4.7    KEY_LEFT_UP */\n#define XF86XK_LeftDown                 _EVDEVK(0x269)  /* v4.7    KEY_LEFT_DOWN */\n#define XF86XK_RootMenu                 _EVDEVK(0x26a)  /* v4.7    KEY_ROOT_MENU */\n#define XF86XK_MediaTopMenu             _EVDEVK(0x26b)  /* v4.7    KEY_MEDIA_TOP_MENU */\n#define XF86XK_Numeric11                _EVDEVK(0x26c)  /* v4.7    KEY_NUMERIC_11 */\n#define XF86XK_Numeric12                _EVDEVK(0x26d)  /* v4.7    KEY_NUMERIC_12 */\n#define XF86XK_AudioDesc                _EVDEVK(0x26e)  /* v4.7    KEY_AUDIO_DESC */\n#define XF86XK_3DMode                   _EVDEVK(0x26f)  /* v4.7    KEY_3D_MODE */\n#define XF86XK_NextFavorite             _EVDEVK(0x270)  /* v4.7    KEY_NEXT_FAVORITE */\n#define XF86XK_StopRecord               _EVDEVK(0x271)  /* v4.7    KEY_STOP_RECORD */\n#define XF86XK_PauseRecord              _EVDEVK(0x272)  /* v4.7    KEY_PAUSE_RECORD */\n#define XF86XK_VOD                      _EVDEVK(0x273)  /* v4.7    KEY_VOD */\n#define XF86XK_Unmute                   _EVDEVK(0x274)  /* v4.7    KEY_UNMUTE */\n#define XF86XK_FastReverse              _EVDEVK(0x275)  /* v4.7    KEY_FASTREVERSE */\n#define XF86XK_SlowReverse              _EVDEVK(0x276)  /* v4.7    KEY_SLOWREVERSE */\n#define XF86XK_Data                     _EVDEVK(0x277)  /* v4.7    KEY_DATA */\n#define XF86XK_OnScreenKeyboard         _EVDEVK(0x278)  /* v4.12   KEY_ONSCREEN_KEYBOARD */\n#define XF86XK_PrivacyScreenToggle      _EVDEVK(0x279)  /* v5.5    KEY_PRIVACY_SCREEN_TOGGLE */\n#define XF86XK_SelectiveScreenshot      _EVDEVK(0x27a)  /* v5.6    KEY_SELECTIVE_SCREENSHOT */\n#define XF86XK_NextElement              _EVDEVK(0x27b)  /* v5.18   KEY_NEXT_ELEMENT */\n#define XF86XK_PreviousElement          _EVDEVK(0x27c)  /* v5.18   KEY_PREVIOUS_ELEMENT */\n#define XF86XK_AutopilotEngageToggle    _EVDEVK(0x27d)  /* v5.18   KEY_AUTOPILOT_ENGAGE_TOGGLE */\n#define XF86XK_MarkWaypoint             _EVDEVK(0x27e)  /* v5.18   KEY_MARK_WAYPOINT */\n#define XF86XK_Sos                      _EVDEVK(0x27f)  /* v5.18   KEY_SOS */\n#define XF86XK_NavChart                 _EVDEVK(0x280)  /* v5.18   KEY_NAV_CHART */\n#define XF86XK_FishingChart             _EVDEVK(0x281)  /* v5.18   KEY_FISHING_CHART */\n#define XF86XK_SingleRangeRadar         _EVDEVK(0x282)  /* v5.18   KEY_SINGLE_RANGE_RADAR */\n#define XF86XK_DualRangeRadar           _EVDEVK(0x283)  /* v5.18   KEY_DUAL_RANGE_RADAR */\n#define XF86XK_RadarOverlay             _EVDEVK(0x284)  /* v5.18   KEY_RADAR_OVERLAY */\n#define XF86XK_TraditionalSonar         _EVDEVK(0x285)  /* v5.18   KEY_TRADITIONAL_SONAR */\n#define XF86XK_ClearvuSonar             _EVDEVK(0x286)  /* v5.18   KEY_CLEARVU_SONAR */\n#define XF86XK_SidevuSonar              _EVDEVK(0x287)  /* v5.18   KEY_SIDEVU_SONAR */\n#define XF86XK_NavInfo                  _EVDEVK(0x288)  /* v5.18   KEY_NAV_INFO */\n/* Use: XF86XK_BrightnessAdjust         _EVDEVK(0x289)     v5.18   KEY_BRIGHTNESS_MENU */\n#define XF86XK_Macro1                   _EVDEVK(0x290)  /* v5.5    KEY_MACRO1 */\n#define XF86XK_Macro2                   _EVDEVK(0x291)  /* v5.5    KEY_MACRO2 */\n#define XF86XK_Macro3                   _EVDEVK(0x292)  /* v5.5    KEY_MACRO3 */\n#define XF86XK_Macro4                   _EVDEVK(0x293)  /* v5.5    KEY_MACRO4 */\n#define XF86XK_Macro5                   _EVDEVK(0x294)  /* v5.5    KEY_MACRO5 */\n#define XF86XK_Macro6                   _EVDEVK(0x295)  /* v5.5    KEY_MACRO6 */\n#define XF86XK_Macro7                   _EVDEVK(0x296)  /* v5.5    KEY_MACRO7 */\n#define XF86XK_Macro8                   _EVDEVK(0x297)  /* v5.5    KEY_MACRO8 */\n#define XF86XK_Macro9                   _EVDEVK(0x298)  /* v5.5    KEY_MACRO9 */\n#define XF86XK_Macro10                  _EVDEVK(0x299)  /* v5.5    KEY_MACRO10 */\n#define XF86XK_Macro11                  _EVDEVK(0x29a)  /* v5.5    KEY_MACRO11 */\n#define XF86XK_Macro12                  _EVDEVK(0x29b)  /* v5.5    KEY_MACRO12 */\n#define XF86XK_Macro13                  _EVDEVK(0x29c)  /* v5.5    KEY_MACRO13 */\n#define XF86XK_Macro14                  _EVDEVK(0x29d)  /* v5.5    KEY_MACRO14 */\n#define XF86XK_Macro15                  _EVDEVK(0x29e)  /* v5.5    KEY_MACRO15 */\n#define XF86XK_Macro16                  _EVDEVK(0x29f)  /* v5.5    KEY_MACRO16 */\n#define XF86XK_Macro17                  _EVDEVK(0x2a0)  /* v5.5    KEY_MACRO17 */\n#define XF86XK_Macro18                  _EVDEVK(0x2a1)  /* v5.5    KEY_MACRO18 */\n#define XF86XK_Macro19                  _EVDEVK(0x2a2)  /* v5.5    KEY_MACRO19 */\n#define XF86XK_Macro20                  _EVDEVK(0x2a3)  /* v5.5    KEY_MACRO20 */\n#define XF86XK_Macro21                  _EVDEVK(0x2a4)  /* v5.5    KEY_MACRO21 */\n#define XF86XK_Macro22                  _EVDEVK(0x2a5)  /* v5.5    KEY_MACRO22 */\n#define XF86XK_Macro23                  _EVDEVK(0x2a6)  /* v5.5    KEY_MACRO23 */\n#define XF86XK_Macro24                  _EVDEVK(0x2a7)  /* v5.5    KEY_MACRO24 */\n#define XF86XK_Macro25                  _EVDEVK(0x2a8)  /* v5.5    KEY_MACRO25 */\n#define XF86XK_Macro26                  _EVDEVK(0x2a9)  /* v5.5    KEY_MACRO26 */\n#define XF86XK_Macro27                  _EVDEVK(0x2aa)  /* v5.5    KEY_MACRO27 */\n#define XF86XK_Macro28                  _EVDEVK(0x2ab)  /* v5.5    KEY_MACRO28 */\n#define XF86XK_Macro29                  _EVDEVK(0x2ac)  /* v5.5    KEY_MACRO29 */\n#define XF86XK_Macro30                  _EVDEVK(0x2ad)  /* v5.5    KEY_MACRO30 */\n#define XF86XK_MacroRecordStart         _EVDEVK(0x2b0)  /* v5.5    KEY_MACRO_RECORD_START */\n#define XF86XK_MacroRecordStop          _EVDEVK(0x2b1)  /* v5.5    KEY_MACRO_RECORD_STOP */\n#define XF86XK_MacroPresetCycle         _EVDEVK(0x2b2)  /* v5.5    KEY_MACRO_PRESET_CYCLE */\n#define XF86XK_MacroPreset1             _EVDEVK(0x2b3)  /* v5.5    KEY_MACRO_PRESET1 */\n#define XF86XK_MacroPreset2             _EVDEVK(0x2b4)  /* v5.5    KEY_MACRO_PRESET2 */\n#define XF86XK_MacroPreset3             _EVDEVK(0x2b5)  /* v5.5    KEY_MACRO_PRESET3 */\n#define XF86XK_KbdLcdMenu1              _EVDEVK(0x2b8)  /* v5.5    KEY_KBD_LCD_MENU1 */\n#define XF86XK_KbdLcdMenu2              _EVDEVK(0x2b9)  /* v5.5    KEY_KBD_LCD_MENU2 */\n#define XF86XK_KbdLcdMenu3              _EVDEVK(0x2ba)  /* v5.5    KEY_KBD_LCD_MENU3 */\n#define XF86XK_KbdLcdMenu4              _EVDEVK(0x2bb)  /* v5.5    KEY_KBD_LCD_MENU4 */\n#define XF86XK_KbdLcdMenu5              _EVDEVK(0x2bc)  /* v5.5    KEY_KBD_LCD_MENU5 */\n#undef _EVDEVK\n"
  },
  {
    "path": "common/rfb/ZRLEDecoder.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <algorithm>\n\n#include <rdr/InStream.h>\n#include <rdr/MemInStream.h>\n#include <rdr/OutStream.h>\n\n#include <rfb/Exception.h>\n#include <rfb/ServerParams.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/ZRLEDecoder.h>\n\nusing namespace rfb;\n\nstatic inline uint32_t readOpaque24A(rdr::InStream* is)\n{\n  uint32_t r=0;\n  ((uint8_t*)&r)[0] = is->readU8();\n  ((uint8_t*)&r)[1] = is->readU8();\n  ((uint8_t*)&r)[2] = is->readU8();\n  return r;\n\n}\nstatic inline uint32_t readOpaque24B(rdr::InStream* is)\n{\n  uint32_t r=0;\n  ((uint8_t*)&r)[1] = is->readU8();\n  ((uint8_t*)&r)[2] = is->readU8();\n  ((uint8_t*)&r)[3] = is->readU8();\n  return r;\n}\n\ntemplate<class T>\nstatic inline T readPixel(rdr::ZlibInStream* zis)\n{\n  if (sizeof(T) == 1)\n    return zis->readOpaque8();\n  if (sizeof(T) == 2)\n    return zis->readOpaque16();\n  if (sizeof(T) == 4)\n    return zis->readOpaque32();\n}\n\nstatic inline void zlibHasData(rdr::ZlibInStream* zis, size_t length)\n{\n  if (!zis->hasData(length))\n    throw protocol_error(\"ZRLE decode error\");\n}\n\nZRLEDecoder::ZRLEDecoder() : Decoder(DecoderOrdered)\n{\n}\n\nZRLEDecoder::~ZRLEDecoder()\n{\n}\n\nbool ZRLEDecoder::readRect(const core::Rect& /*r*/, rdr::InStream* is,\n                           const ServerParams& /*server*/,\n                           rdr::OutStream* os)\n{\n  uint32_t len;\n\n  if (!is->hasData(4))\n    return false;\n\n  is->setRestorePoint();\n\n  len = is->readU32();\n\n  if (!is->hasDataOrRestore(len))\n    return false;\n\n  is->clearRestorePoint();\n\n  os->writeU32(len);\n  os->copyBytes(is, len);\n\n  return true;\n}\n\nvoid ZRLEDecoder::decodeRect(const core::Rect& r, const uint8_t* buffer,\n                             size_t buflen, const ServerParams& server,\n                             ModifiablePixelBuffer* pb)\n{\n  rdr::MemInStream is(buffer, buflen);\n  const rfb::PixelFormat& pf = server.pf();\n  switch (pf.bpp) {\n  case 8:  zrleDecode<uint8_t>(r, &is, pf, pb); break;\n  case 16: zrleDecode<uint16_t>(r, &is, pf, pb); break;\n  case 32: zrleDecode<uint32_t>(r, &is, pf, pb); break;\n  }\n}\n\ntemplate<class T>\nvoid ZRLEDecoder::zrleDecode(const core::Rect& r, rdr::InStream* is,\n                             const PixelFormat& pf,\n                             ModifiablePixelBuffer* pb)\n{\n  int length = is->readU32();\n  zis.setUnderlying(is, length);\n  core::Rect t;\n  T buf[64 * 64];\n\n  Pixel maxPixel = pf.pixelFromRGB((uint16_t)-1, (uint16_t)-1, (uint16_t)-1);\n  bool fitsInLS3Bytes = maxPixel < (1<<24);\n  bool fitsInMS3Bytes = (maxPixel & 0xff) == 0;\n  bool isLowCPixel = (sizeof(T) == 4) && (pf.depth <= 24) &&\n                     ((fitsInLS3Bytes && pf.isLittleEndian()) ||\n                      (fitsInMS3Bytes && pf.isBigEndian()));\n  bool isHighCPixel = (sizeof(T) == 4) && (pf.depth <= 24) &&\n                      ((fitsInLS3Bytes && pf.isBigEndian()) ||\n                       (fitsInMS3Bytes && pf.isLittleEndian()));\n\n  for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) {\n\n    t.br.y = std::min(r.br.y, t.tl.y + 64);\n\n    for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) {\n\n      t.br.x = std::min(r.br.x, t.tl.x + 64);\n\n      zlibHasData(&zis, 1);\n      int mode = zis.readU8();\n      bool rle = mode & 128;\n      int palSize = mode & 127;\n      T palette[128];\n\n      if (isLowCPixel || isHighCPixel)\n        zlibHasData(&zis, 3 * palSize);\n      else\n        zlibHasData(&zis, sizeof(T) * palSize);\n\n      for (int i = 0; i < palSize; i++) {\n        if (isLowCPixel)\n          palette[i] = readOpaque24A(&zis);\n        else if (isHighCPixel)\n          palette[i] = readOpaque24B(&zis);\n        else\n          palette[i] = readPixel<T>(&zis);\n      }\n\n      if (palSize == 1) {\n        T pix = palette[0];\n        pb->fillRect(pf, t, &pix);\n        continue;\n      }\n\n      if (!rle) {\n        if (palSize == 0) {\n\n          // raw\n\n          if (isLowCPixel || isHighCPixel)\n            zlibHasData(&zis, 3 * t.area());\n          else\n            zlibHasData(&zis, sizeof(T) * t.area());\n\n          if (isLowCPixel || isHighCPixel) {\n            for (T* ptr = buf; ptr < buf+t.area(); ptr++) {\n              if (isLowCPixel)\n                *ptr = readOpaque24A(&zis);\n              else\n                *ptr = readOpaque24B(&zis);\n            }\n          } else {\n            zis.readBytes((uint8_t*)buf, t.area() * sizeof(T));\n          }\n\n        } else {\n\n          // packed pixels\n          int bppp = ((palSize > 16) ? 8 :\n                      ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1)));\n\n          T* ptr = buf;\n\n          for (int i = 0; i < t.height(); i++) {\n            T* eol = ptr + t.width();\n            uint8_t byte = 0;\n            uint8_t nbits = 0;\n\n            while (ptr < eol) {\n              if (nbits == 0) {\n                zlibHasData(&zis, 1);\n                byte = zis.readU8();\n                nbits = 8;\n              }\n              nbits -= bppp;\n              uint8_t index = (byte >> nbits) & ((1 << bppp) - 1) & 127;\n              *ptr++ = palette[index];\n            }\n          }\n        }\n\n      } else {\n\n        if (palSize == 0) {\n\n          // plain RLE\n\n          T* ptr = buf;\n          T* end = ptr + t.area();\n          while (ptr < end) {\n            T pix;\n            if (isLowCPixel || isHighCPixel)\n              zlibHasData(&zis, 3);\n            else\n              zlibHasData(&zis, sizeof(T));\n            if (isLowCPixel)\n              pix = readOpaque24A(&zis);\n            else if (isHighCPixel)\n              pix = readOpaque24B(&zis);\n            else\n              pix = readPixel<T>(&zis);\n            int len = 1;\n            int b;\n            do {\n              zlibHasData(&zis, 1);\n              b = zis.readU8();\n              len += b;\n            } while (b == 255);\n\n            if (end - ptr < len) {\n              throw protocol_error(\"ZRLE decode error\");\n            }\n\n            while (len-- > 0) *ptr++ = pix;\n\n          }\n        } else {\n\n          // palette RLE\n\n          T* ptr = buf;\n          T* end = ptr + t.area();\n          while (ptr < end) {\n            zlibHasData(&zis, 1);\n            int index = zis.readU8();\n            int len = 1;\n            if (index & 128) {\n              int b;\n              do {\n                zlibHasData(&zis, 1);\n                b = zis.readU8();\n                len += b;\n              } while (b == 255);\n\n              if (end - ptr < len) {\n                throw protocol_error(\"ZRLE decode error\");\n              }\n            }\n\n            index &= 127;\n\n            T pix = palette[index];\n\n            while (len-- > 0) *ptr++ = pix;\n          }\n        }\n      }\n\n      pb->imageRect(pf, t, buf);\n    }\n  }\n\n  zis.flushUnderlying();\n  zis.setUnderlying(nullptr, 0);\n}\n"
  },
  {
    "path": "common/rfb/ZRLEDecoder.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_ZRLEDECODER_H__\n#define __RFB_ZRLEDECODER_H__\n\n#include <rdr/ZlibInStream.h>\n#include <rfb/Decoder.h>\n\nnamespace rfb {\n\n  class PixelFormat;\n\n  class ZRLEDecoder : public Decoder {\n  public:\n    ZRLEDecoder();\n    virtual ~ZRLEDecoder();\n    bool readRect(const core::Rect& r, rdr::InStream* is,\n                  const ServerParams& server,\n                  rdr::OutStream* os) override;\n    void decodeRect(const core::Rect& r, const uint8_t* buffer,\n                    size_t buflen, const ServerParams& server,\n                    ModifiablePixelBuffer* pb) override;\n\n  private:\n    template<class T>\n    void zrleDecode(const core::Rect& r, rdr::InStream* is,\n                    const PixelFormat& pf, ModifiablePixelBuffer* pb);\n\n  private:\n    rdr::ZlibInStream zis;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/ZRLEEncoder.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Configuration.h>\n#include <core/LogWriter.h>\n\n#include <rdr/OutStream.h>\n#include <rfb/encodings.h>\n#include <rfb/Palette.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/SConnection.h>\n#include <rfb/ZRLEEncoder.h>\n\nusing namespace rfb;\n\nstatic core::LogWriter vlog(\"ZRLEEncoder\");\n\ncore::IntParameter zlibLevel(\"ZlibLevel\",\n                             \"[DEPRECATED] Zlib compression level\",\n                             -1, -1, -1);\n\nZRLEEncoder::ZRLEEncoder(SConnection* conn_)\n  : Encoder(conn_, encodingZRLE, EncoderPlain, 127),\n  zos(nullptr, 2), mos(129*1024)\n{\n  if (zlibLevel != -1) {\n    vlog.info(\"Warning: The ZlibLevel option is deprecated and is \"\n              \"ignored by the server. The compression level can be set \"\n              \"by the client instead.\");\n  }\n  zos.setUnderlying(&mos);\n}\n\nZRLEEncoder::~ZRLEEncoder()\n{\n  zos.setUnderlying(nullptr);\n}\n\nbool ZRLEEncoder::isSupported()\n{\n  return conn->client.supportsEncoding(encodingZRLE);\n}\n\nvoid ZRLEEncoder::setCompressLevel(int level)\n{\n  zos.setCompressionLevel(level);\n}\n\nvoid ZRLEEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)\n{\n  int x, y;\n  core::Rect tile;\n\n  rdr::OutStream* os;\n\n  // A bit of a special case\n  if (palette.size() == 1) {\n    Encoder::writeSolidRect(pb, palette);\n    return;\n  }\n\n  for (y = 0;y < pb->height();y += 64) {\n    tile.tl.y = y;\n    tile.br.y = y + 64;\n    if (tile.br.y > pb->height())\n      tile.br.y = pb->height();\n\n    for (x = 0;x < pb->width();x += 64) {\n      tile.tl.x = x;\n      tile.br.x = x + 64;\n      if (tile.br.x > pb->width())\n        tile.br.x = pb->width();\n\n      if (palette.size() == 0)\n        writeRawTile(tile, pb);\n      else if (palette.size() <= 16)\n        writePaletteTile(tile, pb, palette);\n      else\n        writePaletteRLETile(tile, pb, palette);\n    }\n  }\n\n  zos.flush();\n\n  os = conn->getOutStream();\n\n  os->writeU32(mos.length());\n  os->writeBytes(mos.data(), mos.length());\n\n  mos.clear();\n}\n\nvoid ZRLEEncoder::writeSolidRect(int width, int height,\n                                 const PixelFormat& pf,\n                                 const uint8_t* colour)\n{\n  int tiles;\n\n  rdr::OutStream* os;\n\n  tiles = ((width + 63)/64) * ((height + 63)/64);\n\n  while (tiles--) {\n    zos.writeU8(1);\n    writePixels(colour, pf, 1);\n  }\n\n  zos.flush();\n\n  os = conn->getOutStream();\n\n  os->writeU32(mos.length());\n  os->writeBytes(mos.data(), mos.length());\n\n  mos.clear();\n}\n\nvoid ZRLEEncoder::writePaletteTile(const core::Rect& tile,\n                                   const PixelBuffer* pb,\n                                   const Palette& palette)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  buffer = pb->getBuffer(tile, &stride);\n\n  switch (pb->getPF().bpp) {\n  case 32:\n    writePaletteTile(tile.width(), tile.height(),\n                     (uint32_t*)buffer, stride,\n                     pb->getPF(), palette);\n    break;\n  case 16:\n    writePaletteTile(tile.width(), tile.height(),\n                     (uint16_t*)buffer, stride,\n                     pb->getPF(), palette);\n    break;\n  default:\n    writePaletteTile(tile.width(), tile.height(),\n                     (uint8_t*)buffer, stride,\n                     pb->getPF(), palette);\n  }\n}\n\nvoid ZRLEEncoder::writePaletteRLETile(const core::Rect& tile,\n                                      const PixelBuffer* pb,\n                                      const Palette& palette)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  buffer = pb->getBuffer(tile, &stride);\n\n  switch (pb->getPF().bpp) {\n  case 32:\n    writePaletteRLETile(tile.width(), tile.height(),\n                        (uint32_t*)buffer, stride,\n                        pb->getPF(), palette);\n    break;\n  case 16:\n    writePaletteRLETile(tile.width(), tile.height(),\n                        (uint16_t*)buffer, stride,\n                        pb->getPF(), palette);\n    break;\n  default:\n    writePaletteRLETile(tile.width(), tile.height(),\n                        (uint8_t*)buffer, stride,\n                        pb->getPF(), palette);\n  }\n}\n\nvoid ZRLEEncoder::writeRawTile(const core::Rect& tile,\n                               const PixelBuffer* pb)\n{\n  const uint8_t* buffer;\n  int stride;\n\n  int w, h, stride_bytes;\n\n  buffer = pb->getBuffer(tile, &stride);\n\n  zos.writeU8(0); // Empty palette (i.e. raw pixels)\n\n  w = tile.width();\n  h = tile.height();\n  stride_bytes = stride * pb->getPF().bpp/8;\n  while (h--) {\n    writePixels(buffer, pb->getPF(), w);\n    buffer += stride_bytes;\n  }\n}\n\nvoid ZRLEEncoder::writePalette(const PixelFormat& pf, const Palette& palette)\n{\n  uint8_t buffer[256*4];\n  int i;\n\n  if (pf.bpp == 32) {\n    uint32_t* buf;\n    buf = (uint32_t*)buffer;\n    for (i = 0;i < palette.size();i++)\n      *buf++ = palette.getColour(i);\n  } else if (pf.bpp == 16) {\n    uint16_t* buf;\n    buf = (uint16_t*)buffer;\n    for (i = 0;i < palette.size();i++)\n      *buf++ = palette.getColour(i);\n  } else {\n    uint8_t* buf;\n    buf = (uint8_t*)buffer;\n    for (i = 0;i < palette.size();i++)\n      *buf++ = palette.getColour(i);\n  }\n\n  writePixels(buffer, pf, palette.size());\n}\n\nvoid ZRLEEncoder::writePixels(const uint8_t* buffer, const PixelFormat& pf,\n                              unsigned int count)\n{\n  Pixel maxPixel;\n  uint8_t pixBuf[4];\n\n  maxPixel = pf.pixelFromRGB((uint16_t)-1, (uint16_t)-1, (uint16_t)-1);\n  pf.bufferFromPixel(pixBuf, maxPixel);\n\n  if ((pf.bpp != 32) || ((pixBuf[0] != 0) && (pixBuf[3] != 0))) {\n    zos.writeBytes(buffer, count * (pf.bpp/8));\n    return;\n  }\n\n  if (pixBuf[0] == 0)\n    buffer++;\n\n  while (count--) {\n    zos.writeBytes(buffer, 3);\n    buffer += 4;\n  }\n}\n\ntemplate<class T>\nvoid ZRLEEncoder::writePaletteTile(int width, int height,\n                                   const T* buffer, int stride,\n                                   const PixelFormat& pf,\n                                   const Palette& palette)\n{\n  const int bitsPerPackedPixel[] = {\n    0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4\n  };\n\n  int bppp;\n  int pad;\n\n  assert(palette.size() > 1);\n  assert(palette.size() <= 16);\n\n  zos.writeU8(palette.size());\n  writePalette(pf, palette);\n\n  bppp = bitsPerPackedPixel[palette.size()-1];\n  pad = stride - width;\n\n  for (int i = 0; i < height; i++) {\n    int w;\n\n    uint8_t nbits = 0;\n    uint8_t byte = 0;\n\n    w = width;\n    while (w--) {\n      T pix = *buffer++;\n      uint8_t index = palette.lookup(pix);\n      byte = (byte << bppp) | index;\n      nbits += bppp;\n      if (nbits >= 8) {\n        zos.writeU8(byte);\n        nbits = 0;\n      }\n    }\n    if (nbits > 0) {\n      byte <<= 8 - nbits;\n      zos.writeU8(byte);\n    }\n\n    buffer += pad;\n  }\n}\n\ntemplate<class T>\nvoid ZRLEEncoder::writePaletteRLETile(int width, int height,\n                                      const T* buffer, int stride,\n                                      const PixelFormat& pf,\n                                      const Palette& palette)\n{\n  int pad;\n\n  T prevColour;\n  int runLength;\n\n  assert(palette.size() > 1);\n  assert(palette.size() <= 127);\n\n  zos.writeU8(palette.size() | 0x80);\n  writePalette(pf, palette);\n\n  pad = stride - width;\n\n  prevColour = *buffer;\n  runLength = 0;\n\n  while (height--) {\n    int w = width;\n    while (w--) {\n      if (prevColour != *buffer) {\n        if (runLength == 1)\n          zos.writeU8(palette.lookup(prevColour));\n        else {\n          zos.writeU8(palette.lookup(prevColour) | 0x80);\n\n          while (runLength > 255) {\n            zos.writeU8(255);\n            runLength -= 255;\n          }\n          zos.writeU8(runLength - 1);\n        }\n\n        prevColour = *buffer;\n        runLength = 0;\n      }\n\n      runLength++;\n      buffer++;\n    }\n    buffer += pad;\n  }\n  if (runLength == 1)\n    zos.writeU8(palette.lookup(prevColour));\n  else {\n    zos.writeU8(palette.lookup(prevColour) | 0x80);\n\n    while (runLength > 255) {\n      zos.writeU8(255);\n      runLength -= 255;\n    }\n    zos.writeU8(runLength - 1);\n  }\n}\n"
  },
  {
    "path": "common/rfb/ZRLEEncoder.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2022 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_ZRLEENCODER_H__\n#define __RFB_ZRLEENCODER_H__\n\n#include <rdr/MemOutStream.h>\n#include <rdr/ZlibOutStream.h>\n#include <rfb/Encoder.h>\n\nnamespace rfb {\n\n  class ZRLEEncoder : public Encoder {\n  public:\n    ZRLEEncoder(SConnection* conn);\n    virtual ~ZRLEEncoder();\n\n    bool isSupported() override;\n\n    void setCompressLevel(int level) override;\n\n    void writeRect(const PixelBuffer* pb,\n                   const Palette& palette) override;\n    void writeSolidRect(int width, int height, const PixelFormat& pf,\n                        const uint8_t* colour) override;\n\n  protected:\n    void writePaletteTile(const core::Rect& tile,\n                          const PixelBuffer* pb,\n                          const Palette& palette);\n    void writePaletteRLETile(const core::Rect& tile,\n                             const PixelBuffer* pb,\n                             const Palette& palette);\n    void writeRawTile(const core::Rect& tile, const PixelBuffer* pb);\n\n    void writePalette(const PixelFormat& pf, const Palette& palette);\n\n    void writePixels(const uint8_t* buffer, const PixelFormat& pf,\n                     unsigned int count);\n\n  protected:\n    // Templated, optimised methods\n    template<class T>\n    void writePaletteTile(int width, int height,\n                          const T* buffer, int stride,\n                          const PixelFormat& pf, const Palette& palette);\n    template<class T>\n    void writePaletteRLETile(int width, int height,\n                             const T* buffer, int stride,\n                             const PixelFormat& pf, const Palette& palette);\n\n  protected:\n    rdr::ZlibOutStream zos;\n    rdr::MemOutStream mos;\n  };\n}\n#endif\n"
  },
  {
    "path": "common/rfb/clipboardTypes.h",
    "content": "/* Copyright 2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_CLIPBOARDTYPES_H__\n#define __RFB_CLIPBOARDTYPES_H__\n\nnamespace rfb {\n\n  // Formats\n  const unsigned int clipboardUTF8 = 1 << 0;\n  const unsigned int clipboardRTF = 1 << 1;\n  const unsigned int clipboardHTML = 1 << 2;\n  const unsigned int clipboardDIB = 1 << 3;\n  const unsigned int clipboardFiles = 1 << 4;\n\n  const unsigned int clipboardFormatMask = 0x0000ffff;\n\n  // Actions\n  const unsigned int clipboardCaps = 1 << 24;\n  const unsigned int clipboardRequest = 1 << 25;\n  const unsigned int clipboardPeek = 1 << 26;\n  const unsigned int clipboardNotify = 1 << 27;\n  const unsigned int clipboardProvide = 1 << 28;\n\n  const unsigned int clipboardActionMask = 0xff000000;\n}\n#endif\n"
  },
  {
    "path": "common/rfb/d3des.c",
    "content": "/*\n * This is D3DES (V5.09) by Richard Outerbridge with the double and\n * triple-length support removed for use in VNC.  Also the bytebit[] array\n * has been reversed so that the most significant bit in each byte of the\n * key is ignored, not the least significant.\n *\n * These changes are:\n *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n */\n\n/* D3DES (V5.09) -\n *\n * A portable, public domain, version of the Data Encryption Standard.\n *\n * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.\n * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation\n * code;  Jim Gillogly & Phil Karn for the DES key schedule code; Dennis\n * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,\n * for humouring me on.\n *\n * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.\n * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.\n */\n\n#include \"d3des.h\"\n\nstatic void scrunch(unsigned char *, unsigned long *);\nstatic void unscrun(unsigned long *, unsigned char *);\nstatic void desfunc(unsigned long *, unsigned long *);\nstatic void cookey(unsigned long *);\n\nstatic unsigned long KnL[32] = { 0L };\n\nstatic unsigned short bytebit[8]\t= {\n\t01, 02, 04, 010, 020, 040, 0100, 0200 };\n\nstatic unsigned long bigbyte[24] = {\n\t0x800000L,\t0x400000L,\t0x200000L,\t0x100000L,\n\t0x80000L,\t0x40000L,\t0x20000L,\t0x10000L,\n\t0x8000L,\t0x4000L,\t0x2000L,\t0x1000L,\n\t0x800L, \t0x400L, \t0x200L, \t0x100L,\n\t0x80L,\t\t0x40L,\t\t0x20L,\t\t0x10L,\n\t0x8L,\t\t0x4L,\t\t0x2L,\t\t0x1L\t};\n\n/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */\n\nstatic unsigned char pc1[56] = {\n\t56, 48, 40, 32, 24, 16,  8,\t 0, 57, 49, 41, 33, 25, 17,\n\t 9,  1, 58, 50, 42, 34, 26,\t18, 10,  2, 59, 51, 43, 35,\n\t62, 54, 46, 38, 30, 22, 14,\t 6, 61, 53, 45, 37, 29, 21,\n\t13,  5, 60, 52, 44, 36, 28,\t20, 12,  4, 27, 19, 11,  3 };\n\nstatic unsigned char totrot[16] = {\n\t1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };\n\nstatic unsigned char pc2[48] = {\n\t13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,\n\t22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,\n\t40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,\n\t43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };\n\nvoid deskey(unsigned char *key, int edf) /* Thanks to James Gillogly & Phil Karn! */\n{\n\tregister int i, j, l, m, n;\n\tunsigned char pc1m[56], pcr[56];\n\tunsigned long kn[32];\n\n\tfor ( j = 0; j < 56; j++ ) {\n\t\tl = pc1[j];\n\t\tm = l & 07;\n\t\tpc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;\n\t\t}\n\tfor( i = 0; i < 16; i++ ) {\n\t\tif( edf == DE1 ) m = (15 - i) << 1;\n\t\telse m = i << 1;\n\t\tn = m + 1;\n\t\tkn[m] = kn[n] = 0L;\n\t\tfor( j = 0; j < 28; j++ ) {\n\t\t\tl = j + totrot[i];\n\t\t\tif( l < 28 ) pcr[j] = pc1m[l];\n\t\t\telse pcr[j] = pc1m[l - 28];\n\t\t\t}\n\t\tfor( j = 28; j < 56; j++ ) {\n\t\t    l = j + totrot[i];\n\t\t    if( l < 56 ) pcr[j] = pc1m[l];\n\t\t    else pcr[j] = pc1m[l - 28];\n\t\t    }\n\t\tfor( j = 0; j < 24; j++ ) {\n\t\t\tif( pcr[pc2[j]] ) kn[m] |= bigbyte[j];\n\t\t\tif( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];\n\t\t\t}\n\t\t}\n\tcookey(kn);\n\treturn;\n\t}\n\nstatic void cookey(register unsigned long *raw1)\n{\n\tregister unsigned long *cook, *raw0;\n\tunsigned long dough[32];\n\tregister int i;\n\n\tcook = dough;\n\tfor( i = 0; i < 16; i++, raw1++ ) {\n\t\traw0 = raw1++;\n\t\t*cook\t = (*raw0 & 0x00fc0000L) << 6;\n\t\t*cook\t|= (*raw0 & 0x00000fc0L) << 10;\n\t\t*cook\t|= (*raw1 & 0x00fc0000L) >> 10;\n\t\t*cook++ |= (*raw1 & 0x00000fc0L) >> 6;\n\t\t*cook\t = (*raw0 & 0x0003f000L) << 12;\n\t\t*cook\t|= (*raw0 & 0x0000003fL) << 16;\n\t\t*cook\t|= (*raw1 & 0x0003f000L) >> 4;\n\t\t*cook++ |= (*raw1 & 0x0000003fL);\n\t\t}\n\tusekey(dough);\n\treturn;\n\t}\n\nvoid cpkey(register unsigned long *into)\n{\n\tregister unsigned long *from, *endp;\n\n\tfrom = KnL, endp = &KnL[32];\n\twhile( from < endp ) *into++ = *from++;\n\treturn;\n\t}\n\nvoid usekey(register unsigned long *from)\n{\n\tregister unsigned long *to, *endp;\n\n\tto = KnL, endp = &KnL[32];\n\twhile( to < endp ) *to++ = *from++;\n\treturn;\n\t}\n\nvoid des(unsigned char *inblock, unsigned char *outblock)\n{\n\tunsigned long work[2];\n\n\tscrunch(inblock, work);\n\tdesfunc(work, KnL);\n\tunscrun(work, outblock);\n\treturn;\n\t}\n\nstatic void scrunch(register unsigned char *outof,\n                    register unsigned long *into)\n{\n\t*into\t = (*outof++ & 0xffL) << 24;\n\t*into\t|= (*outof++ & 0xffL) << 16;\n\t*into\t|= (*outof++ & 0xffL) << 8;\n\t*into++ |= (*outof++ & 0xffL);\n\t*into\t = (*outof++ & 0xffL) << 24;\n\t*into\t|= (*outof++ & 0xffL) << 16;\n\t*into\t|= (*outof++ & 0xffL) << 8;\n\t*into\t|= (*outof   & 0xffL);\n\treturn;\n\t}\n\nstatic void unscrun(register unsigned long *outof,\n                    register unsigned char *into)\n{\n\t*into++ = (unsigned char)((*outof >> 24) & 0xffL);\n\t*into++ = (unsigned char)((*outof >> 16) & 0xffL);\n\t*into++ = (unsigned char)((*outof >>  8) & 0xffL);\n\t*into++ = (unsigned char)(*outof++\t & 0xffL);\n\t*into++ = (unsigned char)((*outof >> 24) & 0xffL);\n\t*into++ = (unsigned char)((*outof >> 16) & 0xffL);\n\t*into++ = (unsigned char)((*outof >>  8) & 0xffL);\n\t*into\t=  (unsigned char)(*outof\t & 0xffL);\n\treturn;\n\t}\n\nstatic unsigned long SP1[64] = {\n\t0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,\n\t0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,\n\t0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,\n\t0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,\n\t0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,\n\t0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,\n\t0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,\n\t0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,\n\t0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,\n\t0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,\n\t0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,\n\t0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,\n\t0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,\n\t0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,\n\t0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,\n\t0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };\n\nstatic unsigned long SP2[64] = {\n\t0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,\n\t0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,\n\t0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,\n\t0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,\n\t0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,\n\t0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,\n\t0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,\n\t0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,\n\t0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,\n\t0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,\n\t0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,\n\t0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,\n\t0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,\n\t0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,\n\t0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,\n\t0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };\n\nstatic unsigned long SP3[64] = {\n\t0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,\n\t0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,\n\t0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,\n\t0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,\n\t0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,\n\t0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,\n\t0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,\n\t0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,\n\t0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,\n\t0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,\n\t0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,\n\t0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,\n\t0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,\n\t0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,\n\t0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,\n\t0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };\n\nstatic unsigned long SP4[64] = {\n\t0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,\n\t0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,\n\t0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,\n\t0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,\n\t0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,\n\t0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,\n\t0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,\n\t0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,\n\t0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,\n\t0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,\n\t0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,\n\t0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,\n\t0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,\n\t0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,\n\t0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,\n\t0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };\n\nstatic unsigned long SP5[64] = {\n\t0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,\n\t0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,\n\t0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,\n\t0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,\n\t0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,\n\t0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,\n\t0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,\n\t0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,\n\t0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,\n\t0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,\n\t0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,\n\t0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,\n\t0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,\n\t0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,\n\t0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,\n\t0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };\n\nstatic unsigned long SP6[64] = {\n\t0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,\n\t0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,\n\t0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,\n\t0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,\n\t0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,\n\t0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,\n\t0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,\n\t0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,\n\t0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,\n\t0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,\n\t0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,\n\t0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,\n\t0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,\n\t0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,\n\t0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,\n\t0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };\n\nstatic unsigned long SP7[64] = {\n\t0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,\n\t0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,\n\t0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,\n\t0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,\n\t0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,\n\t0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,\n\t0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,\n\t0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,\n\t0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,\n\t0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,\n\t0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,\n\t0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,\n\t0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,\n\t0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,\n\t0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,\n\t0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };\n\nstatic unsigned long SP8[64] = {\n\t0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,\n\t0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,\n\t0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,\n\t0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,\n\t0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,\n\t0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,\n\t0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,\n\t0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,\n\t0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,\n\t0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,\n\t0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,\n\t0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,\n\t0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,\n\t0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,\n\t0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,\n\t0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };\n\nstatic void desfunc(register unsigned long *block,\n                    register unsigned long *keys)\n{\n\tregister unsigned long fval, work, right, leftt;\n\tregister int round;\n\n\tleftt = block[0];\n\tright = block[1];\n\twork = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;\n\tright ^= work;\n\tleftt ^= (work << 4);\n\twork = ((leftt >> 16) ^ right) & 0x0000ffffL;\n\tright ^= work;\n\tleftt ^= (work << 16);\n\twork = ((right >> 2) ^ leftt) & 0x33333333L;\n\tleftt ^= work;\n\tright ^= (work << 2);\n\twork = ((right >> 8) ^ leftt) & 0x00ff00ffL;\n\tleftt ^= work;\n\tright ^= (work << 8);\n\tright = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;\n\twork = (leftt ^ right) & 0xaaaaaaaaL;\n\tleftt ^= work;\n\tright ^= work;\n\tleftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;\n\n\tfor( round = 0; round < 8; round++ ) {\n\t\twork  = (right << 28) | (right >> 4);\n\t\twork ^= *keys++;\n\t\tfval  = SP7[ work\t\t & 0x3fL];\n\t\tfval |= SP5[(work >>  8) & 0x3fL];\n\t\tfval |= SP3[(work >> 16) & 0x3fL];\n\t\tfval |= SP1[(work >> 24) & 0x3fL];\n\t\twork  = right ^ *keys++;\n\t\tfval |= SP8[ work\t\t & 0x3fL];\n\t\tfval |= SP6[(work >>  8) & 0x3fL];\n\t\tfval |= SP4[(work >> 16) & 0x3fL];\n\t\tfval |= SP2[(work >> 24) & 0x3fL];\n\t\tleftt ^= fval;\n\t\twork  = (leftt << 28) | (leftt >> 4);\n\t\twork ^= *keys++;\n\t\tfval  = SP7[ work\t\t & 0x3fL];\n\t\tfval |= SP5[(work >>  8) & 0x3fL];\n\t\tfval |= SP3[(work >> 16) & 0x3fL];\n\t\tfval |= SP1[(work >> 24) & 0x3fL];\n\t\twork  = leftt ^ *keys++;\n\t\tfval |= SP8[ work\t\t & 0x3fL];\n\t\tfval |= SP6[(work >>  8) & 0x3fL];\n\t\tfval |= SP4[(work >> 16) & 0x3fL];\n\t\tfval |= SP2[(work >> 24) & 0x3fL];\n\t\tright ^= fval;\n\t\t}\n\n\tright = (right << 31) | (right >> 1);\n\twork = (leftt ^ right) & 0xaaaaaaaaL;\n\tleftt ^= work;\n\tright ^= work;\n\tleftt = (leftt << 31) | (leftt >> 1);\n\twork = ((leftt >> 8) ^ right) & 0x00ff00ffL;\n\tright ^= work;\n\tleftt ^= (work << 8);\n\twork = ((leftt >> 2) ^ right) & 0x33333333L;\n\tright ^= work;\n\tleftt ^= (work << 2);\n\twork = ((right >> 16) ^ leftt) & 0x0000ffffL;\n\tleftt ^= work;\n\tright ^= (work << 16);\n\twork = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;\n\tleftt ^= work;\n\tright ^= (work << 4);\n\t*block++ = right;\n\t*block = leftt;\n\treturn;\n\t}\n\n/* Validation sets:\n *\n * Single-length key, single-length plaintext -\n * Key\t  : 0123 4567 89ab cdef\n * Plain  : 0123 4567 89ab cde7\n * Cipher : c957 4425 6a5e d31d\n *\n * Double-length key, single-length plaintext -\n * Key\t  : 0123 4567 89ab cdef fedc ba98 7654 3210\n * Plain  : 0123 4567 89ab cde7\n * Cipher : 7f1d 0a77 826b 8aff\n *\n * Double-length key, double-length plaintext -\n * Key\t  : 0123 4567 89ab cdef fedc ba98 7654 3210\n * Plain  : 0123 4567 89ab cdef 0123 4567 89ab cdff\n * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7\n *\n * Triple-length key, single-length plaintext -\n * Key\t  : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567\n * Plain  : 0123 4567 89ab cde7\n * Cipher : de0b 7c06 ae5e 0ed5\n *\n * Triple-length key, double-length plaintext -\n * Key\t  : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567\n * Plain  : 0123 4567 89ab cdef 0123 4567 89ab cdff\n * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5\n *\n * d3des V5.0a rwo 9208.07 18:44 Graven Imagery\n **********************************************************************/\n"
  },
  {
    "path": "common/rfb/d3des.h",
    "content": "/*\n * This is D3DES (V5.09) by Richard Outerbridge with the double and\n * triple-length support removed for use in VNC.\n *\n * These changes are:\n *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n */\n\n/* d3des.h -\n *\n *\tHeaders and defines for d3des.c\n *\tGraven Imagery, 1992.\n *\n * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge\n *\t(GEnie : OUTER; CIS : [71755,204])\n */\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n#define EN0\t0\t/* MODE == encrypt */\n#define DE1\t1\t/* MODE == decrypt */\n\nextern void deskey(unsigned char *, int);\n/*\t\t      hexkey[8]     MODE\n * Sets the internal key register according to the hexadecimal\n * key contained in the 8 bytes of hexkey, according to the DES,\n * for encryption or decryption according to MODE.\n */\n\nextern void usekey(unsigned long *);\n/*\t\t    cookedkey[32]\n * Loads the internal key register with the data in cookedkey.\n */\n\nextern void cpkey(unsigned long *);\n/*\t\t   cookedkey[32]\n * Copies the contents of the internal key register into the storage\n * located at &cookedkey[0].\n */\n\nextern void des(unsigned char *, unsigned char *);\n/*\t\t    from[8]\t      to[8]\n * Encrypts/Decrypts (according to the key currently loaded in the\n * internal key register) one block of eight bytes at address 'from'\n * into the block at address 'to'.  They can be the same.\n */\n\n#ifdef __cplusplus\n}\n#endif\n\n/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery\n ********************************************************************/\n"
  },
  {
    "path": "common/rfb/encodings.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string.h>\n#include <rfb/encodings.h>\n\nint rfb::encodingNum(const char* name)\n{\n  if (strcasecmp(name, \"raw\") == 0)      return encodingRaw;\n  if (strcasecmp(name, \"copyRect\") == 0) return encodingCopyRect;\n  if (strcasecmp(name, \"RRE\") == 0)      return encodingRRE;\n  if (strcasecmp(name, \"CoRRE\") == 0)    return encodingCoRRE;\n  if (strcasecmp(name, \"hextile\") == 0)  return encodingHextile;\n  if (strcasecmp(name, \"ZRLE\") == 0)     return encodingZRLE;\n  if (strcasecmp(name, \"Tight\") == 0)    return encodingTight;\n  if (strcasecmp(name, \"JPEG\") == 0)     return encodingJPEG;\n  if (strcasecmp(name, \"H.264\") == 0)    return encodingH264;\n  return -1;\n}\n\nconst char* rfb::encodingName(int num)\n{\n  switch (num) {\n  case encodingRaw:      return \"raw\";\n  case encodingCopyRect: return \"copyRect\";\n  case encodingRRE:      return \"RRE\";\n  case encodingCoRRE:    return \"CoRRE\";\n  case encodingHextile:  return \"hextile\";\n  case encodingZRLE:     return \"ZRLE\";\n  case encodingTight:    return \"Tight\";\n  case encodingJPEG:     return \"JPEG\";\n  case encodingH264:     return \"H.264\";\n  default:               return \"[unknown encoding]\";\n  }\n}\n"
  },
  {
    "path": "common/rfb/encodings.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyeight (C) 2011 D. R. Commander.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_ENCODINGS_H__\n#define __RFB_ENCODINGS_H__\n\nnamespace rfb {\n\n  const int encodingRaw = 0;\n  const int encodingCopyRect = 1;\n  const int encodingRRE = 2;\n  const int encodingCoRRE = 4;\n  const int encodingHextile = 5;\n  const int encodingTight = 7;\n  const int encodingZRLE = 16;\n  const int encodingJPEG = 21;\n  const int encodingH264 = 50;\n\n  const int encodingMax = 255;\n\n  const int pseudoEncodingXCursor = -240;\n  const int pseudoEncodingCursor = -239;\n  const int pseudoEncodingExtendedMouseButtons = -316;\n  const int pseudoEncodingDesktopSize = -223;\n  const int pseudoEncodingLEDState = -261;\n  const int pseudoEncodingExtendedDesktopSize = -308;\n  const int pseudoEncodingDesktopName = -307;\n  const int pseudoEncodingFence = -312;\n  const int pseudoEncodingContinuousUpdates = -313;\n  const int pseudoEncodingCursorWithAlpha = -314;\n  const int pseudoEncodingQEMUKeyEvent = -258;\n\n  // TightVNC-specific\n  const int pseudoEncodingLastRect = -224;\n  const int pseudoEncodingQualityLevel0 = -32;\n  const int pseudoEncodingQualityLevel9 = -23;\n  const int pseudoEncodingCompressLevel0 = -256;\n  const int pseudoEncodingCompressLevel9 = -247;\n\n  // TurboVNC-specific\n  const int pseudoEncodingFineQualityLevel0 = -512;\n  const int pseudoEncodingFineQualityLevel100 = -412;\n  const int pseudoEncodingSubsamp1X = -768;\n  const int pseudoEncodingSubsamp4X = -767;\n  const int pseudoEncodingSubsamp2X = -766;\n  const int pseudoEncodingSubsampGray = -765;\n  const int pseudoEncodingSubsamp8X = -764;\n  const int pseudoEncodingSubsamp16X = -763;\n\n  // VMware-specific\n  const int pseudoEncodingVMwareCursor = 0x574d5664;\n  const int pseudoEncodingVMwareCursorPosition = 0x574d5666;\n  const int pseudoEncodingVMwareLEDState = 0x574d5668;\n\n  // UltraVNC-specific\n  const int pseudoEncodingExtendedClipboard = 0xC0A1E5CE;\n\n  int encodingNum(const char* name);\n  const char* encodingName(int num);\n}\n#endif\n"
  },
  {
    "path": "common/rfb/fenceTypes.h",
    "content": "/* Copyright 2011 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_FENCETYPES_H__\n#define __RFB_FENCETYPES_H__\n\n#include <stdint.h>\n\nnamespace rfb {\n  const uint32_t fenceFlagBlockBefore = 1<<0;\n  const uint32_t fenceFlagBlockAfter  = 1<<1;\n  const uint32_t fenceFlagSyncNext    = 1<<2;\n\n  const uint32_t fenceFlagRequest     = 1<<31;\n\n  const uint32_t fenceFlagsSupported  = (fenceFlagBlockBefore |\n                                         fenceFlagBlockAfter |\n                                         fenceFlagSyncNext |\n                                         fenceFlagRequest);\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/hextileConstants.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_HEXTILECONSTANTS_H__\n#define __RFB_HEXTILECONSTANTS_H__\nnamespace rfb {\n  const int hextileRaw = (1 << 0);\n  const int hextileBgSpecified = (1 << 1);\n  const int hextileFgSpecified = (1 << 2);\n  const int hextileAnySubrects = (1 << 3);\n  const int hextileSubrectsColoured = (1 << 4);\n}\n#endif\n"
  },
  {
    "path": "common/rfb/keysymdef.h",
    "content": "/***********************************************************\nCopyright 1987, 1994, 1998  The Open Group\n\nPermission to use, copy, modify, distribute, and sell this software and its\ndocumentation for any purpose is hereby granted without fee, provided that\nthe above copyright notice appear in all copies and that both that\ncopyright notice and this permission notice appear in supporting\ndocumentation.\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of The Open Group shall\nnot be used in advertising or otherwise to promote the sale, use or\nother dealings in this Software without prior written authorization\nfrom The Open Group.\n\n\nCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts\n\n                        All Rights Reserved\n\nPermission to use, copy, modify, and distribute this software and its\ndocumentation for any purpose and without fee is hereby granted,\nprovided that the above copyright notice appear in all copies and that\nboth that copyright notice and this permission notice appear in\nsupporting documentation, and that the name of Digital not be\nused in advertising or publicity pertaining to distribution of the\nsoftware without specific, written prior permission.\n\nDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\nALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\nDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\nANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\nWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\nARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\nSOFTWARE.\n\n******************************************************************/\n\n/*\n * The \"X11 Window System Protocol\" standard defines in Appendix A the\n * keysym codes. These 29-bit integer values identify characters or\n * functions associated with each key (e.g., via the visible\n * engraving) of a keyboard layout. This file assigns mnemonic macro\n * names for these keysyms.\n *\n * This file is also compiled (by src/util/makekeys.c in libX11) into\n * hash tables that can be accessed with X11 library functions such as\n * XStringToKeysym() and XKeysymToString().\n *\n * Where a keysym corresponds one-to-one to an ISO 10646 / Unicode\n * character, this is noted in a comment that provides both the U+xxxx\n * Unicode position, as well as the official Unicode name of the\n * character.\n *\n * Some keysyms map to a character already mapped by another keysym,\n * with compatible but more precise semantics, such as the keypad-\n * related keysyms. In this case, none of the keysym are deprecated.\n * The most generic keysym is annotated as previously and more specific\n * keysyms have the same annotation between angle brackets:\n *\n *     #define XK_space                 0x0020  // U+0020 SPACE\n *     #define XK_KP_Space              0xff80  //<U+0020 SPACE>\n *\n * Where the correspondence is either not one-to-one or semantically\n * unclear, the Unicode position and name are enclosed in\n * parentheses. Such legacy keysyms should be considered deprecated\n * and are not recommended for use in future keyboard mappings.\n *\n * For any future extension of the keysyms with characters already\n * found in ISO 10646 / Unicode, the following algorithm shall be\n * used. The new keysym code position will simply be the character's\n * Unicode number plus 0x01000000. The keysym values in the range\n * 0x01000100 to 0x0110ffff are reserved to represent Unicode\n * characters in the range U+0100 to U+10FFFF.\n *\n * While most newer Unicode-based X11 clients do already accept\n * Unicode-mapped keysyms in the range 0x01000100 to 0x0110ffff, it\n * will remain necessary for clients -- in the interest of\n * compatibility with existing servers -- to also understand the\n * existing legacy keysym values in the range 0x0100 to 0x20ff.\n *\n * Where several mnemonic names are defined for the same keysym in this\n * file, all but the first one listed should be considered deprecated,\n * unless the comment explicitly states the alias, e.g.:\n *\n *     #define XK_dead_tilde            0xfe53\n *     #define XK_dead_perispomeni      0xfe53 // alias for dead_tilde\n *\n * Additionally, a keysym can be explicitly deprecated by starting the\n * comment with \"deprecated\".\n *\n * Mnemonic names for keysyms are defined in this file with lines\n * that match one of these Perl regular expressions:\n *\n *    /^\\#define XK_([a-zA-Z_0-9]+)\\s+0x([0-9a-f]+)\\s*\\/\\* U\\+([0-9A-F]{4,6}) (.*) \\*\\/\\s*$/\n *    /^\\#define XK_([a-zA-Z_0-9]+)\\s+0x([0-9a-f]+)\\s*\\/\\*\\(U\\+([0-9A-F]{4,6}) (.*)\\)\\*\\/\\s*$/\n *    /^\\#define XK_([a-zA-Z_0-9]+)\\s+0x([0-9a-f]+)\\s*(\\/\\*\\s*(.*)\\s*\\*\\/)?\\s*$/\n *\n * Before adding new keysyms, please do consider the following: In\n * addition to the keysym names defined in this file, the\n * XStringToKeysym() and XKeysymToString() functions will also handle\n * any keysym string of the form \"U0020\" to \"U007E\" and \"U00A0\" to\n * \"U10FFFF\" for all possible Unicode characters. In other words,\n * every possible Unicode character has already a keysym string\n * defined algorithmically, even if it is not listed here. Therefore,\n * defining an additional keysym macro is only necessary where a\n * non-hexadecimal mnemonic name is needed, or where the new keysym\n * does not represent any existing Unicode character.\n *\n * When adding new keysyms to this file, do not forget to also update the\n * following as needed:\n *\n *   - the mappings in src/KeyBind.c in the libX11 repo\n *     https://gitlab.freedesktop.org/xorg/lib/libx11\n *\n *   - the protocol specification in specs/keysyms.xml in this repo\n *     https://gitlab.freedesktop.org/xorg/proto/xorgproto\n *\n */\n\n#define XK_VoidSymbol                  0xffffff  /* Void symbol */\n\n#ifdef XK_MISCELLANY\n/*\n * TTY function keys, cleverly chosen to map to ASCII, for convenience of\n * programming, but could have been arbitrary (at the cost of lookup\n * tables in client code).\n */\n\n#define XK_BackSpace                     0xff08  /* U+0008 BACKSPACE */\n#define XK_Tab                           0xff09  /* U+0009 CHARACTER TABULATION */\n#define XK_Linefeed                      0xff0a  /* U+000A LINE FEED */\n#define XK_Clear                         0xff0b  /* U+000B LINE TABULATION */\n#define XK_Return                        0xff0d  /* U+000D CARRIAGE RETURN */\n#define XK_Pause                         0xff13  /* Pause, hold */\n#define XK_Scroll_Lock                   0xff14\n#define XK_Sys_Req                       0xff15\n#define XK_Escape                        0xff1b  /* U+001B ESCAPE */\n#define XK_Delete                        0xffff  /* U+007F DELETE */\n\n\n\n/* International & multi-key character composition */\n\n#define XK_Multi_key                     0xff20  /* Multi-key character compose */\n#define XK_Codeinput                     0xff37\n#define XK_SingleCandidate               0xff3c\n#define XK_MultipleCandidate             0xff3d\n#define XK_PreviousCandidate             0xff3e\n\n/* Japanese keyboard support */\n\n#define XK_Kanji                         0xff21  /* Kanji, Kanji convert */\n#define XK_Muhenkan                      0xff22  /* Cancel Conversion */\n#define XK_Henkan_Mode                   0xff23  /* Start/Stop Conversion */\n#define XK_Henkan                        0xff23  /* Alias for Henkan_Mode */\n#define XK_Romaji                        0xff24  /* to Romaji */\n#define XK_Hiragana                      0xff25  /* to Hiragana */\n#define XK_Katakana                      0xff26  /* to Katakana */\n#define XK_Hiragana_Katakana             0xff27  /* Hiragana/Katakana toggle */\n#define XK_Zenkaku                       0xff28  /* to Zenkaku */\n#define XK_Hankaku                       0xff29  /* to Hankaku */\n#define XK_Zenkaku_Hankaku               0xff2a  /* Zenkaku/Hankaku toggle */\n#define XK_Touroku                       0xff2b  /* Add to Dictionary */\n#define XK_Massyo                        0xff2c  /* Delete from Dictionary */\n#define XK_Kana_Lock                     0xff2d  /* Kana Lock */\n#define XK_Kana_Shift                    0xff2e  /* Kana Shift */\n#define XK_Eisu_Shift                    0xff2f  /* Alphanumeric Shift */\n#define XK_Eisu_toggle                   0xff30  /* Alphanumeric toggle */\n#define XK_Kanji_Bangou                  0xff37  /* Codeinput */\n#define XK_Zen_Koho                      0xff3d  /* Multiple/All Candidate(s) */\n#define XK_Mae_Koho                      0xff3e  /* Previous Candidate */\n\n/* 0xff31 thru 0xff3f are under XK_KOREAN */\n\n/* Cursor control & motion */\n\n#define XK_Home                          0xff50\n#define XK_Left                          0xff51  /* Move left, left arrow */\n#define XK_Up                            0xff52  /* Move up, up arrow */\n#define XK_Right                         0xff53  /* Move right, right arrow */\n#define XK_Down                          0xff54  /* Move down, down arrow */\n#define XK_Prior                         0xff55  /* Prior, previous */\n#define XK_Page_Up                       0xff55  /* deprecated alias for Prior */\n#define XK_Next                          0xff56  /* Next */\n#define XK_Page_Down                     0xff56  /* deprecated alias for Next */\n#define XK_End                           0xff57  /* EOL */\n#define XK_Begin                         0xff58  /* BOL */\n\n\n/* Misc functions */\n\n#define XK_Select                        0xff60  /* Select, mark */\n#define XK_Print                         0xff61\n#define XK_Execute                       0xff62  /* Execute, run, do */\n#define XK_Insert                        0xff63  /* Insert, insert here */\n#define XK_Undo                          0xff65\n#define XK_Redo                          0xff66  /* Redo, again */\n#define XK_Menu                          0xff67\n#define XK_Find                          0xff68  /* Find, search */\n#define XK_Cancel                        0xff69  /* Cancel, stop, abort, exit */\n#define XK_Help                          0xff6a  /* Help */\n#define XK_Break                         0xff6b\n#define XK_Mode_switch                   0xff7e  /* Character set switch */\n#define XK_script_switch                 0xff7e  /* Alias for Mode_switch */\n#define XK_Num_Lock                      0xff7f\n\n/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */\n\n#define XK_KP_Space                      0xff80  /*<U+0020 SPACE>*/\n#define XK_KP_Tab                        0xff89  /*<U+0009 CHARACTER TABULATION>*/\n#define XK_KP_Enter                      0xff8d  /*<U+000D CARRIAGE RETURN>*/\n#define XK_KP_F1                         0xff91  /* PF1, KP_A, ... */\n#define XK_KP_F2                         0xff92\n#define XK_KP_F3                         0xff93\n#define XK_KP_F4                         0xff94\n#define XK_KP_Home                       0xff95\n#define XK_KP_Left                       0xff96\n#define XK_KP_Up                         0xff97\n#define XK_KP_Right                      0xff98\n#define XK_KP_Down                       0xff99\n#define XK_KP_Prior                      0xff9a\n#define XK_KP_Page_Up                    0xff9a  /* deprecated alias for KP_Prior */\n#define XK_KP_Next                       0xff9b\n#define XK_KP_Page_Down                  0xff9b  /* deprecated alias for KP_Next */\n#define XK_KP_End                        0xff9c\n#define XK_KP_Begin                      0xff9d\n#define XK_KP_Insert                     0xff9e\n#define XK_KP_Delete                     0xff9f\n#define XK_KP_Equal                      0xffbd  /*<U+003D EQUALS SIGN>*/\n#define XK_KP_Multiply                   0xffaa  /*<U+002A ASTERISK>*/\n#define XK_KP_Add                        0xffab  /*<U+002B PLUS SIGN>*/\n#define XK_KP_Separator                  0xffac  /*<U+002C COMMA>*/\n#define XK_KP_Subtract                   0xffad  /*<U+002D HYPHEN-MINUS>*/\n#define XK_KP_Decimal                    0xffae  /*<U+002E FULL STOP>*/\n#define XK_KP_Divide                     0xffaf  /*<U+002F SOLIDUS>*/\n\n#define XK_KP_0                          0xffb0  /*<U+0030 DIGIT ZERO>*/\n#define XK_KP_1                          0xffb1  /*<U+0031 DIGIT ONE>*/\n#define XK_KP_2                          0xffb2  /*<U+0032 DIGIT TWO>*/\n#define XK_KP_3                          0xffb3  /*<U+0033 DIGIT THREE>*/\n#define XK_KP_4                          0xffb4  /*<U+0034 DIGIT FOUR>*/\n#define XK_KP_5                          0xffb5  /*<U+0035 DIGIT FIVE>*/\n#define XK_KP_6                          0xffb6  /*<U+0036 DIGIT SIX>*/\n#define XK_KP_7                          0xffb7  /*<U+0037 DIGIT SEVEN>*/\n#define XK_KP_8                          0xffb8  /*<U+0038 DIGIT EIGHT>*/\n#define XK_KP_9                          0xffb9  /*<U+0039 DIGIT NINE>*/\n\n\n\n/*\n * Auxiliary functions; note the duplicate definitions for left and right\n * function keys;  Sun keyboards and a few other manufacturers have such\n * function key groups on the left and/or right sides of the keyboard.\n * We've not found a keyboard with more than 35 function keys total.\n */\n\n#define XK_F1                            0xffbe\n#define XK_F2                            0xffbf\n#define XK_F3                            0xffc0\n#define XK_F4                            0xffc1\n#define XK_F5                            0xffc2\n#define XK_F6                            0xffc3\n#define XK_F7                            0xffc4\n#define XK_F8                            0xffc5\n#define XK_F9                            0xffc6\n#define XK_F10                           0xffc7\n#define XK_F11                           0xffc8\n#define XK_L1                            0xffc8  /* deprecated alias for F11 */\n#define XK_F12                           0xffc9\n#define XK_L2                            0xffc9  /* deprecated alias for F12 */\n#define XK_F13                           0xffca\n#define XK_L3                            0xffca  /* deprecated alias for F13 */\n#define XK_F14                           0xffcb\n#define XK_L4                            0xffcb  /* deprecated alias for F14 */\n#define XK_F15                           0xffcc\n#define XK_L5                            0xffcc  /* deprecated alias for F15 */\n#define XK_F16                           0xffcd\n#define XK_L6                            0xffcd  /* deprecated alias for F16 */\n#define XK_F17                           0xffce\n#define XK_L7                            0xffce  /* deprecated alias for F17 */\n#define XK_F18                           0xffcf\n#define XK_L8                            0xffcf  /* deprecated alias for F18 */\n#define XK_F19                           0xffd0\n#define XK_L9                            0xffd0  /* deprecated alias for F19 */\n#define XK_F20                           0xffd1\n#define XK_L10                           0xffd1  /* deprecated alias for F20 */\n#define XK_F21                           0xffd2\n#define XK_R1                            0xffd2  /* deprecated alias for F21 */\n#define XK_F22                           0xffd3\n#define XK_R2                            0xffd3  /* deprecated alias for F22 */\n#define XK_F23                           0xffd4\n#define XK_R3                            0xffd4  /* deprecated alias for F23 */\n#define XK_F24                           0xffd5\n#define XK_R4                            0xffd5  /* deprecated alias for F24 */\n#define XK_F25                           0xffd6\n#define XK_R5                            0xffd6  /* deprecated alias for F25 */\n#define XK_F26                           0xffd7\n#define XK_R6                            0xffd7  /* deprecated alias for F26 */\n#define XK_F27                           0xffd8\n#define XK_R7                            0xffd8  /* deprecated alias for F27 */\n#define XK_F28                           0xffd9\n#define XK_R8                            0xffd9  /* deprecated alias for F28 */\n#define XK_F29                           0xffda\n#define XK_R9                            0xffda  /* deprecated alias for F29 */\n#define XK_F30                           0xffdb\n#define XK_R10                           0xffdb  /* deprecated alias for F30 */\n#define XK_F31                           0xffdc\n#define XK_R11                           0xffdc  /* deprecated alias for F31 */\n#define XK_F32                           0xffdd\n#define XK_R12                           0xffdd  /* deprecated alias for F32 */\n#define XK_F33                           0xffde\n#define XK_R13                           0xffde  /* deprecated alias for F33 */\n#define XK_F34                           0xffdf\n#define XK_R14                           0xffdf  /* deprecated alias for F34 */\n#define XK_F35                           0xffe0\n#define XK_R15                           0xffe0  /* deprecated alias for F35 */\n\n/* Modifiers */\n\n#define XK_Shift_L                       0xffe1  /* Left shift */\n#define XK_Shift_R                       0xffe2  /* Right shift */\n#define XK_Control_L                     0xffe3  /* Left control */\n#define XK_Control_R                     0xffe4  /* Right control */\n#define XK_Caps_Lock                     0xffe5  /* Caps lock */\n#define XK_Shift_Lock                    0xffe6  /* Shift lock */\n\n#define XK_Meta_L                        0xffe7  /* Left meta */\n#define XK_Meta_R                        0xffe8  /* Right meta */\n#define XK_Alt_L                         0xffe9  /* Left alt */\n#define XK_Alt_R                         0xffea  /* Right alt */\n#define XK_Super_L                       0xffeb  /* Left super */\n#define XK_Super_R                       0xffec  /* Right super */\n#define XK_Hyper_L                       0xffed  /* Left hyper */\n#define XK_Hyper_R                       0xffee  /* Right hyper */\n#endif /* XK_MISCELLANY */\n\n/*\n * Keyboard (XKB) Extension function and modifier keys\n * (from Appendix C of \"The X Keyboard Extension: Protocol Specification\")\n * Byte 3 = 0xfe\n */\n\n#ifdef XK_XKB_KEYS\n#define XK_ISO_Lock                      0xfe01\n#define XK_ISO_Level2_Latch              0xfe02\n#define XK_ISO_Level3_Shift              0xfe03\n#define XK_ISO_Level3_Latch              0xfe04\n#define XK_ISO_Level3_Lock               0xfe05\n#define XK_ISO_Level5_Shift              0xfe11\n#define XK_ISO_Level5_Latch              0xfe12\n#define XK_ISO_Level5_Lock               0xfe13\n#define XK_ISO_Group_Shift               0xff7e  /* Alias for Mode_switch */\n#define XK_ISO_Group_Latch               0xfe06\n#define XK_ISO_Group_Lock                0xfe07\n#define XK_ISO_Next_Group                0xfe08\n#define XK_ISO_Next_Group_Lock           0xfe09\n#define XK_ISO_Prev_Group                0xfe0a\n#define XK_ISO_Prev_Group_Lock           0xfe0b\n#define XK_ISO_First_Group               0xfe0c\n#define XK_ISO_First_Group_Lock          0xfe0d\n#define XK_ISO_Last_Group                0xfe0e\n#define XK_ISO_Last_Group_Lock           0xfe0f\n\n#define XK_ISO_Left_Tab                  0xfe20\n#define XK_ISO_Move_Line_Up              0xfe21\n#define XK_ISO_Move_Line_Down            0xfe22\n#define XK_ISO_Partial_Line_Up           0xfe23\n#define XK_ISO_Partial_Line_Down         0xfe24\n#define XK_ISO_Partial_Space_Left        0xfe25\n#define XK_ISO_Partial_Space_Right       0xfe26\n#define XK_ISO_Set_Margin_Left           0xfe27\n#define XK_ISO_Set_Margin_Right          0xfe28\n#define XK_ISO_Release_Margin_Left       0xfe29\n#define XK_ISO_Release_Margin_Right      0xfe2a\n#define XK_ISO_Release_Both_Margins      0xfe2b\n#define XK_ISO_Fast_Cursor_Left          0xfe2c\n#define XK_ISO_Fast_Cursor_Right         0xfe2d\n#define XK_ISO_Fast_Cursor_Up            0xfe2e\n#define XK_ISO_Fast_Cursor_Down          0xfe2f\n#define XK_ISO_Continuous_Underline      0xfe30\n#define XK_ISO_Discontinuous_Underline   0xfe31\n#define XK_ISO_Emphasize                 0xfe32\n#define XK_ISO_Center_Object             0xfe33\n#define XK_ISO_Enter                     0xfe34\n\n#define XK_dead_grave                    0xfe50\n#define XK_dead_acute                    0xfe51\n#define XK_dead_circumflex               0xfe52\n#define XK_dead_tilde                    0xfe53\n#define XK_dead_perispomeni              0xfe53  /* alias for dead_tilde */\n#define XK_dead_macron                   0xfe54\n#define XK_dead_breve                    0xfe55\n#define XK_dead_abovedot                 0xfe56\n#define XK_dead_diaeresis                0xfe57\n#define XK_dead_abovering                0xfe58\n#define XK_dead_doubleacute              0xfe59\n#define XK_dead_caron                    0xfe5a\n#define XK_dead_cedilla                  0xfe5b\n#define XK_dead_ogonek                   0xfe5c\n#define XK_dead_iota                     0xfe5d\n#define XK_dead_voiced_sound             0xfe5e\n#define XK_dead_semivoiced_sound         0xfe5f\n#define XK_dead_belowdot                 0xfe60\n#define XK_dead_hook                     0xfe61\n#define XK_dead_horn                     0xfe62\n#define XK_dead_stroke                   0xfe63\n#define XK_dead_abovecomma               0xfe64\n#define XK_dead_psili                    0xfe64  /* alias for dead_abovecomma */\n#define XK_dead_abovereversedcomma       0xfe65\n#define XK_dead_dasia                    0xfe65  /* alias for dead_abovereversedcomma */\n#define XK_dead_doublegrave              0xfe66\n#define XK_dead_belowring                0xfe67\n#define XK_dead_belowmacron              0xfe68\n#define XK_dead_belowcircumflex          0xfe69\n#define XK_dead_belowtilde               0xfe6a\n#define XK_dead_belowbreve               0xfe6b\n#define XK_dead_belowdiaeresis           0xfe6c\n#define XK_dead_invertedbreve            0xfe6d\n#define XK_dead_belowcomma               0xfe6e\n#define XK_dead_currency                 0xfe6f\n\n/* dead vowels for universal syllable entry */\n#define XK_dead_a                        0xfe80\n#define XK_dead_A                        0xfe81\n#define XK_dead_e                        0xfe82\n#define XK_dead_E                        0xfe83\n#define XK_dead_i                        0xfe84\n#define XK_dead_I                        0xfe85\n#define XK_dead_o                        0xfe86\n#define XK_dead_O                        0xfe87\n#define XK_dead_u                        0xfe88\n#define XK_dead_U                        0xfe89\n#define XK_dead_schwa                    0xfe8a\n#define XK_dead_SCHWA                    0xfe8b\n#define XK_dead_small_schwa              0xfe8a  /* deprecated, remove in 2025 */\n#define XK_dead_capital_schwa            0xfe8b  /* deprecated, remove in 2025 */\n\n#define XK_dead_greek                    0xfe8c\n#define XK_dead_hamza                    0xfe8d\n\n#define XK_First_Virtual_Screen          0xfed0\n#define XK_Prev_Virtual_Screen           0xfed1\n#define XK_Next_Virtual_Screen           0xfed2\n#define XK_Last_Virtual_Screen           0xfed4\n#define XK_Terminate_Server              0xfed5\n\n#define XK_AccessX_Enable                0xfe70\n#define XK_AccessX_Feedback_Enable       0xfe71\n#define XK_RepeatKeys_Enable             0xfe72\n#define XK_SlowKeys_Enable               0xfe73\n#define XK_BounceKeys_Enable             0xfe74\n#define XK_StickyKeys_Enable             0xfe75\n#define XK_MouseKeys_Enable              0xfe76\n#define XK_MouseKeys_Accel_Enable        0xfe77\n#define XK_Overlay1_Enable               0xfe78\n#define XK_Overlay2_Enable               0xfe79\n#define XK_AudibleBell_Enable            0xfe7a\n\n#define XK_Pointer_Left                  0xfee0\n#define XK_Pointer_Right                 0xfee1\n#define XK_Pointer_Up                    0xfee2\n#define XK_Pointer_Down                  0xfee3\n#define XK_Pointer_UpLeft                0xfee4\n#define XK_Pointer_UpRight               0xfee5\n#define XK_Pointer_DownLeft              0xfee6\n#define XK_Pointer_DownRight             0xfee7\n#define XK_Pointer_Button_Dflt           0xfee8\n#define XK_Pointer_Button1               0xfee9\n#define XK_Pointer_Button2               0xfeea\n#define XK_Pointer_Button3               0xfeeb\n#define XK_Pointer_Button4               0xfeec\n#define XK_Pointer_Button5               0xfeed\n#define XK_Pointer_DblClick_Dflt         0xfeee\n#define XK_Pointer_DblClick1             0xfeef\n#define XK_Pointer_DblClick2             0xfef0\n#define XK_Pointer_DblClick3             0xfef1\n#define XK_Pointer_DblClick4             0xfef2\n#define XK_Pointer_DblClick5             0xfef3\n#define XK_Pointer_Drag_Dflt             0xfef4\n#define XK_Pointer_Drag1                 0xfef5\n#define XK_Pointer_Drag2                 0xfef6\n#define XK_Pointer_Drag3                 0xfef7\n#define XK_Pointer_Drag4                 0xfef8\n#define XK_Pointer_Drag5                 0xfefd\n\n#define XK_Pointer_EnableKeys            0xfef9\n#define XK_Pointer_Accelerate            0xfefa\n#define XK_Pointer_DfltBtnNext           0xfefb\n#define XK_Pointer_DfltBtnPrev           0xfefc\n\n/* Single-Stroke Multiple-Character N-Graph Keysyms For The X Input Method */\n\n#define XK_ch                            0xfea0\n#define XK_Ch                            0xfea1\n#define XK_CH                            0xfea2\n#define XK_c_h                           0xfea3\n#define XK_C_h                           0xfea4\n#define XK_C_H                           0xfea5\n\n#endif /* XK_XKB_KEYS */\n\n/*\n * 3270 Terminal Keys\n * Byte 3 = 0xfd\n */\n\n#ifdef XK_3270\n#define XK_3270_Duplicate                0xfd01\n#define XK_3270_FieldMark                0xfd02\n#define XK_3270_Right2                   0xfd03\n#define XK_3270_Left2                    0xfd04\n#define XK_3270_BackTab                  0xfd05\n#define XK_3270_EraseEOF                 0xfd06\n#define XK_3270_EraseInput               0xfd07\n#define XK_3270_Reset                    0xfd08\n#define XK_3270_Quit                     0xfd09\n#define XK_3270_PA1                      0xfd0a\n#define XK_3270_PA2                      0xfd0b\n#define XK_3270_PA3                      0xfd0c\n#define XK_3270_Test                     0xfd0d\n#define XK_3270_Attn                     0xfd0e\n#define XK_3270_CursorBlink              0xfd0f\n#define XK_3270_AltCursor                0xfd10\n#define XK_3270_KeyClick                 0xfd11\n#define XK_3270_Jump                     0xfd12\n#define XK_3270_Ident                    0xfd13\n#define XK_3270_Rule                     0xfd14\n#define XK_3270_Copy                     0xfd15\n#define XK_3270_Play                     0xfd16\n#define XK_3270_Setup                    0xfd17\n#define XK_3270_Record                   0xfd18\n#define XK_3270_ChangeScreen             0xfd19\n#define XK_3270_DeleteWord               0xfd1a\n#define XK_3270_ExSelect                 0xfd1b\n#define XK_3270_CursorSelect             0xfd1c\n#define XK_3270_PrintScreen              0xfd1d\n#define XK_3270_Enter                    0xfd1e\n#endif /* XK_3270 */\n\n/*\n * Latin 1\n * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF)\n * Byte 3 = 0\n */\n#ifdef XK_LATIN1\n#define XK_space                         0x0020  /* U+0020 SPACE */\n#define XK_exclam                        0x0021  /* U+0021 EXCLAMATION MARK */\n#define XK_quotedbl                      0x0022  /* U+0022 QUOTATION MARK */\n#define XK_numbersign                    0x0023  /* U+0023 NUMBER SIGN */\n#define XK_dollar                        0x0024  /* U+0024 DOLLAR SIGN */\n#define XK_percent                       0x0025  /* U+0025 PERCENT SIGN */\n#define XK_ampersand                     0x0026  /* U+0026 AMPERSAND */\n#define XK_apostrophe                    0x0027  /* U+0027 APOSTROPHE */\n#define XK_quoteright                    0x0027  /* deprecated */\n#define XK_parenleft                     0x0028  /* U+0028 LEFT PARENTHESIS */\n#define XK_parenright                    0x0029  /* U+0029 RIGHT PARENTHESIS */\n#define XK_asterisk                      0x002a  /* U+002A ASTERISK */\n#define XK_plus                          0x002b  /* U+002B PLUS SIGN */\n#define XK_comma                         0x002c  /* U+002C COMMA */\n#define XK_minus                         0x002d  /* U+002D HYPHEN-MINUS */\n#define XK_period                        0x002e  /* U+002E FULL STOP */\n#define XK_slash                         0x002f  /* U+002F SOLIDUS */\n#define XK_0                             0x0030  /* U+0030 DIGIT ZERO */\n#define XK_1                             0x0031  /* U+0031 DIGIT ONE */\n#define XK_2                             0x0032  /* U+0032 DIGIT TWO */\n#define XK_3                             0x0033  /* U+0033 DIGIT THREE */\n#define XK_4                             0x0034  /* U+0034 DIGIT FOUR */\n#define XK_5                             0x0035  /* U+0035 DIGIT FIVE */\n#define XK_6                             0x0036  /* U+0036 DIGIT SIX */\n#define XK_7                             0x0037  /* U+0037 DIGIT SEVEN */\n#define XK_8                             0x0038  /* U+0038 DIGIT EIGHT */\n#define XK_9                             0x0039  /* U+0039 DIGIT NINE */\n#define XK_colon                         0x003a  /* U+003A COLON */\n#define XK_semicolon                     0x003b  /* U+003B SEMICOLON */\n#define XK_less                          0x003c  /* U+003C LESS-THAN SIGN */\n#define XK_equal                         0x003d  /* U+003D EQUALS SIGN */\n#define XK_greater                       0x003e  /* U+003E GREATER-THAN SIGN */\n#define XK_question                      0x003f  /* U+003F QUESTION MARK */\n#define XK_at                            0x0040  /* U+0040 COMMERCIAL AT */\n#define XK_A                             0x0041  /* U+0041 LATIN CAPITAL LETTER A */\n#define XK_B                             0x0042  /* U+0042 LATIN CAPITAL LETTER B */\n#define XK_C                             0x0043  /* U+0043 LATIN CAPITAL LETTER C */\n#define XK_D                             0x0044  /* U+0044 LATIN CAPITAL LETTER D */\n#define XK_E                             0x0045  /* U+0045 LATIN CAPITAL LETTER E */\n#define XK_F                             0x0046  /* U+0046 LATIN CAPITAL LETTER F */\n#define XK_G                             0x0047  /* U+0047 LATIN CAPITAL LETTER G */\n#define XK_H                             0x0048  /* U+0048 LATIN CAPITAL LETTER H */\n#define XK_I                             0x0049  /* U+0049 LATIN CAPITAL LETTER I */\n#define XK_J                             0x004a  /* U+004A LATIN CAPITAL LETTER J */\n#define XK_K                             0x004b  /* U+004B LATIN CAPITAL LETTER K */\n#define XK_L                             0x004c  /* U+004C LATIN CAPITAL LETTER L */\n#define XK_M                             0x004d  /* U+004D LATIN CAPITAL LETTER M */\n#define XK_N                             0x004e  /* U+004E LATIN CAPITAL LETTER N */\n#define XK_O                             0x004f  /* U+004F LATIN CAPITAL LETTER O */\n#define XK_P                             0x0050  /* U+0050 LATIN CAPITAL LETTER P */\n#define XK_Q                             0x0051  /* U+0051 LATIN CAPITAL LETTER Q */\n#define XK_R                             0x0052  /* U+0052 LATIN CAPITAL LETTER R */\n#define XK_S                             0x0053  /* U+0053 LATIN CAPITAL LETTER S */\n#define XK_T                             0x0054  /* U+0054 LATIN CAPITAL LETTER T */\n#define XK_U                             0x0055  /* U+0055 LATIN CAPITAL LETTER U */\n#define XK_V                             0x0056  /* U+0056 LATIN CAPITAL LETTER V */\n#define XK_W                             0x0057  /* U+0057 LATIN CAPITAL LETTER W */\n#define XK_X                             0x0058  /* U+0058 LATIN CAPITAL LETTER X */\n#define XK_Y                             0x0059  /* U+0059 LATIN CAPITAL LETTER Y */\n#define XK_Z                             0x005a  /* U+005A LATIN CAPITAL LETTER Z */\n#define XK_bracketleft                   0x005b  /* U+005B LEFT SQUARE BRACKET */\n#define XK_backslash                     0x005c  /* U+005C REVERSE SOLIDUS */\n#define XK_bracketright                  0x005d  /* U+005D RIGHT SQUARE BRACKET */\n#define XK_asciicircum                   0x005e  /* U+005E CIRCUMFLEX ACCENT */\n#define XK_underscore                    0x005f  /* U+005F LOW LINE */\n#define XK_grave                         0x0060  /* U+0060 GRAVE ACCENT */\n#define XK_quoteleft                     0x0060  /* deprecated */\n#define XK_a                             0x0061  /* U+0061 LATIN SMALL LETTER A */\n#define XK_b                             0x0062  /* U+0062 LATIN SMALL LETTER B */\n#define XK_c                             0x0063  /* U+0063 LATIN SMALL LETTER C */\n#define XK_d                             0x0064  /* U+0064 LATIN SMALL LETTER D */\n#define XK_e                             0x0065  /* U+0065 LATIN SMALL LETTER E */\n#define XK_f                             0x0066  /* U+0066 LATIN SMALL LETTER F */\n#define XK_g                             0x0067  /* U+0067 LATIN SMALL LETTER G */\n#define XK_h                             0x0068  /* U+0068 LATIN SMALL LETTER H */\n#define XK_i                             0x0069  /* U+0069 LATIN SMALL LETTER I */\n#define XK_j                             0x006a  /* U+006A LATIN SMALL LETTER J */\n#define XK_k                             0x006b  /* U+006B LATIN SMALL LETTER K */\n#define XK_l                             0x006c  /* U+006C LATIN SMALL LETTER L */\n#define XK_m                             0x006d  /* U+006D LATIN SMALL LETTER M */\n#define XK_n                             0x006e  /* U+006E LATIN SMALL LETTER N */\n#define XK_o                             0x006f  /* U+006F LATIN SMALL LETTER O */\n#define XK_p                             0x0070  /* U+0070 LATIN SMALL LETTER P */\n#define XK_q                             0x0071  /* U+0071 LATIN SMALL LETTER Q */\n#define XK_r                             0x0072  /* U+0072 LATIN SMALL LETTER R */\n#define XK_s                             0x0073  /* U+0073 LATIN SMALL LETTER S */\n#define XK_t                             0x0074  /* U+0074 LATIN SMALL LETTER T */\n#define XK_u                             0x0075  /* U+0075 LATIN SMALL LETTER U */\n#define XK_v                             0x0076  /* U+0076 LATIN SMALL LETTER V */\n#define XK_w                             0x0077  /* U+0077 LATIN SMALL LETTER W */\n#define XK_x                             0x0078  /* U+0078 LATIN SMALL LETTER X */\n#define XK_y                             0x0079  /* U+0079 LATIN SMALL LETTER Y */\n#define XK_z                             0x007a  /* U+007A LATIN SMALL LETTER Z */\n#define XK_braceleft                     0x007b  /* U+007B LEFT CURLY BRACKET */\n#define XK_bar                           0x007c  /* U+007C VERTICAL LINE */\n#define XK_braceright                    0x007d  /* U+007D RIGHT CURLY BRACKET */\n#define XK_asciitilde                    0x007e  /* U+007E TILDE */\n\n#define XK_nobreakspace                  0x00a0  /* U+00A0 NO-BREAK SPACE */\n#define XK_exclamdown                    0x00a1  /* U+00A1 INVERTED EXCLAMATION MARK */\n#define XK_cent                          0x00a2  /* U+00A2 CENT SIGN */\n#define XK_sterling                      0x00a3  /* U+00A3 POUND SIGN */\n#define XK_currency                      0x00a4  /* U+00A4 CURRENCY SIGN */\n#define XK_yen                           0x00a5  /* U+00A5 YEN SIGN */\n#define XK_brokenbar                     0x00a6  /* U+00A6 BROKEN BAR */\n#define XK_section                       0x00a7  /* U+00A7 SECTION SIGN */\n#define XK_diaeresis                     0x00a8  /* U+00A8 DIAERESIS */\n#define XK_copyright                     0x00a9  /* U+00A9 COPYRIGHT SIGN */\n#define XK_ordfeminine                   0x00aa  /* U+00AA FEMININE ORDINAL INDICATOR */\n#define XK_guillemetleft                 0x00ab  /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */\n#define XK_guillemotleft                 0x00ab  /* deprecated misspelling */\n#define XK_notsign                       0x00ac  /* U+00AC NOT SIGN */\n#define XK_hyphen                        0x00ad  /* U+00AD SOFT HYPHEN */\n#define XK_registered                    0x00ae  /* U+00AE REGISTERED SIGN */\n#define XK_macron                        0x00af  /* U+00AF MACRON */\n#define XK_degree                        0x00b0  /* U+00B0 DEGREE SIGN */\n#define XK_plusminus                     0x00b1  /* U+00B1 PLUS-MINUS SIGN */\n#define XK_twosuperior                   0x00b2  /* U+00B2 SUPERSCRIPT TWO */\n#define XK_threesuperior                 0x00b3  /* U+00B3 SUPERSCRIPT THREE */\n#define XK_acute                         0x00b4  /* U+00B4 ACUTE ACCENT */\n#define XK_mu                            0x00b5  /* U+00B5 MICRO SIGN */\n#define XK_paragraph                     0x00b6  /* U+00B6 PILCROW SIGN */\n#define XK_periodcentered                0x00b7  /* U+00B7 MIDDLE DOT */\n#define XK_cedilla                       0x00b8  /* U+00B8 CEDILLA */\n#define XK_onesuperior                   0x00b9  /* U+00B9 SUPERSCRIPT ONE */\n#define XK_ordmasculine                  0x00ba  /* U+00BA MASCULINE ORDINAL INDICATOR */\n#define XK_masculine                     0x00ba  /* deprecated inconsistent name */\n#define XK_guillemetright                0x00bb  /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */\n#define XK_guillemotright                0x00bb  /* deprecated misspelling */\n#define XK_onequarter                    0x00bc  /* U+00BC VULGAR FRACTION ONE QUARTER */\n#define XK_onehalf                       0x00bd  /* U+00BD VULGAR FRACTION ONE HALF */\n#define XK_threequarters                 0x00be  /* U+00BE VULGAR FRACTION THREE QUARTERS */\n#define XK_questiondown                  0x00bf  /* U+00BF INVERTED QUESTION MARK */\n#define XK_Agrave                        0x00c0  /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */\n#define XK_Aacute                        0x00c1  /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */\n#define XK_Acircumflex                   0x00c2  /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */\n#define XK_Atilde                        0x00c3  /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */\n#define XK_Adiaeresis                    0x00c4  /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */\n#define XK_Aring                         0x00c5  /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */\n#define XK_AE                            0x00c6  /* U+00C6 LATIN CAPITAL LETTER AE */\n#define XK_Ccedilla                      0x00c7  /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */\n#define XK_Egrave                        0x00c8  /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */\n#define XK_Eacute                        0x00c9  /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */\n#define XK_Ecircumflex                   0x00ca  /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */\n#define XK_Ediaeresis                    0x00cb  /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */\n#define XK_Igrave                        0x00cc  /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */\n#define XK_Iacute                        0x00cd  /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */\n#define XK_Icircumflex                   0x00ce  /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */\n#define XK_Idiaeresis                    0x00cf  /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */\n#define XK_ETH                           0x00d0  /* U+00D0 LATIN CAPITAL LETTER ETH */\n#define XK_Eth                           0x00d0  /* deprecated */\n#define XK_Ntilde                        0x00d1  /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */\n#define XK_Ograve                        0x00d2  /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */\n#define XK_Oacute                        0x00d3  /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */\n#define XK_Ocircumflex                   0x00d4  /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */\n#define XK_Otilde                        0x00d5  /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */\n#define XK_Odiaeresis                    0x00d6  /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */\n#define XK_multiply                      0x00d7  /* U+00D7 MULTIPLICATION SIGN */\n#define XK_Oslash                        0x00d8  /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */\n#define XK_Ooblique                      0x00d8  /* deprecated alias for Oslash */\n#define XK_Ugrave                        0x00d9  /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */\n#define XK_Uacute                        0x00da  /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */\n#define XK_Ucircumflex                   0x00db  /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */\n#define XK_Udiaeresis                    0x00dc  /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */\n#define XK_Yacute                        0x00dd  /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */\n#define XK_THORN                         0x00de  /* U+00DE LATIN CAPITAL LETTER THORN */\n#define XK_Thorn                         0x00de  /* deprecated */\n#define XK_ssharp                        0x00df  /* U+00DF LATIN SMALL LETTER SHARP S */\n#define XK_agrave                        0x00e0  /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */\n#define XK_aacute                        0x00e1  /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */\n#define XK_acircumflex                   0x00e2  /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */\n#define XK_atilde                        0x00e3  /* U+00E3 LATIN SMALL LETTER A WITH TILDE */\n#define XK_adiaeresis                    0x00e4  /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */\n#define XK_aring                         0x00e5  /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */\n#define XK_ae                            0x00e6  /* U+00E6 LATIN SMALL LETTER AE */\n#define XK_ccedilla                      0x00e7  /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */\n#define XK_egrave                        0x00e8  /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */\n#define XK_eacute                        0x00e9  /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */\n#define XK_ecircumflex                   0x00ea  /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */\n#define XK_ediaeresis                    0x00eb  /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */\n#define XK_igrave                        0x00ec  /* U+00EC LATIN SMALL LETTER I WITH GRAVE */\n#define XK_iacute                        0x00ed  /* U+00ED LATIN SMALL LETTER I WITH ACUTE */\n#define XK_icircumflex                   0x00ee  /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */\n#define XK_idiaeresis                    0x00ef  /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */\n#define XK_eth                           0x00f0  /* U+00F0 LATIN SMALL LETTER ETH */\n#define XK_ntilde                        0x00f1  /* U+00F1 LATIN SMALL LETTER N WITH TILDE */\n#define XK_ograve                        0x00f2  /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */\n#define XK_oacute                        0x00f3  /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */\n#define XK_ocircumflex                   0x00f4  /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */\n#define XK_otilde                        0x00f5  /* U+00F5 LATIN SMALL LETTER O WITH TILDE */\n#define XK_odiaeresis                    0x00f6  /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */\n#define XK_division                      0x00f7  /* U+00F7 DIVISION SIGN */\n#define XK_oslash                        0x00f8  /* U+00F8 LATIN SMALL LETTER O WITH STROKE */\n#define XK_ooblique                      0x00f8  /* deprecated alias for oslash */\n#define XK_ugrave                        0x00f9  /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */\n#define XK_uacute                        0x00fa  /* U+00FA LATIN SMALL LETTER U WITH ACUTE */\n#define XK_ucircumflex                   0x00fb  /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */\n#define XK_udiaeresis                    0x00fc  /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */\n#define XK_yacute                        0x00fd  /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */\n#define XK_thorn                         0x00fe  /* U+00FE LATIN SMALL LETTER THORN */\n#define XK_ydiaeresis                    0x00ff  /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */\n#endif /* XK_LATIN1 */\n\n/*\n * Latin 2\n * Byte 3 = 1\n */\n\n#ifdef XK_LATIN2\n#define XK_Aogonek                       0x01a1  /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */\n#define XK_breve                         0x01a2  /* U+02D8 BREVE */\n#define XK_Lstroke                       0x01a3  /* U+0141 LATIN CAPITAL LETTER L WITH STROKE */\n#define XK_Lcaron                        0x01a5  /* U+013D LATIN CAPITAL LETTER L WITH CARON */\n#define XK_Sacute                        0x01a6  /* U+015A LATIN CAPITAL LETTER S WITH ACUTE */\n#define XK_Scaron                        0x01a9  /* U+0160 LATIN CAPITAL LETTER S WITH CARON */\n#define XK_Scedilla                      0x01aa  /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */\n#define XK_Tcaron                        0x01ab  /* U+0164 LATIN CAPITAL LETTER T WITH CARON */\n#define XK_Zacute                        0x01ac  /* U+0179 LATIN CAPITAL LETTER Z WITH ACUTE */\n#define XK_Zcaron                        0x01ae  /* U+017D LATIN CAPITAL LETTER Z WITH CARON */\n#define XK_Zabovedot                     0x01af  /* U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE */\n#define XK_aogonek                       0x01b1  /* U+0105 LATIN SMALL LETTER A WITH OGONEK */\n#define XK_ogonek                        0x01b2  /* U+02DB OGONEK */\n#define XK_lstroke                       0x01b3  /* U+0142 LATIN SMALL LETTER L WITH STROKE */\n#define XK_lcaron                        0x01b5  /* U+013E LATIN SMALL LETTER L WITH CARON */\n#define XK_sacute                        0x01b6  /* U+015B LATIN SMALL LETTER S WITH ACUTE */\n#define XK_caron                         0x01b7  /* U+02C7 CARON */\n#define XK_scaron                        0x01b9  /* U+0161 LATIN SMALL LETTER S WITH CARON */\n#define XK_scedilla                      0x01ba  /* U+015F LATIN SMALL LETTER S WITH CEDILLA */\n#define XK_tcaron                        0x01bb  /* U+0165 LATIN SMALL LETTER T WITH CARON */\n#define XK_zacute                        0x01bc  /* U+017A LATIN SMALL LETTER Z WITH ACUTE */\n#define XK_doubleacute                   0x01bd  /* U+02DD DOUBLE ACUTE ACCENT */\n#define XK_zcaron                        0x01be  /* U+017E LATIN SMALL LETTER Z WITH CARON */\n#define XK_zabovedot                     0x01bf  /* U+017C LATIN SMALL LETTER Z WITH DOT ABOVE */\n#define XK_Racute                        0x01c0  /* U+0154 LATIN CAPITAL LETTER R WITH ACUTE */\n#define XK_Abreve                        0x01c3  /* U+0102 LATIN CAPITAL LETTER A WITH BREVE */\n#define XK_Lacute                        0x01c5  /* U+0139 LATIN CAPITAL LETTER L WITH ACUTE */\n#define XK_Cacute                        0x01c6  /* U+0106 LATIN CAPITAL LETTER C WITH ACUTE */\n#define XK_Ccaron                        0x01c8  /* U+010C LATIN CAPITAL LETTER C WITH CARON */\n#define XK_Eogonek                       0x01ca  /* U+0118 LATIN CAPITAL LETTER E WITH OGONEK */\n#define XK_Ecaron                        0x01cc  /* U+011A LATIN CAPITAL LETTER E WITH CARON */\n#define XK_Dcaron                        0x01cf  /* U+010E LATIN CAPITAL LETTER D WITH CARON */\n#define XK_Dstroke                       0x01d0  /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */\n#define XK_Nacute                        0x01d1  /* U+0143 LATIN CAPITAL LETTER N WITH ACUTE */\n#define XK_Ncaron                        0x01d2  /* U+0147 LATIN CAPITAL LETTER N WITH CARON */\n#define XK_Odoubleacute                  0x01d5  /* U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */\n#define XK_Rcaron                        0x01d8  /* U+0158 LATIN CAPITAL LETTER R WITH CARON */\n#define XK_Uring                         0x01d9  /* U+016E LATIN CAPITAL LETTER U WITH RING ABOVE */\n#define XK_Udoubleacute                  0x01db  /* U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */\n#define XK_Tcedilla                      0x01de  /* U+0162 LATIN CAPITAL LETTER T WITH CEDILLA */\n#define XK_racute                        0x01e0  /* U+0155 LATIN SMALL LETTER R WITH ACUTE */\n#define XK_abreve                        0x01e3  /* U+0103 LATIN SMALL LETTER A WITH BREVE */\n#define XK_lacute                        0x01e5  /* U+013A LATIN SMALL LETTER L WITH ACUTE */\n#define XK_cacute                        0x01e6  /* U+0107 LATIN SMALL LETTER C WITH ACUTE */\n#define XK_ccaron                        0x01e8  /* U+010D LATIN SMALL LETTER C WITH CARON */\n#define XK_eogonek                       0x01ea  /* U+0119 LATIN SMALL LETTER E WITH OGONEK */\n#define XK_ecaron                        0x01ec  /* U+011B LATIN SMALL LETTER E WITH CARON */\n#define XK_dcaron                        0x01ef  /* U+010F LATIN SMALL LETTER D WITH CARON */\n#define XK_dstroke                       0x01f0  /* U+0111 LATIN SMALL LETTER D WITH STROKE */\n#define XK_nacute                        0x01f1  /* U+0144 LATIN SMALL LETTER N WITH ACUTE */\n#define XK_ncaron                        0x01f2  /* U+0148 LATIN SMALL LETTER N WITH CARON */\n#define XK_odoubleacute                  0x01f5  /* U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE */\n#define XK_rcaron                        0x01f8  /* U+0159 LATIN SMALL LETTER R WITH CARON */\n#define XK_uring                         0x01f9  /* U+016F LATIN SMALL LETTER U WITH RING ABOVE */\n#define XK_udoubleacute                  0x01fb  /* U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE */\n#define XK_tcedilla                      0x01fe  /* U+0163 LATIN SMALL LETTER T WITH CEDILLA */\n#define XK_abovedot                      0x01ff  /* U+02D9 DOT ABOVE */\n#endif /* XK_LATIN2 */\n\n/*\n * Latin 3\n * Byte 3 = 2\n */\n\n#ifdef XK_LATIN3\n#define XK_Hstroke                       0x02a1  /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */\n#define XK_Hcircumflex                   0x02a6  /* U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX */\n#define XK_Iabovedot                     0x02a9  /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */\n#define XK_Gbreve                        0x02ab  /* U+011E LATIN CAPITAL LETTER G WITH BREVE */\n#define XK_Jcircumflex                   0x02ac  /* U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX */\n#define XK_hstroke                       0x02b1  /* U+0127 LATIN SMALL LETTER H WITH STROKE */\n#define XK_hcircumflex                   0x02b6  /* U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX */\n#define XK_idotless                      0x02b9  /* U+0131 LATIN SMALL LETTER DOTLESS I */\n#define XK_gbreve                        0x02bb  /* U+011F LATIN SMALL LETTER G WITH BREVE */\n#define XK_jcircumflex                   0x02bc  /* U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX */\n#define XK_Cabovedot                     0x02c5  /* U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE */\n#define XK_Ccircumflex                   0x02c6  /* U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX */\n#define XK_Gabovedot                     0x02d5  /* U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE */\n#define XK_Gcircumflex                   0x02d8  /* U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX */\n#define XK_Ubreve                        0x02dd  /* U+016C LATIN CAPITAL LETTER U WITH BREVE */\n#define XK_Scircumflex                   0x02de  /* U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX */\n#define XK_cabovedot                     0x02e5  /* U+010B LATIN SMALL LETTER C WITH DOT ABOVE */\n#define XK_ccircumflex                   0x02e6  /* U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX */\n#define XK_gabovedot                     0x02f5  /* U+0121 LATIN SMALL LETTER G WITH DOT ABOVE */\n#define XK_gcircumflex                   0x02f8  /* U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX */\n#define XK_ubreve                        0x02fd  /* U+016D LATIN SMALL LETTER U WITH BREVE */\n#define XK_scircumflex                   0x02fe  /* U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX */\n#endif /* XK_LATIN3 */\n\n\n/*\n * Latin 4\n * Byte 3 = 3\n */\n\n#ifdef XK_LATIN4\n#define XK_kra                           0x03a2  /* U+0138 LATIN SMALL LETTER KRA */\n#define XK_kappa                         0x03a2  /* deprecated */\n#define XK_Rcedilla                      0x03a3  /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */\n#define XK_Itilde                        0x03a5  /* U+0128 LATIN CAPITAL LETTER I WITH TILDE */\n#define XK_Lcedilla                      0x03a6  /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */\n#define XK_Emacron                       0x03aa  /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */\n#define XK_Gcedilla                      0x03ab  /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */\n#define XK_Tslash                        0x03ac  /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */\n#define XK_rcedilla                      0x03b3  /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */\n#define XK_itilde                        0x03b5  /* U+0129 LATIN SMALL LETTER I WITH TILDE */\n#define XK_lcedilla                      0x03b6  /* U+013C LATIN SMALL LETTER L WITH CEDILLA */\n#define XK_emacron                       0x03ba  /* U+0113 LATIN SMALL LETTER E WITH MACRON */\n#define XK_gcedilla                      0x03bb  /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */\n#define XK_tslash                        0x03bc  /* U+0167 LATIN SMALL LETTER T WITH STROKE */\n#define XK_ENG                           0x03bd  /* U+014A LATIN CAPITAL LETTER ENG */\n#define XK_eng                           0x03bf  /* U+014B LATIN SMALL LETTER ENG */\n#define XK_Amacron                       0x03c0  /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */\n#define XK_Iogonek                       0x03c7  /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */\n#define XK_Eabovedot                     0x03cc  /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */\n#define XK_Imacron                       0x03cf  /* U+012A LATIN CAPITAL LETTER I WITH MACRON */\n#define XK_Ncedilla                      0x03d1  /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */\n#define XK_Omacron                       0x03d2  /* U+014C LATIN CAPITAL LETTER O WITH MACRON */\n#define XK_Kcedilla                      0x03d3  /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */\n#define XK_Uogonek                       0x03d9  /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */\n#define XK_Utilde                        0x03dd  /* U+0168 LATIN CAPITAL LETTER U WITH TILDE */\n#define XK_Umacron                       0x03de  /* U+016A LATIN CAPITAL LETTER U WITH MACRON */\n#define XK_amacron                       0x03e0  /* U+0101 LATIN SMALL LETTER A WITH MACRON */\n#define XK_iogonek                       0x03e7  /* U+012F LATIN SMALL LETTER I WITH OGONEK */\n#define XK_eabovedot                     0x03ec  /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */\n#define XK_imacron                       0x03ef  /* U+012B LATIN SMALL LETTER I WITH MACRON */\n#define XK_ncedilla                      0x03f1  /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */\n#define XK_omacron                       0x03f2  /* U+014D LATIN SMALL LETTER O WITH MACRON */\n#define XK_kcedilla                      0x03f3  /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */\n#define XK_uogonek                       0x03f9  /* U+0173 LATIN SMALL LETTER U WITH OGONEK */\n#define XK_utilde                        0x03fd  /* U+0169 LATIN SMALL LETTER U WITH TILDE */\n#define XK_umacron                       0x03fe  /* U+016B LATIN SMALL LETTER U WITH MACRON */\n#endif /* XK_LATIN4 */\n\n/*\n * Latin 8\n */\n#ifdef XK_LATIN8\n#define XK_Wcircumflex                0x1000174  /* U+0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX */\n#define XK_wcircumflex                0x1000175  /* U+0175 LATIN SMALL LETTER W WITH CIRCUMFLEX */\n#define XK_Ycircumflex                0x1000176  /* U+0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */\n#define XK_ycircumflex                0x1000177  /* U+0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX */\n#define XK_Babovedot                  0x1001e02  /* U+1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE */\n#define XK_babovedot                  0x1001e03  /* U+1E03 LATIN SMALL LETTER B WITH DOT ABOVE */\n#define XK_Dabovedot                  0x1001e0a  /* U+1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE */\n#define XK_dabovedot                  0x1001e0b  /* U+1E0B LATIN SMALL LETTER D WITH DOT ABOVE */\n#define XK_Fabovedot                  0x1001e1e  /* U+1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE */\n#define XK_fabovedot                  0x1001e1f  /* U+1E1F LATIN SMALL LETTER F WITH DOT ABOVE */\n#define XK_Mabovedot                  0x1001e40  /* U+1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE */\n#define XK_mabovedot                  0x1001e41  /* U+1E41 LATIN SMALL LETTER M WITH DOT ABOVE */\n#define XK_Pabovedot                  0x1001e56  /* U+1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE */\n#define XK_pabovedot                  0x1001e57  /* U+1E57 LATIN SMALL LETTER P WITH DOT ABOVE */\n#define XK_Sabovedot                  0x1001e60  /* U+1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE */\n#define XK_sabovedot                  0x1001e61  /* U+1E61 LATIN SMALL LETTER S WITH DOT ABOVE */\n#define XK_Tabovedot                  0x1001e6a  /* U+1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE */\n#define XK_tabovedot                  0x1001e6b  /* U+1E6B LATIN SMALL LETTER T WITH DOT ABOVE */\n#define XK_Wgrave                     0x1001e80  /* U+1E80 LATIN CAPITAL LETTER W WITH GRAVE */\n#define XK_wgrave                     0x1001e81  /* U+1E81 LATIN SMALL LETTER W WITH GRAVE */\n#define XK_Wacute                     0x1001e82  /* U+1E82 LATIN CAPITAL LETTER W WITH ACUTE */\n#define XK_wacute                     0x1001e83  /* U+1E83 LATIN SMALL LETTER W WITH ACUTE */\n#define XK_Wdiaeresis                 0x1001e84  /* U+1E84 LATIN CAPITAL LETTER W WITH DIAERESIS */\n#define XK_wdiaeresis                 0x1001e85  /* U+1E85 LATIN SMALL LETTER W WITH DIAERESIS */\n#define XK_Ygrave                     0x1001ef2  /* U+1EF2 LATIN CAPITAL LETTER Y WITH GRAVE */\n#define XK_ygrave                     0x1001ef3  /* U+1EF3 LATIN SMALL LETTER Y WITH GRAVE */\n#endif /* XK_LATIN8 */\n\n/*\n * Latin 9\n * Byte 3 = 0x13\n */\n\n#ifdef XK_LATIN9\n#define XK_OE                            0x13bc  /* U+0152 LATIN CAPITAL LIGATURE OE */\n#define XK_oe                            0x13bd  /* U+0153 LATIN SMALL LIGATURE OE */\n#define XK_Ydiaeresis                    0x13be  /* U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS */\n#endif /* XK_LATIN9 */\n\n/*\n * Katakana\n * Byte 3 = 4\n */\n\n#ifdef XK_KATAKANA\n#define XK_overline                      0x047e  /* U+203E OVERLINE */\n#define XK_kana_fullstop                 0x04a1  /* U+3002 IDEOGRAPHIC FULL STOP */\n#define XK_kana_openingbracket           0x04a2  /* U+300C LEFT CORNER BRACKET */\n#define XK_kana_closingbracket           0x04a3  /* U+300D RIGHT CORNER BRACKET */\n#define XK_kana_comma                    0x04a4  /* U+3001 IDEOGRAPHIC COMMA */\n#define XK_kana_conjunctive              0x04a5  /* U+30FB KATAKANA MIDDLE DOT */\n#define XK_kana_middledot                0x04a5  /* deprecated */\n#define XK_kana_WO                       0x04a6  /* U+30F2 KATAKANA LETTER WO */\n#define XK_kana_a                        0x04a7  /* U+30A1 KATAKANA LETTER SMALL A */\n#define XK_kana_i                        0x04a8  /* U+30A3 KATAKANA LETTER SMALL I */\n#define XK_kana_u                        0x04a9  /* U+30A5 KATAKANA LETTER SMALL U */\n#define XK_kana_e                        0x04aa  /* U+30A7 KATAKANA LETTER SMALL E */\n#define XK_kana_o                        0x04ab  /* U+30A9 KATAKANA LETTER SMALL O */\n#define XK_kana_ya                       0x04ac  /* U+30E3 KATAKANA LETTER SMALL YA */\n#define XK_kana_yu                       0x04ad  /* U+30E5 KATAKANA LETTER SMALL YU */\n#define XK_kana_yo                       0x04ae  /* U+30E7 KATAKANA LETTER SMALL YO */\n#define XK_kana_tsu                      0x04af  /* U+30C3 KATAKANA LETTER SMALL TU */\n#define XK_kana_tu                       0x04af  /* deprecated */\n#define XK_prolongedsound                0x04b0  /* U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK */\n#define XK_kana_A                        0x04b1  /* U+30A2 KATAKANA LETTER A */\n#define XK_kana_I                        0x04b2  /* U+30A4 KATAKANA LETTER I */\n#define XK_kana_U                        0x04b3  /* U+30A6 KATAKANA LETTER U */\n#define XK_kana_E                        0x04b4  /* U+30A8 KATAKANA LETTER E */\n#define XK_kana_O                        0x04b5  /* U+30AA KATAKANA LETTER O */\n#define XK_kana_KA                       0x04b6  /* U+30AB KATAKANA LETTER KA */\n#define XK_kana_KI                       0x04b7  /* U+30AD KATAKANA LETTER KI */\n#define XK_kana_KU                       0x04b8  /* U+30AF KATAKANA LETTER KU */\n#define XK_kana_KE                       0x04b9  /* U+30B1 KATAKANA LETTER KE */\n#define XK_kana_KO                       0x04ba  /* U+30B3 KATAKANA LETTER KO */\n#define XK_kana_SA                       0x04bb  /* U+30B5 KATAKANA LETTER SA */\n#define XK_kana_SHI                      0x04bc  /* U+30B7 KATAKANA LETTER SI */\n#define XK_kana_SU                       0x04bd  /* U+30B9 KATAKANA LETTER SU */\n#define XK_kana_SE                       0x04be  /* U+30BB KATAKANA LETTER SE */\n#define XK_kana_SO                       0x04bf  /* U+30BD KATAKANA LETTER SO */\n#define XK_kana_TA                       0x04c0  /* U+30BF KATAKANA LETTER TA */\n#define XK_kana_CHI                      0x04c1  /* U+30C1 KATAKANA LETTER TI */\n#define XK_kana_TI                       0x04c1  /* deprecated */\n#define XK_kana_TSU                      0x04c2  /* U+30C4 KATAKANA LETTER TU */\n#define XK_kana_TU                       0x04c2  /* deprecated */\n#define XK_kana_TE                       0x04c3  /* U+30C6 KATAKANA LETTER TE */\n#define XK_kana_TO                       0x04c4  /* U+30C8 KATAKANA LETTER TO */\n#define XK_kana_NA                       0x04c5  /* U+30CA KATAKANA LETTER NA */\n#define XK_kana_NI                       0x04c6  /* U+30CB KATAKANA LETTER NI */\n#define XK_kana_NU                       0x04c7  /* U+30CC KATAKANA LETTER NU */\n#define XK_kana_NE                       0x04c8  /* U+30CD KATAKANA LETTER NE */\n#define XK_kana_NO                       0x04c9  /* U+30CE KATAKANA LETTER NO */\n#define XK_kana_HA                       0x04ca  /* U+30CF KATAKANA LETTER HA */\n#define XK_kana_HI                       0x04cb  /* U+30D2 KATAKANA LETTER HI */\n#define XK_kana_FU                       0x04cc  /* U+30D5 KATAKANA LETTER HU */\n#define XK_kana_HU                       0x04cc  /* deprecated */\n#define XK_kana_HE                       0x04cd  /* U+30D8 KATAKANA LETTER HE */\n#define XK_kana_HO                       0x04ce  /* U+30DB KATAKANA LETTER HO */\n#define XK_kana_MA                       0x04cf  /* U+30DE KATAKANA LETTER MA */\n#define XK_kana_MI                       0x04d0  /* U+30DF KATAKANA LETTER MI */\n#define XK_kana_MU                       0x04d1  /* U+30E0 KATAKANA LETTER MU */\n#define XK_kana_ME                       0x04d2  /* U+30E1 KATAKANA LETTER ME */\n#define XK_kana_MO                       0x04d3  /* U+30E2 KATAKANA LETTER MO */\n#define XK_kana_YA                       0x04d4  /* U+30E4 KATAKANA LETTER YA */\n#define XK_kana_YU                       0x04d5  /* U+30E6 KATAKANA LETTER YU */\n#define XK_kana_YO                       0x04d6  /* U+30E8 KATAKANA LETTER YO */\n#define XK_kana_RA                       0x04d7  /* U+30E9 KATAKANA LETTER RA */\n#define XK_kana_RI                       0x04d8  /* U+30EA KATAKANA LETTER RI */\n#define XK_kana_RU                       0x04d9  /* U+30EB KATAKANA LETTER RU */\n#define XK_kana_RE                       0x04da  /* U+30EC KATAKANA LETTER RE */\n#define XK_kana_RO                       0x04db  /* U+30ED KATAKANA LETTER RO */\n#define XK_kana_WA                       0x04dc  /* U+30EF KATAKANA LETTER WA */\n#define XK_kana_N                        0x04dd  /* U+30F3 KATAKANA LETTER N */\n#define XK_voicedsound                   0x04de  /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */\n#define XK_semivoicedsound               0x04df  /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */\n#define XK_kana_switch                   0xff7e  /* Alias for Mode_switch */\n#endif /* XK_KATAKANA */\n\n/*\n * Arabic\n * Byte 3 = 5\n */\n\n#ifdef XK_ARABIC\n#define XK_Farsi_0                    0x10006f0  /* U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO */\n#define XK_Farsi_1                    0x10006f1  /* U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE */\n#define XK_Farsi_2                    0x10006f2  /* U+06F2 EXTENDED ARABIC-INDIC DIGIT TWO */\n#define XK_Farsi_3                    0x10006f3  /* U+06F3 EXTENDED ARABIC-INDIC DIGIT THREE */\n#define XK_Farsi_4                    0x10006f4  /* U+06F4 EXTENDED ARABIC-INDIC DIGIT FOUR */\n#define XK_Farsi_5                    0x10006f5  /* U+06F5 EXTENDED ARABIC-INDIC DIGIT FIVE */\n#define XK_Farsi_6                    0x10006f6  /* U+06F6 EXTENDED ARABIC-INDIC DIGIT SIX */\n#define XK_Farsi_7                    0x10006f7  /* U+06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN */\n#define XK_Farsi_8                    0x10006f8  /* U+06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT */\n#define XK_Farsi_9                    0x10006f9  /* U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE */\n#define XK_Arabic_percent             0x100066a  /* U+066A ARABIC PERCENT SIGN */\n#define XK_Arabic_superscript_alef    0x1000670  /* U+0670 ARABIC LETTER SUPERSCRIPT ALEF */\n#define XK_Arabic_tteh                0x1000679  /* U+0679 ARABIC LETTER TTEH */\n#define XK_Arabic_peh                 0x100067e  /* U+067E ARABIC LETTER PEH */\n#define XK_Arabic_tcheh               0x1000686  /* U+0686 ARABIC LETTER TCHEH */\n#define XK_Arabic_ddal                0x1000688  /* U+0688 ARABIC LETTER DDAL */\n#define XK_Arabic_rreh                0x1000691  /* U+0691 ARABIC LETTER RREH */\n#define XK_Arabic_comma                  0x05ac  /* U+060C ARABIC COMMA */\n#define XK_Arabic_fullstop            0x10006d4  /* U+06D4 ARABIC FULL STOP */\n#define XK_Arabic_0                   0x1000660  /* U+0660 ARABIC-INDIC DIGIT ZERO */\n#define XK_Arabic_1                   0x1000661  /* U+0661 ARABIC-INDIC DIGIT ONE */\n#define XK_Arabic_2                   0x1000662  /* U+0662 ARABIC-INDIC DIGIT TWO */\n#define XK_Arabic_3                   0x1000663  /* U+0663 ARABIC-INDIC DIGIT THREE */\n#define XK_Arabic_4                   0x1000664  /* U+0664 ARABIC-INDIC DIGIT FOUR */\n#define XK_Arabic_5                   0x1000665  /* U+0665 ARABIC-INDIC DIGIT FIVE */\n#define XK_Arabic_6                   0x1000666  /* U+0666 ARABIC-INDIC DIGIT SIX */\n#define XK_Arabic_7                   0x1000667  /* U+0667 ARABIC-INDIC DIGIT SEVEN */\n#define XK_Arabic_8                   0x1000668  /* U+0668 ARABIC-INDIC DIGIT EIGHT */\n#define XK_Arabic_9                   0x1000669  /* U+0669 ARABIC-INDIC DIGIT NINE */\n#define XK_Arabic_semicolon              0x05bb  /* U+061B ARABIC SEMICOLON */\n#define XK_Arabic_question_mark          0x05bf  /* U+061F ARABIC QUESTION MARK */\n#define XK_Arabic_hamza                  0x05c1  /* U+0621 ARABIC LETTER HAMZA */\n#define XK_Arabic_maddaonalef            0x05c2  /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */\n#define XK_Arabic_hamzaonalef            0x05c3  /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */\n#define XK_Arabic_hamzaonwaw             0x05c4  /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */\n#define XK_Arabic_hamzaunderalef         0x05c5  /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */\n#define XK_Arabic_hamzaonyeh             0x05c6  /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */\n#define XK_Arabic_alef                   0x05c7  /* U+0627 ARABIC LETTER ALEF */\n#define XK_Arabic_beh                    0x05c8  /* U+0628 ARABIC LETTER BEH */\n#define XK_Arabic_tehmarbuta             0x05c9  /* U+0629 ARABIC LETTER TEH MARBUTA */\n#define XK_Arabic_teh                    0x05ca  /* U+062A ARABIC LETTER TEH */\n#define XK_Arabic_theh                   0x05cb  /* U+062B ARABIC LETTER THEH */\n#define XK_Arabic_jeem                   0x05cc  /* U+062C ARABIC LETTER JEEM */\n#define XK_Arabic_hah                    0x05cd  /* U+062D ARABIC LETTER HAH */\n#define XK_Arabic_khah                   0x05ce  /* U+062E ARABIC LETTER KHAH */\n#define XK_Arabic_dal                    0x05cf  /* U+062F ARABIC LETTER DAL */\n#define XK_Arabic_thal                   0x05d0  /* U+0630 ARABIC LETTER THAL */\n#define XK_Arabic_ra                     0x05d1  /* U+0631 ARABIC LETTER REH */\n#define XK_Arabic_zain                   0x05d2  /* U+0632 ARABIC LETTER ZAIN */\n#define XK_Arabic_seen                   0x05d3  /* U+0633 ARABIC LETTER SEEN */\n#define XK_Arabic_sheen                  0x05d4  /* U+0634 ARABIC LETTER SHEEN */\n#define XK_Arabic_sad                    0x05d5  /* U+0635 ARABIC LETTER SAD */\n#define XK_Arabic_dad                    0x05d6  /* U+0636 ARABIC LETTER DAD */\n#define XK_Arabic_tah                    0x05d7  /* U+0637 ARABIC LETTER TAH */\n#define XK_Arabic_zah                    0x05d8  /* U+0638 ARABIC LETTER ZAH */\n#define XK_Arabic_ain                    0x05d9  /* U+0639 ARABIC LETTER AIN */\n#define XK_Arabic_ghain                  0x05da  /* U+063A ARABIC LETTER GHAIN */\n#define XK_Arabic_tatweel                0x05e0  /* U+0640 ARABIC TATWEEL */\n#define XK_Arabic_feh                    0x05e1  /* U+0641 ARABIC LETTER FEH */\n#define XK_Arabic_qaf                    0x05e2  /* U+0642 ARABIC LETTER QAF */\n#define XK_Arabic_kaf                    0x05e3  /* U+0643 ARABIC LETTER KAF */\n#define XK_Arabic_lam                    0x05e4  /* U+0644 ARABIC LETTER LAM */\n#define XK_Arabic_meem                   0x05e5  /* U+0645 ARABIC LETTER MEEM */\n#define XK_Arabic_noon                   0x05e6  /* U+0646 ARABIC LETTER NOON */\n#define XK_Arabic_ha                     0x05e7  /* U+0647 ARABIC LETTER HEH */\n#define XK_Arabic_heh                    0x05e7  /* deprecated */\n#define XK_Arabic_waw                    0x05e8  /* U+0648 ARABIC LETTER WAW */\n#define XK_Arabic_alefmaksura            0x05e9  /* U+0649 ARABIC LETTER ALEF MAKSURA */\n#define XK_Arabic_yeh                    0x05ea  /* U+064A ARABIC LETTER YEH */\n#define XK_Arabic_fathatan               0x05eb  /* U+064B ARABIC FATHATAN */\n#define XK_Arabic_dammatan               0x05ec  /* U+064C ARABIC DAMMATAN */\n#define XK_Arabic_kasratan               0x05ed  /* U+064D ARABIC KASRATAN */\n#define XK_Arabic_fatha                  0x05ee  /* U+064E ARABIC FATHA */\n#define XK_Arabic_damma                  0x05ef  /* U+064F ARABIC DAMMA */\n#define XK_Arabic_kasra                  0x05f0  /* U+0650 ARABIC KASRA */\n#define XK_Arabic_shadda                 0x05f1  /* U+0651 ARABIC SHADDA */\n#define XK_Arabic_sukun                  0x05f2  /* U+0652 ARABIC SUKUN */\n#define XK_Arabic_madda_above         0x1000653  /* U+0653 ARABIC MADDAH ABOVE */\n#define XK_Arabic_hamza_above         0x1000654  /* U+0654 ARABIC HAMZA ABOVE */\n#define XK_Arabic_hamza_below         0x1000655  /* U+0655 ARABIC HAMZA BELOW */\n#define XK_Arabic_jeh                 0x1000698  /* U+0698 ARABIC LETTER JEH */\n#define XK_Arabic_veh                 0x10006a4  /* U+06A4 ARABIC LETTER VEH */\n#define XK_Arabic_keheh               0x10006a9  /* U+06A9 ARABIC LETTER KEHEH */\n#define XK_Arabic_gaf                 0x10006af  /* U+06AF ARABIC LETTER GAF */\n#define XK_Arabic_noon_ghunna         0x10006ba  /* U+06BA ARABIC LETTER NOON GHUNNA */\n#define XK_Arabic_heh_doachashmee     0x10006be  /* U+06BE ARABIC LETTER HEH DOACHASHMEE */\n#define XK_Farsi_yeh                  0x10006cc  /* U+06CC ARABIC LETTER FARSI YEH */\n#define XK_Arabic_farsi_yeh           0x10006cc  /* deprecated alias for Farsi_yeh */\n#define XK_Arabic_yeh_baree           0x10006d2  /* U+06D2 ARABIC LETTER YEH BARREE */\n#define XK_Arabic_heh_goal            0x10006c1  /* U+06C1 ARABIC LETTER HEH GOAL */\n#define XK_Arabic_switch                 0xff7e  /* Alias for Mode_switch */\n#endif /* XK_ARABIC */\n\n/*\n * Cyrillic\n * Byte 3 = 6\n */\n#ifdef XK_CYRILLIC\n#define XK_Cyrillic_GHE_bar           0x1000492  /* U+0492 CYRILLIC CAPITAL LETTER GHE WITH STROKE */\n#define XK_Cyrillic_ghe_bar           0x1000493  /* U+0493 CYRILLIC SMALL LETTER GHE WITH STROKE */\n#define XK_Cyrillic_ZHE_descender     0x1000496  /* U+0496 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */\n#define XK_Cyrillic_zhe_descender     0x1000497  /* U+0497 CYRILLIC SMALL LETTER ZHE WITH DESCENDER */\n#define XK_Cyrillic_KA_descender      0x100049a  /* U+049A CYRILLIC CAPITAL LETTER KA WITH DESCENDER */\n#define XK_Cyrillic_ka_descender      0x100049b  /* U+049B CYRILLIC SMALL LETTER KA WITH DESCENDER */\n#define XK_Cyrillic_KA_vertstroke     0x100049c  /* U+049C CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */\n#define XK_Cyrillic_ka_vertstroke     0x100049d  /* U+049D CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE */\n#define XK_Cyrillic_EN_descender      0x10004a2  /* U+04A2 CYRILLIC CAPITAL LETTER EN WITH DESCENDER */\n#define XK_Cyrillic_en_descender      0x10004a3  /* U+04A3 CYRILLIC SMALL LETTER EN WITH DESCENDER */\n#define XK_Cyrillic_U_straight        0x10004ae  /* U+04AE CYRILLIC CAPITAL LETTER STRAIGHT U */\n#define XK_Cyrillic_u_straight        0x10004af  /* U+04AF CYRILLIC SMALL LETTER STRAIGHT U */\n#define XK_Cyrillic_U_straight_bar    0x10004b0  /* U+04B0 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */\n#define XK_Cyrillic_u_straight_bar    0x10004b1  /* U+04B1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE */\n#define XK_Cyrillic_HA_descender      0x10004b2  /* U+04B2 CYRILLIC CAPITAL LETTER HA WITH DESCENDER */\n#define XK_Cyrillic_ha_descender      0x10004b3  /* U+04B3 CYRILLIC SMALL LETTER HA WITH DESCENDER */\n#define XK_Cyrillic_CHE_descender     0x10004b6  /* U+04B6 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */\n#define XK_Cyrillic_che_descender     0x10004b7  /* U+04B7 CYRILLIC SMALL LETTER CHE WITH DESCENDER */\n#define XK_Cyrillic_CHE_vertstroke    0x10004b8  /* U+04B8 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */\n#define XK_Cyrillic_che_vertstroke    0x10004b9  /* U+04B9 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE */\n#define XK_Cyrillic_SHHA              0x10004ba  /* U+04BA CYRILLIC CAPITAL LETTER SHHA */\n#define XK_Cyrillic_shha              0x10004bb  /* U+04BB CYRILLIC SMALL LETTER SHHA */\n\n#define XK_Cyrillic_SCHWA             0x10004d8  /* U+04D8 CYRILLIC CAPITAL LETTER SCHWA */\n#define XK_Cyrillic_schwa             0x10004d9  /* U+04D9 CYRILLIC SMALL LETTER SCHWA */\n#define XK_Cyrillic_I_macron          0x10004e2  /* U+04E2 CYRILLIC CAPITAL LETTER I WITH MACRON */\n#define XK_Cyrillic_i_macron          0x10004e3  /* U+04E3 CYRILLIC SMALL LETTER I WITH MACRON */\n#define XK_Cyrillic_O_bar             0x10004e8  /* U+04E8 CYRILLIC CAPITAL LETTER BARRED O */\n#define XK_Cyrillic_o_bar             0x10004e9  /* U+04E9 CYRILLIC SMALL LETTER BARRED O */\n#define XK_Cyrillic_U_macron          0x10004ee  /* U+04EE CYRILLIC CAPITAL LETTER U WITH MACRON */\n#define XK_Cyrillic_u_macron          0x10004ef  /* U+04EF CYRILLIC SMALL LETTER U WITH MACRON */\n\n#define XK_Serbian_dje                   0x06a1  /* U+0452 CYRILLIC SMALL LETTER DJE */\n#define XK_Macedonia_gje                 0x06a2  /* U+0453 CYRILLIC SMALL LETTER GJE */\n#define XK_Cyrillic_io                   0x06a3  /* U+0451 CYRILLIC SMALL LETTER IO */\n#define XK_Ukrainian_ie                  0x06a4  /* U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE */\n#define XK_Ukranian_je                   0x06a4  /* deprecated */\n#define XK_Macedonia_dse                 0x06a5  /* U+0455 CYRILLIC SMALL LETTER DZE */\n#define XK_Ukrainian_i                   0x06a6  /* U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */\n#define XK_Ukranian_i                    0x06a6  /* deprecated */\n#define XK_Ukrainian_yi                  0x06a7  /* U+0457 CYRILLIC SMALL LETTER YI */\n#define XK_Ukranian_yi                   0x06a7  /* deprecated */\n#define XK_Cyrillic_je                   0x06a8  /* U+0458 CYRILLIC SMALL LETTER JE */\n#define XK_Serbian_je                    0x06a8  /* deprecated */\n#define XK_Cyrillic_lje                  0x06a9  /* U+0459 CYRILLIC SMALL LETTER LJE */\n#define XK_Serbian_lje                   0x06a9  /* deprecated */\n#define XK_Cyrillic_nje                  0x06aa  /* U+045A CYRILLIC SMALL LETTER NJE */\n#define XK_Serbian_nje                   0x06aa  /* deprecated */\n#define XK_Serbian_tshe                  0x06ab  /* U+045B CYRILLIC SMALL LETTER TSHE */\n#define XK_Macedonia_kje                 0x06ac  /* U+045C CYRILLIC SMALL LETTER KJE */\n#define XK_Ukrainian_ghe_with_upturn     0x06ad  /* U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN */\n#define XK_Byelorussian_shortu           0x06ae  /* U+045E CYRILLIC SMALL LETTER SHORT U */\n#define XK_Cyrillic_dzhe                 0x06af  /* U+045F CYRILLIC SMALL LETTER DZHE */\n#define XK_Serbian_dze                   0x06af  /* deprecated */\n#define XK_numerosign                    0x06b0  /* U+2116 NUMERO SIGN */\n#define XK_Serbian_DJE                   0x06b1  /* U+0402 CYRILLIC CAPITAL LETTER DJE */\n#define XK_Macedonia_GJE                 0x06b2  /* U+0403 CYRILLIC CAPITAL LETTER GJE */\n#define XK_Cyrillic_IO                   0x06b3  /* U+0401 CYRILLIC CAPITAL LETTER IO */\n#define XK_Ukrainian_IE                  0x06b4  /* U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE */\n#define XK_Ukranian_JE                   0x06b4  /* deprecated */\n#define XK_Macedonia_DSE                 0x06b5  /* U+0405 CYRILLIC CAPITAL LETTER DZE */\n#define XK_Ukrainian_I                   0x06b6  /* U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */\n#define XK_Ukranian_I                    0x06b6  /* deprecated */\n#define XK_Ukrainian_YI                  0x06b7  /* U+0407 CYRILLIC CAPITAL LETTER YI */\n#define XK_Ukranian_YI                   0x06b7  /* deprecated */\n#define XK_Cyrillic_JE                   0x06b8  /* U+0408 CYRILLIC CAPITAL LETTER JE */\n#define XK_Serbian_JE                    0x06b8  /* deprecated */\n#define XK_Cyrillic_LJE                  0x06b9  /* U+0409 CYRILLIC CAPITAL LETTER LJE */\n#define XK_Serbian_LJE                   0x06b9  /* deprecated */\n#define XK_Cyrillic_NJE                  0x06ba  /* U+040A CYRILLIC CAPITAL LETTER NJE */\n#define XK_Serbian_NJE                   0x06ba  /* deprecated */\n#define XK_Serbian_TSHE                  0x06bb  /* U+040B CYRILLIC CAPITAL LETTER TSHE */\n#define XK_Macedonia_KJE                 0x06bc  /* U+040C CYRILLIC CAPITAL LETTER KJE */\n#define XK_Ukrainian_GHE_WITH_UPTURN     0x06bd  /* U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN */\n#define XK_Byelorussian_SHORTU           0x06be  /* U+040E CYRILLIC CAPITAL LETTER SHORT U */\n#define XK_Cyrillic_DZHE                 0x06bf  /* U+040F CYRILLIC CAPITAL LETTER DZHE */\n#define XK_Serbian_DZE                   0x06bf  /* deprecated */\n#define XK_Cyrillic_yu                   0x06c0  /* U+044E CYRILLIC SMALL LETTER YU */\n#define XK_Cyrillic_a                    0x06c1  /* U+0430 CYRILLIC SMALL LETTER A */\n#define XK_Cyrillic_be                   0x06c2  /* U+0431 CYRILLIC SMALL LETTER BE */\n#define XK_Cyrillic_tse                  0x06c3  /* U+0446 CYRILLIC SMALL LETTER TSE */\n#define XK_Cyrillic_de                   0x06c4  /* U+0434 CYRILLIC SMALL LETTER DE */\n#define XK_Cyrillic_ie                   0x06c5  /* U+0435 CYRILLIC SMALL LETTER IE */\n#define XK_Cyrillic_ef                   0x06c6  /* U+0444 CYRILLIC SMALL LETTER EF */\n#define XK_Cyrillic_ghe                  0x06c7  /* U+0433 CYRILLIC SMALL LETTER GHE */\n#define XK_Cyrillic_ha                   0x06c8  /* U+0445 CYRILLIC SMALL LETTER HA */\n#define XK_Cyrillic_i                    0x06c9  /* U+0438 CYRILLIC SMALL LETTER I */\n#define XK_Cyrillic_shorti               0x06ca  /* U+0439 CYRILLIC SMALL LETTER SHORT I */\n#define XK_Cyrillic_ka                   0x06cb  /* U+043A CYRILLIC SMALL LETTER KA */\n#define XK_Cyrillic_el                   0x06cc  /* U+043B CYRILLIC SMALL LETTER EL */\n#define XK_Cyrillic_em                   0x06cd  /* U+043C CYRILLIC SMALL LETTER EM */\n#define XK_Cyrillic_en                   0x06ce  /* U+043D CYRILLIC SMALL LETTER EN */\n#define XK_Cyrillic_o                    0x06cf  /* U+043E CYRILLIC SMALL LETTER O */\n#define XK_Cyrillic_pe                   0x06d0  /* U+043F CYRILLIC SMALL LETTER PE */\n#define XK_Cyrillic_ya                   0x06d1  /* U+044F CYRILLIC SMALL LETTER YA */\n#define XK_Cyrillic_er                   0x06d2  /* U+0440 CYRILLIC SMALL LETTER ER */\n#define XK_Cyrillic_es                   0x06d3  /* U+0441 CYRILLIC SMALL LETTER ES */\n#define XK_Cyrillic_te                   0x06d4  /* U+0442 CYRILLIC SMALL LETTER TE */\n#define XK_Cyrillic_u                    0x06d5  /* U+0443 CYRILLIC SMALL LETTER U */\n#define XK_Cyrillic_zhe                  0x06d6  /* U+0436 CYRILLIC SMALL LETTER ZHE */\n#define XK_Cyrillic_ve                   0x06d7  /* U+0432 CYRILLIC SMALL LETTER VE */\n#define XK_Cyrillic_softsign             0x06d8  /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */\n#define XK_Cyrillic_yeru                 0x06d9  /* U+044B CYRILLIC SMALL LETTER YERU */\n#define XK_Cyrillic_ze                   0x06da  /* U+0437 CYRILLIC SMALL LETTER ZE */\n#define XK_Cyrillic_sha                  0x06db  /* U+0448 CYRILLIC SMALL LETTER SHA */\n#define XK_Cyrillic_e                    0x06dc  /* U+044D CYRILLIC SMALL LETTER E */\n#define XK_Cyrillic_shcha                0x06dd  /* U+0449 CYRILLIC SMALL LETTER SHCHA */\n#define XK_Cyrillic_che                  0x06de  /* U+0447 CYRILLIC SMALL LETTER CHE */\n#define XK_Cyrillic_hardsign             0x06df  /* U+044A CYRILLIC SMALL LETTER HARD SIGN */\n#define XK_Cyrillic_YU                   0x06e0  /* U+042E CYRILLIC CAPITAL LETTER YU */\n#define XK_Cyrillic_A                    0x06e1  /* U+0410 CYRILLIC CAPITAL LETTER A */\n#define XK_Cyrillic_BE                   0x06e2  /* U+0411 CYRILLIC CAPITAL LETTER BE */\n#define XK_Cyrillic_TSE                  0x06e3  /* U+0426 CYRILLIC CAPITAL LETTER TSE */\n#define XK_Cyrillic_DE                   0x06e4  /* U+0414 CYRILLIC CAPITAL LETTER DE */\n#define XK_Cyrillic_IE                   0x06e5  /* U+0415 CYRILLIC CAPITAL LETTER IE */\n#define XK_Cyrillic_EF                   0x06e6  /* U+0424 CYRILLIC CAPITAL LETTER EF */\n#define XK_Cyrillic_GHE                  0x06e7  /* U+0413 CYRILLIC CAPITAL LETTER GHE */\n#define XK_Cyrillic_HA                   0x06e8  /* U+0425 CYRILLIC CAPITAL LETTER HA */\n#define XK_Cyrillic_I                    0x06e9  /* U+0418 CYRILLIC CAPITAL LETTER I */\n#define XK_Cyrillic_SHORTI               0x06ea  /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */\n#define XK_Cyrillic_KA                   0x06eb  /* U+041A CYRILLIC CAPITAL LETTER KA */\n#define XK_Cyrillic_EL                   0x06ec  /* U+041B CYRILLIC CAPITAL LETTER EL */\n#define XK_Cyrillic_EM                   0x06ed  /* U+041C CYRILLIC CAPITAL LETTER EM */\n#define XK_Cyrillic_EN                   0x06ee  /* U+041D CYRILLIC CAPITAL LETTER EN */\n#define XK_Cyrillic_O                    0x06ef  /* U+041E CYRILLIC CAPITAL LETTER O */\n#define XK_Cyrillic_PE                   0x06f0  /* U+041F CYRILLIC CAPITAL LETTER PE */\n#define XK_Cyrillic_YA                   0x06f1  /* U+042F CYRILLIC CAPITAL LETTER YA */\n#define XK_Cyrillic_ER                   0x06f2  /* U+0420 CYRILLIC CAPITAL LETTER ER */\n#define XK_Cyrillic_ES                   0x06f3  /* U+0421 CYRILLIC CAPITAL LETTER ES */\n#define XK_Cyrillic_TE                   0x06f4  /* U+0422 CYRILLIC CAPITAL LETTER TE */\n#define XK_Cyrillic_U                    0x06f5  /* U+0423 CYRILLIC CAPITAL LETTER U */\n#define XK_Cyrillic_ZHE                  0x06f6  /* U+0416 CYRILLIC CAPITAL LETTER ZHE */\n#define XK_Cyrillic_VE                   0x06f7  /* U+0412 CYRILLIC CAPITAL LETTER VE */\n#define XK_Cyrillic_SOFTSIGN             0x06f8  /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */\n#define XK_Cyrillic_YERU                 0x06f9  /* U+042B CYRILLIC CAPITAL LETTER YERU */\n#define XK_Cyrillic_ZE                   0x06fa  /* U+0417 CYRILLIC CAPITAL LETTER ZE */\n#define XK_Cyrillic_SHA                  0x06fb  /* U+0428 CYRILLIC CAPITAL LETTER SHA */\n#define XK_Cyrillic_E                    0x06fc  /* U+042D CYRILLIC CAPITAL LETTER E */\n#define XK_Cyrillic_SHCHA                0x06fd  /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */\n#define XK_Cyrillic_CHE                  0x06fe  /* U+0427 CYRILLIC CAPITAL LETTER CHE */\n#define XK_Cyrillic_HARDSIGN             0x06ff  /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */\n#endif /* XK_CYRILLIC */\n\n/*\n * Greek\n * (based on an early draft of, and not quite identical to, ISO/IEC 8859-7)\n * Byte 3 = 7\n */\n\n#ifdef XK_GREEK\n#define XK_Greek_ALPHAaccent             0x07a1  /* U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS */\n#define XK_Greek_EPSILONaccent           0x07a2  /* U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS */\n#define XK_Greek_ETAaccent               0x07a3  /* U+0389 GREEK CAPITAL LETTER ETA WITH TONOS */\n#define XK_Greek_IOTAaccent              0x07a4  /* U+038A GREEK CAPITAL LETTER IOTA WITH TONOS */\n#define XK_Greek_IOTAdieresis            0x07a5  /* U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */\n#define XK_Greek_IOTAdiaeresis           0x07a5  /* deprecated (old typo) */\n#define XK_Greek_OMICRONaccent           0x07a7  /* U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS */\n#define XK_Greek_UPSILONaccent           0x07a8  /* U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS */\n#define XK_Greek_UPSILONdieresis         0x07a9  /* U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */\n#define XK_Greek_OMEGAaccent             0x07ab  /* U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS */\n#define XK_Greek_accentdieresis          0x07ae  /* U+0385 GREEK DIALYTIKA TONOS */\n#define XK_Greek_horizbar                0x07af  /* U+2015 HORIZONTAL BAR */\n#define XK_Greek_alphaaccent             0x07b1  /* U+03AC GREEK SMALL LETTER ALPHA WITH TONOS */\n#define XK_Greek_epsilonaccent           0x07b2  /* U+03AD GREEK SMALL LETTER EPSILON WITH TONOS */\n#define XK_Greek_etaaccent               0x07b3  /* U+03AE GREEK SMALL LETTER ETA WITH TONOS */\n#define XK_Greek_iotaaccent              0x07b4  /* U+03AF GREEK SMALL LETTER IOTA WITH TONOS */\n#define XK_Greek_iotadieresis            0x07b5  /* U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA */\n#define XK_Greek_iotaaccentdieresis      0x07b6  /* U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */\n#define XK_Greek_omicronaccent           0x07b7  /* U+03CC GREEK SMALL LETTER OMICRON WITH TONOS */\n#define XK_Greek_upsilonaccent           0x07b8  /* U+03CD GREEK SMALL LETTER UPSILON WITH TONOS */\n#define XK_Greek_upsilondieresis         0x07b9  /* U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA */\n#define XK_Greek_upsilonaccentdieresis   0x07ba  /* U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */\n#define XK_Greek_omegaaccent             0x07bb  /* U+03CE GREEK SMALL LETTER OMEGA WITH TONOS */\n#define XK_Greek_ALPHA                   0x07c1  /* U+0391 GREEK CAPITAL LETTER ALPHA */\n#define XK_Greek_BETA                    0x07c2  /* U+0392 GREEK CAPITAL LETTER BETA */\n#define XK_Greek_GAMMA                   0x07c3  /* U+0393 GREEK CAPITAL LETTER GAMMA */\n#define XK_Greek_DELTA                   0x07c4  /* U+0394 GREEK CAPITAL LETTER DELTA */\n#define XK_Greek_EPSILON                 0x07c5  /* U+0395 GREEK CAPITAL LETTER EPSILON */\n#define XK_Greek_ZETA                    0x07c6  /* U+0396 GREEK CAPITAL LETTER ZETA */\n#define XK_Greek_ETA                     0x07c7  /* U+0397 GREEK CAPITAL LETTER ETA */\n#define XK_Greek_THETA                   0x07c8  /* U+0398 GREEK CAPITAL LETTER THETA */\n#define XK_Greek_IOTA                    0x07c9  /* U+0399 GREEK CAPITAL LETTER IOTA */\n#define XK_Greek_KAPPA                   0x07ca  /* U+039A GREEK CAPITAL LETTER KAPPA */\n#define XK_Greek_LAMDA                   0x07cb  /* U+039B GREEK CAPITAL LETTER LAMDA */\n#define XK_Greek_LAMBDA                  0x07cb  /* alias for Greek_LAMDA */\n#define XK_Greek_MU                      0x07cc  /* U+039C GREEK CAPITAL LETTER MU */\n#define XK_Greek_NU                      0x07cd  /* U+039D GREEK CAPITAL LETTER NU */\n#define XK_Greek_XI                      0x07ce  /* U+039E GREEK CAPITAL LETTER XI */\n#define XK_Greek_OMICRON                 0x07cf  /* U+039F GREEK CAPITAL LETTER OMICRON */\n#define XK_Greek_PI                      0x07d0  /* U+03A0 GREEK CAPITAL LETTER PI */\n#define XK_Greek_RHO                     0x07d1  /* U+03A1 GREEK CAPITAL LETTER RHO */\n#define XK_Greek_SIGMA                   0x07d2  /* U+03A3 GREEK CAPITAL LETTER SIGMA */\n#define XK_Greek_TAU                     0x07d4  /* U+03A4 GREEK CAPITAL LETTER TAU */\n#define XK_Greek_UPSILON                 0x07d5  /* U+03A5 GREEK CAPITAL LETTER UPSILON */\n#define XK_Greek_PHI                     0x07d6  /* U+03A6 GREEK CAPITAL LETTER PHI */\n#define XK_Greek_CHI                     0x07d7  /* U+03A7 GREEK CAPITAL LETTER CHI */\n#define XK_Greek_PSI                     0x07d8  /* U+03A8 GREEK CAPITAL LETTER PSI */\n#define XK_Greek_OMEGA                   0x07d9  /* U+03A9 GREEK CAPITAL LETTER OMEGA */\n#define XK_Greek_alpha                   0x07e1  /* U+03B1 GREEK SMALL LETTER ALPHA */\n#define XK_Greek_beta                    0x07e2  /* U+03B2 GREEK SMALL LETTER BETA */\n#define XK_Greek_gamma                   0x07e3  /* U+03B3 GREEK SMALL LETTER GAMMA */\n#define XK_Greek_delta                   0x07e4  /* U+03B4 GREEK SMALL LETTER DELTA */\n#define XK_Greek_epsilon                 0x07e5  /* U+03B5 GREEK SMALL LETTER EPSILON */\n#define XK_Greek_zeta                    0x07e6  /* U+03B6 GREEK SMALL LETTER ZETA */\n#define XK_Greek_eta                     0x07e7  /* U+03B7 GREEK SMALL LETTER ETA */\n#define XK_Greek_theta                   0x07e8  /* U+03B8 GREEK SMALL LETTER THETA */\n#define XK_Greek_iota                    0x07e9  /* U+03B9 GREEK SMALL LETTER IOTA */\n#define XK_Greek_kappa                   0x07ea  /* U+03BA GREEK SMALL LETTER KAPPA */\n#define XK_Greek_lamda                   0x07eb  /* U+03BB GREEK SMALL LETTER LAMDA */\n#define XK_Greek_lambda                  0x07eb  /* alias for Greek_lamda */\n#define XK_Greek_mu                      0x07ec  /* U+03BC GREEK SMALL LETTER MU */\n#define XK_Greek_nu                      0x07ed  /* U+03BD GREEK SMALL LETTER NU */\n#define XK_Greek_xi                      0x07ee  /* U+03BE GREEK SMALL LETTER XI */\n#define XK_Greek_omicron                 0x07ef  /* U+03BF GREEK SMALL LETTER OMICRON */\n#define XK_Greek_pi                      0x07f0  /* U+03C0 GREEK SMALL LETTER PI */\n#define XK_Greek_rho                     0x07f1  /* U+03C1 GREEK SMALL LETTER RHO */\n#define XK_Greek_sigma                   0x07f2  /* U+03C3 GREEK SMALL LETTER SIGMA */\n#define XK_Greek_finalsmallsigma         0x07f3  /* U+03C2 GREEK SMALL LETTER FINAL SIGMA */\n#define XK_Greek_tau                     0x07f4  /* U+03C4 GREEK SMALL LETTER TAU */\n#define XK_Greek_upsilon                 0x07f5  /* U+03C5 GREEK SMALL LETTER UPSILON */\n#define XK_Greek_phi                     0x07f6  /* U+03C6 GREEK SMALL LETTER PHI */\n#define XK_Greek_chi                     0x07f7  /* U+03C7 GREEK SMALL LETTER CHI */\n#define XK_Greek_psi                     0x07f8  /* U+03C8 GREEK SMALL LETTER PSI */\n#define XK_Greek_omega                   0x07f9  /* U+03C9 GREEK SMALL LETTER OMEGA */\n#define XK_Greek_switch                  0xff7e  /* Alias for Mode_switch */\n#endif /* XK_GREEK */\n\n/*\n * Technical\n * (from the DEC VT330/VT420 Technical Character Set, http://vt100.net/charsets/technical.html)\n * Byte 3 = 8\n */\n\n#ifdef XK_TECHNICAL\n#define XK_leftradical                   0x08a1  /* U+23B7 RADICAL SYMBOL BOTTOM */\n#define XK_topleftradical                0x08a2  /*(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)*/\n#define XK_horizconnector                0x08a3  /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/\n#define XK_topintegral                   0x08a4  /* U+2320 TOP HALF INTEGRAL */\n#define XK_botintegral                   0x08a5  /* U+2321 BOTTOM HALF INTEGRAL */\n#define XK_vertconnector                 0x08a6  /*(U+2502 BOX DRAWINGS LIGHT VERTICAL)*/\n#define XK_topleftsqbracket              0x08a7  /* U+23A1 LEFT SQUARE BRACKET UPPER CORNER */\n#define XK_botleftsqbracket              0x08a8  /* U+23A3 LEFT SQUARE BRACKET LOWER CORNER */\n#define XK_toprightsqbracket             0x08a9  /* U+23A4 RIGHT SQUARE BRACKET UPPER CORNER */\n#define XK_botrightsqbracket             0x08aa  /* U+23A6 RIGHT SQUARE BRACKET LOWER CORNER */\n#define XK_topleftparens                 0x08ab  /* U+239B LEFT PARENTHESIS UPPER HOOK */\n#define XK_botleftparens                 0x08ac  /* U+239D LEFT PARENTHESIS LOWER HOOK */\n#define XK_toprightparens                0x08ad  /* U+239E RIGHT PARENTHESIS UPPER HOOK */\n#define XK_botrightparens                0x08ae  /* U+23A0 RIGHT PARENTHESIS LOWER HOOK */\n#define XK_leftmiddlecurlybrace          0x08af  /* U+23A8 LEFT CURLY BRACKET MIDDLE PIECE */\n#define XK_rightmiddlecurlybrace         0x08b0  /* U+23AC RIGHT CURLY BRACKET MIDDLE PIECE */\n#define XK_topleftsummation              0x08b1\n#define XK_botleftsummation              0x08b2\n#define XK_topvertsummationconnector     0x08b3\n#define XK_botvertsummationconnector     0x08b4\n#define XK_toprightsummation             0x08b5\n#define XK_botrightsummation             0x08b6\n#define XK_rightmiddlesummation          0x08b7\n#define XK_lessthanequal                 0x08bc  /* U+2264 LESS-THAN OR EQUAL TO */\n#define XK_notequal                      0x08bd  /* U+2260 NOT EQUAL TO */\n#define XK_greaterthanequal              0x08be  /* U+2265 GREATER-THAN OR EQUAL TO */\n#define XK_integral                      0x08bf  /* U+222B INTEGRAL */\n#define XK_therefore                     0x08c0  /* U+2234 THEREFORE */\n#define XK_variation                     0x08c1  /* U+221D PROPORTIONAL TO */\n#define XK_infinity                      0x08c2  /* U+221E INFINITY */\n#define XK_nabla                         0x08c5  /* U+2207 NABLA */\n#define XK_approximate                   0x08c8  /* U+223C TILDE OPERATOR */\n#define XK_similarequal                  0x08c9  /* U+2243 ASYMPTOTICALLY EQUAL TO */\n#define XK_ifonlyif                      0x08cd  /* U+21D4 LEFT RIGHT DOUBLE ARROW */\n#define XK_implies                       0x08ce  /* U+21D2 RIGHTWARDS DOUBLE ARROW */\n#define XK_identical                     0x08cf  /* U+2261 IDENTICAL TO */\n#define XK_radical                       0x08d6  /* U+221A SQUARE ROOT */\n#define XK_includedin                    0x08da  /* U+2282 SUBSET OF */\n#define XK_includes                      0x08db  /* U+2283 SUPERSET OF */\n#define XK_intersection                  0x08dc  /* U+2229 INTERSECTION */\n#define XK_union                         0x08dd  /* U+222A UNION */\n#define XK_logicaland                    0x08de  /* U+2227 LOGICAL AND */\n#define XK_logicalor                     0x08df  /* U+2228 LOGICAL OR */\n#define XK_partialderivative             0x08ef  /* U+2202 PARTIAL DIFFERENTIAL */\n#define XK_function                      0x08f6  /* U+0192 LATIN SMALL LETTER F WITH HOOK */\n#define XK_leftarrow                     0x08fb  /* U+2190 LEFTWARDS ARROW */\n#define XK_uparrow                       0x08fc  /* U+2191 UPWARDS ARROW */\n#define XK_rightarrow                    0x08fd  /* U+2192 RIGHTWARDS ARROW */\n#define XK_downarrow                     0x08fe  /* U+2193 DOWNWARDS ARROW */\n#endif /* XK_TECHNICAL */\n\n/*\n * Special\n * (from the DEC VT100 Special Graphics Character Set)\n * Byte 3 = 9\n */\n\n#ifdef XK_SPECIAL\n#define XK_blank                         0x09df\n#define XK_soliddiamond                  0x09e0  /* U+25C6 BLACK DIAMOND */\n#define XK_checkerboard                  0x09e1  /* U+2592 MEDIUM SHADE */\n#define XK_ht                            0x09e2  /* U+2409 SYMBOL FOR HORIZONTAL TABULATION */\n#define XK_ff                            0x09e3  /* U+240C SYMBOL FOR FORM FEED */\n#define XK_cr                            0x09e4  /* U+240D SYMBOL FOR CARRIAGE RETURN */\n#define XK_lf                            0x09e5  /* U+240A SYMBOL FOR LINE FEED */\n#define XK_nl                            0x09e8  /* U+2424 SYMBOL FOR NEWLINE */\n#define XK_vt                            0x09e9  /* U+240B SYMBOL FOR VERTICAL TABULATION */\n#define XK_lowrightcorner                0x09ea  /* U+2518 BOX DRAWINGS LIGHT UP AND LEFT */\n#define XK_uprightcorner                 0x09eb  /* U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT */\n#define XK_upleftcorner                  0x09ec  /* U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT */\n#define XK_lowleftcorner                 0x09ed  /* U+2514 BOX DRAWINGS LIGHT UP AND RIGHT */\n#define XK_crossinglines                 0x09ee  /* U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */\n#define XK_horizlinescan1                0x09ef  /* U+23BA HORIZONTAL SCAN LINE-1 */\n#define XK_horizlinescan3                0x09f0  /* U+23BB HORIZONTAL SCAN LINE-3 */\n#define XK_horizlinescan5                0x09f1  /* U+2500 BOX DRAWINGS LIGHT HORIZONTAL */\n#define XK_horizlinescan7                0x09f2  /* U+23BC HORIZONTAL SCAN LINE-7 */\n#define XK_horizlinescan9                0x09f3  /* U+23BD HORIZONTAL SCAN LINE-9 */\n#define XK_leftt                         0x09f4  /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */\n#define XK_rightt                        0x09f5  /* U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT */\n#define XK_bott                          0x09f6  /* U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL */\n#define XK_topt                          0x09f7  /* U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */\n#define XK_vertbar                       0x09f8  /* U+2502 BOX DRAWINGS LIGHT VERTICAL */\n#endif /* XK_SPECIAL */\n\n/*\n * Publishing\n * (these are probably from a long forgotten DEC Publishing\n * font that once shipped with DECwrite)\n * Byte 3 = 0x0a\n */\n\n#ifdef XK_PUBLISHING\n#define XK_emspace                       0x0aa1  /* U+2003 EM SPACE */\n#define XK_enspace                       0x0aa2  /* U+2002 EN SPACE */\n#define XK_em3space                      0x0aa3  /* U+2004 THREE-PER-EM SPACE */\n#define XK_em4space                      0x0aa4  /* U+2005 FOUR-PER-EM SPACE */\n#define XK_digitspace                    0x0aa5  /* U+2007 FIGURE SPACE */\n#define XK_punctspace                    0x0aa6  /* U+2008 PUNCTUATION SPACE */\n#define XK_thinspace                     0x0aa7  /* U+2009 THIN SPACE */\n#define XK_hairspace                     0x0aa8  /* U+200A HAIR SPACE */\n#define XK_emdash                        0x0aa9  /* U+2014 EM DASH */\n#define XK_endash                        0x0aaa  /* U+2013 EN DASH */\n#define XK_signifblank                   0x0aac  /*(U+2423 OPEN BOX)*/\n#define XK_ellipsis                      0x0aae  /* U+2026 HORIZONTAL ELLIPSIS */\n#define XK_doubbaselinedot               0x0aaf  /* U+2025 TWO DOT LEADER */\n#define XK_onethird                      0x0ab0  /* U+2153 VULGAR FRACTION ONE THIRD */\n#define XK_twothirds                     0x0ab1  /* U+2154 VULGAR FRACTION TWO THIRDS */\n#define XK_onefifth                      0x0ab2  /* U+2155 VULGAR FRACTION ONE FIFTH */\n#define XK_twofifths                     0x0ab3  /* U+2156 VULGAR FRACTION TWO FIFTHS */\n#define XK_threefifths                   0x0ab4  /* U+2157 VULGAR FRACTION THREE FIFTHS */\n#define XK_fourfifths                    0x0ab5  /* U+2158 VULGAR FRACTION FOUR FIFTHS */\n#define XK_onesixth                      0x0ab6  /* U+2159 VULGAR FRACTION ONE SIXTH */\n#define XK_fivesixths                    0x0ab7  /* U+215A VULGAR FRACTION FIVE SIXTHS */\n#define XK_careof                        0x0ab8  /* U+2105 CARE OF */\n#define XK_figdash                       0x0abb  /* U+2012 FIGURE DASH */\n#define XK_leftanglebracket              0x0abc  /*(U+2329 LEFT-POINTING ANGLE BRACKET)*/\n#define XK_decimalpoint                  0x0abd  /*(U+002E FULL STOP)*/\n#define XK_rightanglebracket             0x0abe  /*(U+232A RIGHT-POINTING ANGLE BRACKET)*/\n#define XK_marker                        0x0abf\n#define XK_oneeighth                     0x0ac3  /* U+215B VULGAR FRACTION ONE EIGHTH */\n#define XK_threeeighths                  0x0ac4  /* U+215C VULGAR FRACTION THREE EIGHTHS */\n#define XK_fiveeighths                   0x0ac5  /* U+215D VULGAR FRACTION FIVE EIGHTHS */\n#define XK_seveneighths                  0x0ac6  /* U+215E VULGAR FRACTION SEVEN EIGHTHS */\n#define XK_trademark                     0x0ac9  /* U+2122 TRADE MARK SIGN */\n#define XK_signaturemark                 0x0aca  /*(U+2613 SALTIRE)*/\n#define XK_trademarkincircle             0x0acb\n#define XK_leftopentriangle              0x0acc  /*(U+25C1 WHITE LEFT-POINTING TRIANGLE)*/\n#define XK_rightopentriangle             0x0acd  /*(U+25B7 WHITE RIGHT-POINTING TRIANGLE)*/\n#define XK_emopencircle                  0x0ace  /*(U+25CB WHITE CIRCLE)*/\n#define XK_emopenrectangle               0x0acf  /*(U+25AF WHITE VERTICAL RECTANGLE)*/\n#define XK_leftsinglequotemark           0x0ad0  /* U+2018 LEFT SINGLE QUOTATION MARK */\n#define XK_rightsinglequotemark          0x0ad1  /* U+2019 RIGHT SINGLE QUOTATION MARK */\n#define XK_leftdoublequotemark           0x0ad2  /* U+201C LEFT DOUBLE QUOTATION MARK */\n#define XK_rightdoublequotemark          0x0ad3  /* U+201D RIGHT DOUBLE QUOTATION MARK */\n#define XK_prescription                  0x0ad4  /* U+211E PRESCRIPTION TAKE */\n#define XK_permille                      0x0ad5  /* U+2030 PER MILLE SIGN */\n#define XK_minutes                       0x0ad6  /* U+2032 PRIME */\n#define XK_seconds                       0x0ad7  /* U+2033 DOUBLE PRIME */\n#define XK_latincross                    0x0ad9  /* U+271D LATIN CROSS */\n#define XK_hexagram                      0x0ada\n#define XK_filledrectbullet              0x0adb  /*(U+25AC BLACK RECTANGLE)*/\n#define XK_filledlefttribullet           0x0adc  /*(U+25C0 BLACK LEFT-POINTING TRIANGLE)*/\n#define XK_filledrighttribullet          0x0add  /*(U+25B6 BLACK RIGHT-POINTING TRIANGLE)*/\n#define XK_emfilledcircle                0x0ade  /*(U+25CF BLACK CIRCLE)*/\n#define XK_emfilledrect                  0x0adf  /*(U+25AE BLACK VERTICAL RECTANGLE)*/\n#define XK_enopencircbullet              0x0ae0  /*(U+25E6 WHITE BULLET)*/\n#define XK_enopensquarebullet            0x0ae1  /*(U+25AB WHITE SMALL SQUARE)*/\n#define XK_openrectbullet                0x0ae2  /*(U+25AD WHITE RECTANGLE)*/\n#define XK_opentribulletup               0x0ae3  /*(U+25B3 WHITE UP-POINTING TRIANGLE)*/\n#define XK_opentribulletdown             0x0ae4  /*(U+25BD WHITE DOWN-POINTING TRIANGLE)*/\n#define XK_openstar                      0x0ae5  /*(U+2606 WHITE STAR)*/\n#define XK_enfilledcircbullet            0x0ae6  /*(U+2022 BULLET)*/\n#define XK_enfilledsqbullet              0x0ae7  /*(U+25AA BLACK SMALL SQUARE)*/\n#define XK_filledtribulletup             0x0ae8  /*(U+25B2 BLACK UP-POINTING TRIANGLE)*/\n#define XK_filledtribulletdown           0x0ae9  /*(U+25BC BLACK DOWN-POINTING TRIANGLE)*/\n#define XK_leftpointer                   0x0aea  /*(U+261C WHITE LEFT POINTING INDEX)*/\n#define XK_rightpointer                  0x0aeb  /*(U+261E WHITE RIGHT POINTING INDEX)*/\n#define XK_club                          0x0aec  /* U+2663 BLACK CLUB SUIT */\n#define XK_diamond                       0x0aed  /* U+2666 BLACK DIAMOND SUIT */\n#define XK_heart                         0x0aee  /* U+2665 BLACK HEART SUIT */\n#define XK_maltesecross                  0x0af0  /* U+2720 MALTESE CROSS */\n#define XK_dagger                        0x0af1  /* U+2020 DAGGER */\n#define XK_doubledagger                  0x0af2  /* U+2021 DOUBLE DAGGER */\n#define XK_checkmark                     0x0af3  /* U+2713 CHECK MARK */\n#define XK_ballotcross                   0x0af4  /* U+2717 BALLOT X */\n#define XK_musicalsharp                  0x0af5  /* U+266F MUSIC SHARP SIGN */\n#define XK_musicalflat                   0x0af6  /* U+266D MUSIC FLAT SIGN */\n#define XK_malesymbol                    0x0af7  /* U+2642 MALE SIGN */\n#define XK_femalesymbol                  0x0af8  /* U+2640 FEMALE SIGN */\n#define XK_telephone                     0x0af9  /* U+260E BLACK TELEPHONE */\n#define XK_telephonerecorder             0x0afa  /* U+2315 TELEPHONE RECORDER */\n#define XK_phonographcopyright           0x0afb  /* U+2117 SOUND RECORDING COPYRIGHT */\n#define XK_caret                         0x0afc  /* U+2038 CARET */\n#define XK_singlelowquotemark            0x0afd  /* U+201A SINGLE LOW-9 QUOTATION MARK */\n#define XK_doublelowquotemark            0x0afe  /* U+201E DOUBLE LOW-9 QUOTATION MARK */\n#define XK_cursor                        0x0aff\n#endif /* XK_PUBLISHING */\n\n/*\n * APL\n * Byte 3 = 0x0b\n */\n\n#ifdef XK_APL\n#define XK_leftcaret                     0x0ba3  /*(U+003C LESS-THAN SIGN)*/\n#define XK_rightcaret                    0x0ba6  /*(U+003E GREATER-THAN SIGN)*/\n#define XK_downcaret                     0x0ba8  /*(U+2228 LOGICAL OR)*/\n#define XK_upcaret                       0x0ba9  /*(U+2227 LOGICAL AND)*/\n#define XK_overbar                       0x0bc0  /*(U+00AF MACRON)*/\n#define XK_downtack                      0x0bc2  /* U+22A4 DOWN TACK */\n#define XK_upshoe                        0x0bc3  /*(U+2229 INTERSECTION)*/\n#define XK_downstile                     0x0bc4  /* U+230A LEFT FLOOR */\n#define XK_underbar                      0x0bc6  /*(U+005F LOW LINE)*/\n#define XK_jot                           0x0bca  /* U+2218 RING OPERATOR */\n#define XK_quad                          0x0bcc  /* U+2395 APL FUNCTIONAL SYMBOL QUAD */\n#define XK_uptack                        0x0bce  /* U+22A5 UP TACK */\n#define XK_circle                        0x0bcf  /* U+25CB WHITE CIRCLE */\n#define XK_upstile                       0x0bd3  /* U+2308 LEFT CEILING */\n#define XK_downshoe                      0x0bd6  /*(U+222A UNION)*/\n#define XK_rightshoe                     0x0bd8  /*(U+2283 SUPERSET OF)*/\n#define XK_leftshoe                      0x0bda  /*(U+2282 SUBSET OF)*/\n#define XK_lefttack                      0x0bdc  /* U+22A3 LEFT TACK */\n#define XK_righttack                     0x0bfc  /* U+22A2 RIGHT TACK */\n#endif /* XK_APL */\n\n/*\n * Hebrew\n * Byte 3 = 0x0c\n */\n\n#ifdef XK_HEBREW\n#define XK_hebrew_doublelowline          0x0cdf  /* U+2017 DOUBLE LOW LINE */\n#define XK_hebrew_aleph                  0x0ce0  /* U+05D0 HEBREW LETTER ALEF */\n#define XK_hebrew_bet                    0x0ce1  /* U+05D1 HEBREW LETTER BET */\n#define XK_hebrew_beth                   0x0ce1  /* deprecated */\n#define XK_hebrew_gimel                  0x0ce2  /* U+05D2 HEBREW LETTER GIMEL */\n#define XK_hebrew_gimmel                 0x0ce2  /* deprecated */\n#define XK_hebrew_dalet                  0x0ce3  /* U+05D3 HEBREW LETTER DALET */\n#define XK_hebrew_daleth                 0x0ce3  /* deprecated */\n#define XK_hebrew_he                     0x0ce4  /* U+05D4 HEBREW LETTER HE */\n#define XK_hebrew_waw                    0x0ce5  /* U+05D5 HEBREW LETTER VAV */\n#define XK_hebrew_zain                   0x0ce6  /* U+05D6 HEBREW LETTER ZAYIN */\n#define XK_hebrew_zayin                  0x0ce6  /* deprecated */\n#define XK_hebrew_chet                   0x0ce7  /* U+05D7 HEBREW LETTER HET */\n#define XK_hebrew_het                    0x0ce7  /* deprecated */\n#define XK_hebrew_tet                    0x0ce8  /* U+05D8 HEBREW LETTER TET */\n#define XK_hebrew_teth                   0x0ce8  /* deprecated */\n#define XK_hebrew_yod                    0x0ce9  /* U+05D9 HEBREW LETTER YOD */\n#define XK_hebrew_finalkaph              0x0cea  /* U+05DA HEBREW LETTER FINAL KAF */\n#define XK_hebrew_kaph                   0x0ceb  /* U+05DB HEBREW LETTER KAF */\n#define XK_hebrew_lamed                  0x0cec  /* U+05DC HEBREW LETTER LAMED */\n#define XK_hebrew_finalmem               0x0ced  /* U+05DD HEBREW LETTER FINAL MEM */\n#define XK_hebrew_mem                    0x0cee  /* U+05DE HEBREW LETTER MEM */\n#define XK_hebrew_finalnun               0x0cef  /* U+05DF HEBREW LETTER FINAL NUN */\n#define XK_hebrew_nun                    0x0cf0  /* U+05E0 HEBREW LETTER NUN */\n#define XK_hebrew_samech                 0x0cf1  /* U+05E1 HEBREW LETTER SAMEKH */\n#define XK_hebrew_samekh                 0x0cf1  /* deprecated */\n#define XK_hebrew_ayin                   0x0cf2  /* U+05E2 HEBREW LETTER AYIN */\n#define XK_hebrew_finalpe                0x0cf3  /* U+05E3 HEBREW LETTER FINAL PE */\n#define XK_hebrew_pe                     0x0cf4  /* U+05E4 HEBREW LETTER PE */\n#define XK_hebrew_finalzade              0x0cf5  /* U+05E5 HEBREW LETTER FINAL TSADI */\n#define XK_hebrew_finalzadi              0x0cf5  /* deprecated */\n#define XK_hebrew_zade                   0x0cf6  /* U+05E6 HEBREW LETTER TSADI */\n#define XK_hebrew_zadi                   0x0cf6  /* deprecated */\n#define XK_hebrew_qoph                   0x0cf7  /* U+05E7 HEBREW LETTER QOF */\n#define XK_hebrew_kuf                    0x0cf7  /* deprecated */\n#define XK_hebrew_resh                   0x0cf8  /* U+05E8 HEBREW LETTER RESH */\n#define XK_hebrew_shin                   0x0cf9  /* U+05E9 HEBREW LETTER SHIN */\n#define XK_hebrew_taw                    0x0cfa  /* U+05EA HEBREW LETTER TAV */\n#define XK_hebrew_taf                    0x0cfa  /* deprecated */\n#define XK_Hebrew_switch                 0xff7e  /* Alias for Mode_switch */\n#endif /* XK_HEBREW */\n\n/*\n * Thai\n * Byte 3 = 0x0d\n */\n\n#ifdef XK_THAI\n#define XK_Thai_kokai                    0x0da1  /* U+0E01 THAI CHARACTER KO KAI */\n#define XK_Thai_khokhai                  0x0da2  /* U+0E02 THAI CHARACTER KHO KHAI */\n#define XK_Thai_khokhuat                 0x0da3  /* U+0E03 THAI CHARACTER KHO KHUAT */\n#define XK_Thai_khokhwai                 0x0da4  /* U+0E04 THAI CHARACTER KHO KHWAI */\n#define XK_Thai_khokhon                  0x0da5  /* U+0E05 THAI CHARACTER KHO KHON */\n#define XK_Thai_khorakhang               0x0da6  /* U+0E06 THAI CHARACTER KHO RAKHANG */\n#define XK_Thai_ngongu                   0x0da7  /* U+0E07 THAI CHARACTER NGO NGU */\n#define XK_Thai_chochan                  0x0da8  /* U+0E08 THAI CHARACTER CHO CHAN */\n#define XK_Thai_choching                 0x0da9  /* U+0E09 THAI CHARACTER CHO CHING */\n#define XK_Thai_chochang                 0x0daa  /* U+0E0A THAI CHARACTER CHO CHANG */\n#define XK_Thai_soso                     0x0dab  /* U+0E0B THAI CHARACTER SO SO */\n#define XK_Thai_chochoe                  0x0dac  /* U+0E0C THAI CHARACTER CHO CHOE */\n#define XK_Thai_yoying                   0x0dad  /* U+0E0D THAI CHARACTER YO YING */\n#define XK_Thai_dochada                  0x0dae  /* U+0E0E THAI CHARACTER DO CHADA */\n#define XK_Thai_topatak                  0x0daf  /* U+0E0F THAI CHARACTER TO PATAK */\n#define XK_Thai_thothan                  0x0db0  /* U+0E10 THAI CHARACTER THO THAN */\n#define XK_Thai_thonangmontho            0x0db1  /* U+0E11 THAI CHARACTER THO NANGMONTHO */\n#define XK_Thai_thophuthao               0x0db2  /* U+0E12 THAI CHARACTER THO PHUTHAO */\n#define XK_Thai_nonen                    0x0db3  /* U+0E13 THAI CHARACTER NO NEN */\n#define XK_Thai_dodek                    0x0db4  /* U+0E14 THAI CHARACTER DO DEK */\n#define XK_Thai_totao                    0x0db5  /* U+0E15 THAI CHARACTER TO TAO */\n#define XK_Thai_thothung                 0x0db6  /* U+0E16 THAI CHARACTER THO THUNG */\n#define XK_Thai_thothahan                0x0db7  /* U+0E17 THAI CHARACTER THO THAHAN */\n#define XK_Thai_thothong                 0x0db8  /* U+0E18 THAI CHARACTER THO THONG */\n#define XK_Thai_nonu                     0x0db9  /* U+0E19 THAI CHARACTER NO NU */\n#define XK_Thai_bobaimai                 0x0dba  /* U+0E1A THAI CHARACTER BO BAIMAI */\n#define XK_Thai_popla                    0x0dbb  /* U+0E1B THAI CHARACTER PO PLA */\n#define XK_Thai_phophung                 0x0dbc  /* U+0E1C THAI CHARACTER PHO PHUNG */\n#define XK_Thai_fofa                     0x0dbd  /* U+0E1D THAI CHARACTER FO FA */\n#define XK_Thai_phophan                  0x0dbe  /* U+0E1E THAI CHARACTER PHO PHAN */\n#define XK_Thai_fofan                    0x0dbf  /* U+0E1F THAI CHARACTER FO FAN */\n#define XK_Thai_phosamphao               0x0dc0  /* U+0E20 THAI CHARACTER PHO SAMPHAO */\n#define XK_Thai_moma                     0x0dc1  /* U+0E21 THAI CHARACTER MO MA */\n#define XK_Thai_yoyak                    0x0dc2  /* U+0E22 THAI CHARACTER YO YAK */\n#define XK_Thai_rorua                    0x0dc3  /* U+0E23 THAI CHARACTER RO RUA */\n#define XK_Thai_ru                       0x0dc4  /* U+0E24 THAI CHARACTER RU */\n#define XK_Thai_loling                   0x0dc5  /* U+0E25 THAI CHARACTER LO LING */\n#define XK_Thai_lu                       0x0dc6  /* U+0E26 THAI CHARACTER LU */\n#define XK_Thai_wowaen                   0x0dc7  /* U+0E27 THAI CHARACTER WO WAEN */\n#define XK_Thai_sosala                   0x0dc8  /* U+0E28 THAI CHARACTER SO SALA */\n#define XK_Thai_sorusi                   0x0dc9  /* U+0E29 THAI CHARACTER SO RUSI */\n#define XK_Thai_sosua                    0x0dca  /* U+0E2A THAI CHARACTER SO SUA */\n#define XK_Thai_hohip                    0x0dcb  /* U+0E2B THAI CHARACTER HO HIP */\n#define XK_Thai_lochula                  0x0dcc  /* U+0E2C THAI CHARACTER LO CHULA */\n#define XK_Thai_oang                     0x0dcd  /* U+0E2D THAI CHARACTER O ANG */\n#define XK_Thai_honokhuk                 0x0dce  /* U+0E2E THAI CHARACTER HO NOKHUK */\n#define XK_Thai_paiyannoi                0x0dcf  /* U+0E2F THAI CHARACTER PAIYANNOI */\n#define XK_Thai_saraa                    0x0dd0  /* U+0E30 THAI CHARACTER SARA A */\n#define XK_Thai_maihanakat               0x0dd1  /* U+0E31 THAI CHARACTER MAI HAN-AKAT */\n#define XK_Thai_saraaa                   0x0dd2  /* U+0E32 THAI CHARACTER SARA AA */\n#define XK_Thai_saraam                   0x0dd3  /* U+0E33 THAI CHARACTER SARA AM */\n#define XK_Thai_sarai                    0x0dd4  /* U+0E34 THAI CHARACTER SARA I */\n#define XK_Thai_saraii                   0x0dd5  /* U+0E35 THAI CHARACTER SARA II */\n#define XK_Thai_saraue                   0x0dd6  /* U+0E36 THAI CHARACTER SARA UE */\n#define XK_Thai_sarauee                  0x0dd7  /* U+0E37 THAI CHARACTER SARA UEE */\n#define XK_Thai_sarau                    0x0dd8  /* U+0E38 THAI CHARACTER SARA U */\n#define XK_Thai_sarauu                   0x0dd9  /* U+0E39 THAI CHARACTER SARA UU */\n#define XK_Thai_phinthu                  0x0dda  /* U+0E3A THAI CHARACTER PHINTHU */\n#define XK_Thai_maihanakat_maitho        0x0dde  /*(U+0E3E Unassigned code point)*/\n#define XK_Thai_baht                     0x0ddf  /* U+0E3F THAI CURRENCY SYMBOL BAHT */\n#define XK_Thai_sarae                    0x0de0  /* U+0E40 THAI CHARACTER SARA E */\n#define XK_Thai_saraae                   0x0de1  /* U+0E41 THAI CHARACTER SARA AE */\n#define XK_Thai_sarao                    0x0de2  /* U+0E42 THAI CHARACTER SARA O */\n#define XK_Thai_saraaimaimuan            0x0de3  /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */\n#define XK_Thai_saraaimaimalai           0x0de4  /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */\n#define XK_Thai_lakkhangyao              0x0de5  /* U+0E45 THAI CHARACTER LAKKHANGYAO */\n#define XK_Thai_maiyamok                 0x0de6  /* U+0E46 THAI CHARACTER MAIYAMOK */\n#define XK_Thai_maitaikhu                0x0de7  /* U+0E47 THAI CHARACTER MAITAIKHU */\n#define XK_Thai_maiek                    0x0de8  /* U+0E48 THAI CHARACTER MAI EK */\n#define XK_Thai_maitho                   0x0de9  /* U+0E49 THAI CHARACTER MAI THO */\n#define XK_Thai_maitri                   0x0dea  /* U+0E4A THAI CHARACTER MAI TRI */\n#define XK_Thai_maichattawa              0x0deb  /* U+0E4B THAI CHARACTER MAI CHATTAWA */\n#define XK_Thai_thanthakhat              0x0dec  /* U+0E4C THAI CHARACTER THANTHAKHAT */\n#define XK_Thai_nikhahit                 0x0ded  /* U+0E4D THAI CHARACTER NIKHAHIT */\n#define XK_Thai_leksun                   0x0df0  /* U+0E50 THAI DIGIT ZERO */\n#define XK_Thai_leknung                  0x0df1  /* U+0E51 THAI DIGIT ONE */\n#define XK_Thai_leksong                  0x0df2  /* U+0E52 THAI DIGIT TWO */\n#define XK_Thai_leksam                   0x0df3  /* U+0E53 THAI DIGIT THREE */\n#define XK_Thai_leksi                    0x0df4  /* U+0E54 THAI DIGIT FOUR */\n#define XK_Thai_lekha                    0x0df5  /* U+0E55 THAI DIGIT FIVE */\n#define XK_Thai_lekhok                   0x0df6  /* U+0E56 THAI DIGIT SIX */\n#define XK_Thai_lekchet                  0x0df7  /* U+0E57 THAI DIGIT SEVEN */\n#define XK_Thai_lekpaet                  0x0df8  /* U+0E58 THAI DIGIT EIGHT */\n#define XK_Thai_lekkao                   0x0df9  /* U+0E59 THAI DIGIT NINE */\n#endif /* XK_THAI */\n\n/*\n * Korean\n * Byte 3 = 0x0e\n */\n\n#ifdef XK_KOREAN\n\n#define XK_Hangul                        0xff31  /* Hangul start/stop(toggle) */\n#define XK_Hangul_Start                  0xff32  /* Hangul start */\n#define XK_Hangul_End                    0xff33  /* Hangul end, English start */\n#define XK_Hangul_Hanja                  0xff34  /* Start Hangul->Hanja Conversion */\n#define XK_Hangul_Jamo                   0xff35  /* Hangul Jamo mode */\n#define XK_Hangul_Romaja                 0xff36  /* Hangul Romaja mode */\n#define XK_Hangul_Codeinput              0xff37  /* Hangul code input mode */\n#define XK_Hangul_Jeonja                 0xff38  /* Jeonja mode */\n#define XK_Hangul_Banja                  0xff39  /* Banja mode */\n#define XK_Hangul_PreHanja               0xff3a  /* Pre Hanja conversion */\n#define XK_Hangul_PostHanja              0xff3b  /* Post Hanja conversion */\n#define XK_Hangul_SingleCandidate        0xff3c  /* Single candidate */\n#define XK_Hangul_MultipleCandidate      0xff3d  /* Multiple candidate */\n#define XK_Hangul_PreviousCandidate      0xff3e  /* Previous candidate */\n#define XK_Hangul_Special                0xff3f  /* Special symbols */\n#define XK_Hangul_switch                 0xff7e  /* Alias for Mode_switch */\n\n/* Hangul Consonant Characters */\n#define XK_Hangul_Kiyeog                 0x0ea1  /* U+3131 HANGUL LETTER KIYEOK */\n#define XK_Hangul_SsangKiyeog            0x0ea2  /* U+3132 HANGUL LETTER SSANGKIYEOK */\n#define XK_Hangul_KiyeogSios             0x0ea3  /* U+3133 HANGUL LETTER KIYEOK-SIOS */\n#define XK_Hangul_Nieun                  0x0ea4  /* U+3134 HANGUL LETTER NIEUN */\n#define XK_Hangul_NieunJieuj             0x0ea5  /* U+3135 HANGUL LETTER NIEUN-CIEUC */\n#define XK_Hangul_NieunHieuh             0x0ea6  /* U+3136 HANGUL LETTER NIEUN-HIEUH */\n#define XK_Hangul_Dikeud                 0x0ea7  /* U+3137 HANGUL LETTER TIKEUT */\n#define XK_Hangul_SsangDikeud            0x0ea8  /* U+3138 HANGUL LETTER SSANGTIKEUT */\n#define XK_Hangul_Rieul                  0x0ea9  /* U+3139 HANGUL LETTER RIEUL */\n#define XK_Hangul_RieulKiyeog            0x0eaa  /* U+313A HANGUL LETTER RIEUL-KIYEOK */\n#define XK_Hangul_RieulMieum             0x0eab  /* U+313B HANGUL LETTER RIEUL-MIEUM */\n#define XK_Hangul_RieulPieub             0x0eac  /* U+313C HANGUL LETTER RIEUL-PIEUP */\n#define XK_Hangul_RieulSios              0x0ead  /* U+313D HANGUL LETTER RIEUL-SIOS */\n#define XK_Hangul_RieulTieut             0x0eae  /* U+313E HANGUL LETTER RIEUL-THIEUTH */\n#define XK_Hangul_RieulPhieuf            0x0eaf  /* U+313F HANGUL LETTER RIEUL-PHIEUPH */\n#define XK_Hangul_RieulHieuh             0x0eb0  /* U+3140 HANGUL LETTER RIEUL-HIEUH */\n#define XK_Hangul_Mieum                  0x0eb1  /* U+3141 HANGUL LETTER MIEUM */\n#define XK_Hangul_Pieub                  0x0eb2  /* U+3142 HANGUL LETTER PIEUP */\n#define XK_Hangul_SsangPieub             0x0eb3  /* U+3143 HANGUL LETTER SSANGPIEUP */\n#define XK_Hangul_PieubSios              0x0eb4  /* U+3144 HANGUL LETTER PIEUP-SIOS */\n#define XK_Hangul_Sios                   0x0eb5  /* U+3145 HANGUL LETTER SIOS */\n#define XK_Hangul_SsangSios              0x0eb6  /* U+3146 HANGUL LETTER SSANGSIOS */\n#define XK_Hangul_Ieung                  0x0eb7  /* U+3147 HANGUL LETTER IEUNG */\n#define XK_Hangul_Jieuj                  0x0eb8  /* U+3148 HANGUL LETTER CIEUC */\n#define XK_Hangul_SsangJieuj             0x0eb9  /* U+3149 HANGUL LETTER SSANGCIEUC */\n#define XK_Hangul_Cieuc                  0x0eba  /* U+314A HANGUL LETTER CHIEUCH */\n#define XK_Hangul_Khieuq                 0x0ebb  /* U+314B HANGUL LETTER KHIEUKH */\n#define XK_Hangul_Tieut                  0x0ebc  /* U+314C HANGUL LETTER THIEUTH */\n#define XK_Hangul_Phieuf                 0x0ebd  /* U+314D HANGUL LETTER PHIEUPH */\n#define XK_Hangul_Hieuh                  0x0ebe  /* U+314E HANGUL LETTER HIEUH */\n\n/* Hangul Vowel Characters */\n#define XK_Hangul_A                      0x0ebf  /* U+314F HANGUL LETTER A */\n#define XK_Hangul_AE                     0x0ec0  /* U+3150 HANGUL LETTER AE */\n#define XK_Hangul_YA                     0x0ec1  /* U+3151 HANGUL LETTER YA */\n#define XK_Hangul_YAE                    0x0ec2  /* U+3152 HANGUL LETTER YAE */\n#define XK_Hangul_EO                     0x0ec3  /* U+3153 HANGUL LETTER EO */\n#define XK_Hangul_E                      0x0ec4  /* U+3154 HANGUL LETTER E */\n#define XK_Hangul_YEO                    0x0ec5  /* U+3155 HANGUL LETTER YEO */\n#define XK_Hangul_YE                     0x0ec6  /* U+3156 HANGUL LETTER YE */\n#define XK_Hangul_O                      0x0ec7  /* U+3157 HANGUL LETTER O */\n#define XK_Hangul_WA                     0x0ec8  /* U+3158 HANGUL LETTER WA */\n#define XK_Hangul_WAE                    0x0ec9  /* U+3159 HANGUL LETTER WAE */\n#define XK_Hangul_OE                     0x0eca  /* U+315A HANGUL LETTER OE */\n#define XK_Hangul_YO                     0x0ecb  /* U+315B HANGUL LETTER YO */\n#define XK_Hangul_U                      0x0ecc  /* U+315C HANGUL LETTER U */\n#define XK_Hangul_WEO                    0x0ecd  /* U+315D HANGUL LETTER WEO */\n#define XK_Hangul_WE                     0x0ece  /* U+315E HANGUL LETTER WE */\n#define XK_Hangul_WI                     0x0ecf  /* U+315F HANGUL LETTER WI */\n#define XK_Hangul_YU                     0x0ed0  /* U+3160 HANGUL LETTER YU */\n#define XK_Hangul_EU                     0x0ed1  /* U+3161 HANGUL LETTER EU */\n#define XK_Hangul_YI                     0x0ed2  /* U+3162 HANGUL LETTER YI */\n#define XK_Hangul_I                      0x0ed3  /* U+3163 HANGUL LETTER I */\n\n/* Hangul syllable-final (JongSeong) Characters */\n#define XK_Hangul_J_Kiyeog               0x0ed4  /* U+11A8 HANGUL JONGSEONG KIYEOK */\n#define XK_Hangul_J_SsangKiyeog          0x0ed5  /* U+11A9 HANGUL JONGSEONG SSANGKIYEOK */\n#define XK_Hangul_J_KiyeogSios           0x0ed6  /* U+11AA HANGUL JONGSEONG KIYEOK-SIOS */\n#define XK_Hangul_J_Nieun                0x0ed7  /* U+11AB HANGUL JONGSEONG NIEUN */\n#define XK_Hangul_J_NieunJieuj           0x0ed8  /* U+11AC HANGUL JONGSEONG NIEUN-CIEUC */\n#define XK_Hangul_J_NieunHieuh           0x0ed9  /* U+11AD HANGUL JONGSEONG NIEUN-HIEUH */\n#define XK_Hangul_J_Dikeud               0x0eda  /* U+11AE HANGUL JONGSEONG TIKEUT */\n#define XK_Hangul_J_Rieul                0x0edb  /* U+11AF HANGUL JONGSEONG RIEUL */\n#define XK_Hangul_J_RieulKiyeog          0x0edc  /* U+11B0 HANGUL JONGSEONG RIEUL-KIYEOK */\n#define XK_Hangul_J_RieulMieum           0x0edd  /* U+11B1 HANGUL JONGSEONG RIEUL-MIEUM */\n#define XK_Hangul_J_RieulPieub           0x0ede  /* U+11B2 HANGUL JONGSEONG RIEUL-PIEUP */\n#define XK_Hangul_J_RieulSios            0x0edf  /* U+11B3 HANGUL JONGSEONG RIEUL-SIOS */\n#define XK_Hangul_J_RieulTieut           0x0ee0  /* U+11B4 HANGUL JONGSEONG RIEUL-THIEUTH */\n#define XK_Hangul_J_RieulPhieuf          0x0ee1  /* U+11B5 HANGUL JONGSEONG RIEUL-PHIEUPH */\n#define XK_Hangul_J_RieulHieuh           0x0ee2  /* U+11B6 HANGUL JONGSEONG RIEUL-HIEUH */\n#define XK_Hangul_J_Mieum                0x0ee3  /* U+11B7 HANGUL JONGSEONG MIEUM */\n#define XK_Hangul_J_Pieub                0x0ee4  /* U+11B8 HANGUL JONGSEONG PIEUP */\n#define XK_Hangul_J_PieubSios            0x0ee5  /* U+11B9 HANGUL JONGSEONG PIEUP-SIOS */\n#define XK_Hangul_J_Sios                 0x0ee6  /* U+11BA HANGUL JONGSEONG SIOS */\n#define XK_Hangul_J_SsangSios            0x0ee7  /* U+11BB HANGUL JONGSEONG SSANGSIOS */\n#define XK_Hangul_J_Ieung                0x0ee8  /* U+11BC HANGUL JONGSEONG IEUNG */\n#define XK_Hangul_J_Jieuj                0x0ee9  /* U+11BD HANGUL JONGSEONG CIEUC */\n#define XK_Hangul_J_Cieuc                0x0eea  /* U+11BE HANGUL JONGSEONG CHIEUCH */\n#define XK_Hangul_J_Khieuq               0x0eeb  /* U+11BF HANGUL JONGSEONG KHIEUKH */\n#define XK_Hangul_J_Tieut                0x0eec  /* U+11C0 HANGUL JONGSEONG THIEUTH */\n#define XK_Hangul_J_Phieuf               0x0eed  /* U+11C1 HANGUL JONGSEONG PHIEUPH */\n#define XK_Hangul_J_Hieuh                0x0eee  /* U+11C2 HANGUL JONGSEONG HIEUH */\n\n/* Ancient Hangul Consonant Characters */\n#define XK_Hangul_RieulYeorinHieuh       0x0eef  /* U+316D HANGUL LETTER RIEUL-YEORINHIEUH */\n#define XK_Hangul_SunkyeongeumMieum      0x0ef0  /* U+3171 HANGUL LETTER KAPYEOUNMIEUM */\n#define XK_Hangul_SunkyeongeumPieub      0x0ef1  /* U+3178 HANGUL LETTER KAPYEOUNPIEUP */\n#define XK_Hangul_PanSios                0x0ef2  /* U+317F HANGUL LETTER PANSIOS */\n#define XK_Hangul_KkogjiDalrinIeung      0x0ef3  /* U+3181 HANGUL LETTER YESIEUNG */\n#define XK_Hangul_SunkyeongeumPhieuf     0x0ef4  /* U+3184 HANGUL LETTER KAPYEOUNPHIEUPH */\n#define XK_Hangul_YeorinHieuh            0x0ef5  /* U+3186 HANGUL LETTER YEORINHIEUH */\n\n/* Ancient Hangul Vowel Characters */\n#define XK_Hangul_AraeA                  0x0ef6  /* U+318D HANGUL LETTER ARAEA */\n#define XK_Hangul_AraeAE                 0x0ef7  /* U+318E HANGUL LETTER ARAEAE */\n\n/* Ancient Hangul syllable-final (JongSeong) Characters */\n#define XK_Hangul_J_PanSios              0x0ef8  /* U+11EB HANGUL JONGSEONG PANSIOS */\n#define XK_Hangul_J_KkogjiDalrinIeung    0x0ef9  /* U+11F0 HANGUL JONGSEONG YESIEUNG */\n#define XK_Hangul_J_YeorinHieuh          0x0efa  /* U+11F9 HANGUL JONGSEONG YEORINHIEUH */\n\n/* Korean currency symbol */\n#define XK_Korean_Won                    0x0eff  /*(U+20A9 WON SIGN)*/\n\n#endif /* XK_KOREAN */\n\n/*\n * Armenian\n */\n\n#ifdef XK_ARMENIAN\n#define XK_Armenian_ligature_ew       0x1000587  /* U+0587 ARMENIAN SMALL LIGATURE ECH YIWN */\n#define XK_Armenian_full_stop         0x1000589  /* U+0589 ARMENIAN FULL STOP */\n#define XK_Armenian_verjaket          0x1000589  /* deprecated alias for Armenian_full_stop */\n#define XK_Armenian_separation_mark   0x100055d  /* U+055D ARMENIAN COMMA */\n#define XK_Armenian_but               0x100055d  /* deprecated alias for Armenian_separation_mark */\n#define XK_Armenian_hyphen            0x100058a  /* U+058A ARMENIAN HYPHEN */\n#define XK_Armenian_yentamna          0x100058a  /* deprecated alias for Armenian_hyphen */\n#define XK_Armenian_exclam            0x100055c  /* U+055C ARMENIAN EXCLAMATION MARK */\n#define XK_Armenian_amanak            0x100055c  /* deprecated alias for Armenian_exclam */\n#define XK_Armenian_accent            0x100055b  /* U+055B ARMENIAN EMPHASIS MARK */\n#define XK_Armenian_shesht            0x100055b  /* deprecated alias for Armenian_accent */\n#define XK_Armenian_question          0x100055e  /* U+055E ARMENIAN QUESTION MARK */\n#define XK_Armenian_paruyk            0x100055e  /* deprecated alias for Armenian_question */\n#define XK_Armenian_AYB               0x1000531  /* U+0531 ARMENIAN CAPITAL LETTER AYB */\n#define XK_Armenian_ayb               0x1000561  /* U+0561 ARMENIAN SMALL LETTER AYB */\n#define XK_Armenian_BEN               0x1000532  /* U+0532 ARMENIAN CAPITAL LETTER BEN */\n#define XK_Armenian_ben               0x1000562  /* U+0562 ARMENIAN SMALL LETTER BEN */\n#define XK_Armenian_GIM               0x1000533  /* U+0533 ARMENIAN CAPITAL LETTER GIM */\n#define XK_Armenian_gim               0x1000563  /* U+0563 ARMENIAN SMALL LETTER GIM */\n#define XK_Armenian_DA                0x1000534  /* U+0534 ARMENIAN CAPITAL LETTER DA */\n#define XK_Armenian_da                0x1000564  /* U+0564 ARMENIAN SMALL LETTER DA */\n#define XK_Armenian_YECH              0x1000535  /* U+0535 ARMENIAN CAPITAL LETTER ECH */\n#define XK_Armenian_yech              0x1000565  /* U+0565 ARMENIAN SMALL LETTER ECH */\n#define XK_Armenian_ZA                0x1000536  /* U+0536 ARMENIAN CAPITAL LETTER ZA */\n#define XK_Armenian_za                0x1000566  /* U+0566 ARMENIAN SMALL LETTER ZA */\n#define XK_Armenian_E                 0x1000537  /* U+0537 ARMENIAN CAPITAL LETTER EH */\n#define XK_Armenian_e                 0x1000567  /* U+0567 ARMENIAN SMALL LETTER EH */\n#define XK_Armenian_AT                0x1000538  /* U+0538 ARMENIAN CAPITAL LETTER ET */\n#define XK_Armenian_at                0x1000568  /* U+0568 ARMENIAN SMALL LETTER ET */\n#define XK_Armenian_TO                0x1000539  /* U+0539 ARMENIAN CAPITAL LETTER TO */\n#define XK_Armenian_to                0x1000569  /* U+0569 ARMENIAN SMALL LETTER TO */\n#define XK_Armenian_ZHE               0x100053a  /* U+053A ARMENIAN CAPITAL LETTER ZHE */\n#define XK_Armenian_zhe               0x100056a  /* U+056A ARMENIAN SMALL LETTER ZHE */\n#define XK_Armenian_INI               0x100053b  /* U+053B ARMENIAN CAPITAL LETTER INI */\n#define XK_Armenian_ini               0x100056b  /* U+056B ARMENIAN SMALL LETTER INI */\n#define XK_Armenian_LYUN              0x100053c  /* U+053C ARMENIAN CAPITAL LETTER LIWN */\n#define XK_Armenian_lyun              0x100056c  /* U+056C ARMENIAN SMALL LETTER LIWN */\n#define XK_Armenian_KHE               0x100053d  /* U+053D ARMENIAN CAPITAL LETTER XEH */\n#define XK_Armenian_khe               0x100056d  /* U+056D ARMENIAN SMALL LETTER XEH */\n#define XK_Armenian_TSA               0x100053e  /* U+053E ARMENIAN CAPITAL LETTER CA */\n#define XK_Armenian_tsa               0x100056e  /* U+056E ARMENIAN SMALL LETTER CA */\n#define XK_Armenian_KEN               0x100053f  /* U+053F ARMENIAN CAPITAL LETTER KEN */\n#define XK_Armenian_ken               0x100056f  /* U+056F ARMENIAN SMALL LETTER KEN */\n#define XK_Armenian_HO                0x1000540  /* U+0540 ARMENIAN CAPITAL LETTER HO */\n#define XK_Armenian_ho                0x1000570  /* U+0570 ARMENIAN SMALL LETTER HO */\n#define XK_Armenian_DZA               0x1000541  /* U+0541 ARMENIAN CAPITAL LETTER JA */\n#define XK_Armenian_dza               0x1000571  /* U+0571 ARMENIAN SMALL LETTER JA */\n#define XK_Armenian_GHAT              0x1000542  /* U+0542 ARMENIAN CAPITAL LETTER GHAD */\n#define XK_Armenian_ghat              0x1000572  /* U+0572 ARMENIAN SMALL LETTER GHAD */\n#define XK_Armenian_TCHE              0x1000543  /* U+0543 ARMENIAN CAPITAL LETTER CHEH */\n#define XK_Armenian_tche              0x1000573  /* U+0573 ARMENIAN SMALL LETTER CHEH */\n#define XK_Armenian_MEN               0x1000544  /* U+0544 ARMENIAN CAPITAL LETTER MEN */\n#define XK_Armenian_men               0x1000574  /* U+0574 ARMENIAN SMALL LETTER MEN */\n#define XK_Armenian_HI                0x1000545  /* U+0545 ARMENIAN CAPITAL LETTER YI */\n#define XK_Armenian_hi                0x1000575  /* U+0575 ARMENIAN SMALL LETTER YI */\n#define XK_Armenian_NU                0x1000546  /* U+0546 ARMENIAN CAPITAL LETTER NOW */\n#define XK_Armenian_nu                0x1000576  /* U+0576 ARMENIAN SMALL LETTER NOW */\n#define XK_Armenian_SHA               0x1000547  /* U+0547 ARMENIAN CAPITAL LETTER SHA */\n#define XK_Armenian_sha               0x1000577  /* U+0577 ARMENIAN SMALL LETTER SHA */\n#define XK_Armenian_VO                0x1000548  /* U+0548 ARMENIAN CAPITAL LETTER VO */\n#define XK_Armenian_vo                0x1000578  /* U+0578 ARMENIAN SMALL LETTER VO */\n#define XK_Armenian_CHA               0x1000549  /* U+0549 ARMENIAN CAPITAL LETTER CHA */\n#define XK_Armenian_cha               0x1000579  /* U+0579 ARMENIAN SMALL LETTER CHA */\n#define XK_Armenian_PE                0x100054a  /* U+054A ARMENIAN CAPITAL LETTER PEH */\n#define XK_Armenian_pe                0x100057a  /* U+057A ARMENIAN SMALL LETTER PEH */\n#define XK_Armenian_JE                0x100054b  /* U+054B ARMENIAN CAPITAL LETTER JHEH */\n#define XK_Armenian_je                0x100057b  /* U+057B ARMENIAN SMALL LETTER JHEH */\n#define XK_Armenian_RA                0x100054c  /* U+054C ARMENIAN CAPITAL LETTER RA */\n#define XK_Armenian_ra                0x100057c  /* U+057C ARMENIAN SMALL LETTER RA */\n#define XK_Armenian_SE                0x100054d  /* U+054D ARMENIAN CAPITAL LETTER SEH */\n#define XK_Armenian_se                0x100057d  /* U+057D ARMENIAN SMALL LETTER SEH */\n#define XK_Armenian_VEV               0x100054e  /* U+054E ARMENIAN CAPITAL LETTER VEW */\n#define XK_Armenian_vev               0x100057e  /* U+057E ARMENIAN SMALL LETTER VEW */\n#define XK_Armenian_TYUN              0x100054f  /* U+054F ARMENIAN CAPITAL LETTER TIWN */\n#define XK_Armenian_tyun              0x100057f  /* U+057F ARMENIAN SMALL LETTER TIWN */\n#define XK_Armenian_RE                0x1000550  /* U+0550 ARMENIAN CAPITAL LETTER REH */\n#define XK_Armenian_re                0x1000580  /* U+0580 ARMENIAN SMALL LETTER REH */\n#define XK_Armenian_TSO               0x1000551  /* U+0551 ARMENIAN CAPITAL LETTER CO */\n#define XK_Armenian_tso               0x1000581  /* U+0581 ARMENIAN SMALL LETTER CO */\n#define XK_Armenian_VYUN              0x1000552  /* U+0552 ARMENIAN CAPITAL LETTER YIWN */\n#define XK_Armenian_vyun              0x1000582  /* U+0582 ARMENIAN SMALL LETTER YIWN */\n#define XK_Armenian_PYUR              0x1000553  /* U+0553 ARMENIAN CAPITAL LETTER PIWR */\n#define XK_Armenian_pyur              0x1000583  /* U+0583 ARMENIAN SMALL LETTER PIWR */\n#define XK_Armenian_KE                0x1000554  /* U+0554 ARMENIAN CAPITAL LETTER KEH */\n#define XK_Armenian_ke                0x1000584  /* U+0584 ARMENIAN SMALL LETTER KEH */\n#define XK_Armenian_O                 0x1000555  /* U+0555 ARMENIAN CAPITAL LETTER OH */\n#define XK_Armenian_o                 0x1000585  /* U+0585 ARMENIAN SMALL LETTER OH */\n#define XK_Armenian_FE                0x1000556  /* U+0556 ARMENIAN CAPITAL LETTER FEH */\n#define XK_Armenian_fe                0x1000586  /* U+0586 ARMENIAN SMALL LETTER FEH */\n#define XK_Armenian_apostrophe        0x100055a  /* U+055A ARMENIAN APOSTROPHE */\n#endif /* XK_ARMENIAN */\n\n/*\n * Georgian\n */\n\n#ifdef XK_GEORGIAN\n#define XK_Georgian_an                0x10010d0  /* U+10D0 GEORGIAN LETTER AN */\n#define XK_Georgian_ban               0x10010d1  /* U+10D1 GEORGIAN LETTER BAN */\n#define XK_Georgian_gan               0x10010d2  /* U+10D2 GEORGIAN LETTER GAN */\n#define XK_Georgian_don               0x10010d3  /* U+10D3 GEORGIAN LETTER DON */\n#define XK_Georgian_en                0x10010d4  /* U+10D4 GEORGIAN LETTER EN */\n#define XK_Georgian_vin               0x10010d5  /* U+10D5 GEORGIAN LETTER VIN */\n#define XK_Georgian_zen               0x10010d6  /* U+10D6 GEORGIAN LETTER ZEN */\n#define XK_Georgian_tan               0x10010d7  /* U+10D7 GEORGIAN LETTER TAN */\n#define XK_Georgian_in                0x10010d8  /* U+10D8 GEORGIAN LETTER IN */\n#define XK_Georgian_kan               0x10010d9  /* U+10D9 GEORGIAN LETTER KAN */\n#define XK_Georgian_las               0x10010da  /* U+10DA GEORGIAN LETTER LAS */\n#define XK_Georgian_man               0x10010db  /* U+10DB GEORGIAN LETTER MAN */\n#define XK_Georgian_nar               0x10010dc  /* U+10DC GEORGIAN LETTER NAR */\n#define XK_Georgian_on                0x10010dd  /* U+10DD GEORGIAN LETTER ON */\n#define XK_Georgian_par               0x10010de  /* U+10DE GEORGIAN LETTER PAR */\n#define XK_Georgian_zhar              0x10010df  /* U+10DF GEORGIAN LETTER ZHAR */\n#define XK_Georgian_rae               0x10010e0  /* U+10E0 GEORGIAN LETTER RAE */\n#define XK_Georgian_san               0x10010e1  /* U+10E1 GEORGIAN LETTER SAN */\n#define XK_Georgian_tar               0x10010e2  /* U+10E2 GEORGIAN LETTER TAR */\n#define XK_Georgian_un                0x10010e3  /* U+10E3 GEORGIAN LETTER UN */\n#define XK_Georgian_phar              0x10010e4  /* U+10E4 GEORGIAN LETTER PHAR */\n#define XK_Georgian_khar              0x10010e5  /* U+10E5 GEORGIAN LETTER KHAR */\n#define XK_Georgian_ghan              0x10010e6  /* U+10E6 GEORGIAN LETTER GHAN */\n#define XK_Georgian_qar               0x10010e7  /* U+10E7 GEORGIAN LETTER QAR */\n#define XK_Georgian_shin              0x10010e8  /* U+10E8 GEORGIAN LETTER SHIN */\n#define XK_Georgian_chin              0x10010e9  /* U+10E9 GEORGIAN LETTER CHIN */\n#define XK_Georgian_can               0x10010ea  /* U+10EA GEORGIAN LETTER CAN */\n#define XK_Georgian_jil               0x10010eb  /* U+10EB GEORGIAN LETTER JIL */\n#define XK_Georgian_cil               0x10010ec  /* U+10EC GEORGIAN LETTER CIL */\n#define XK_Georgian_char              0x10010ed  /* U+10ED GEORGIAN LETTER CHAR */\n#define XK_Georgian_xan               0x10010ee  /* U+10EE GEORGIAN LETTER XAN */\n#define XK_Georgian_jhan              0x10010ef  /* U+10EF GEORGIAN LETTER JHAN */\n#define XK_Georgian_hae               0x10010f0  /* U+10F0 GEORGIAN LETTER HAE */\n#define XK_Georgian_he                0x10010f1  /* U+10F1 GEORGIAN LETTER HE */\n#define XK_Georgian_hie               0x10010f2  /* U+10F2 GEORGIAN LETTER HIE */\n#define XK_Georgian_we                0x10010f3  /* U+10F3 GEORGIAN LETTER WE */\n#define XK_Georgian_har               0x10010f4  /* U+10F4 GEORGIAN LETTER HAR */\n#define XK_Georgian_hoe               0x10010f5  /* U+10F5 GEORGIAN LETTER HOE */\n#define XK_Georgian_fi                0x10010f6  /* U+10F6 GEORGIAN LETTER FI */\n#endif /* XK_GEORGIAN */\n\n/*\n * Azeri (and other Turkic or Caucasian languages)\n */\n\n#ifdef XK_CAUCASUS\n/* latin */\n#define XK_Xabovedot                  0x1001e8a  /* U+1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE */\n#define XK_Ibreve                     0x100012c  /* U+012C LATIN CAPITAL LETTER I WITH BREVE */\n#define XK_Zstroke                    0x10001b5  /* U+01B5 LATIN CAPITAL LETTER Z WITH STROKE */\n#define XK_Gcaron                     0x10001e6  /* U+01E6 LATIN CAPITAL LETTER G WITH CARON */\n#define XK_Ocaron                     0x10001d1  /* U+01D1 LATIN CAPITAL LETTER O WITH CARON */\n#define XK_Obarred                    0x100019f  /* U+019F LATIN CAPITAL LETTER O WITH MIDDLE TILDE */\n#define XK_xabovedot                  0x1001e8b  /* U+1E8B LATIN SMALL LETTER X WITH DOT ABOVE */\n#define XK_ibreve                     0x100012d  /* U+012D LATIN SMALL LETTER I WITH BREVE */\n#define XK_zstroke                    0x10001b6  /* U+01B6 LATIN SMALL LETTER Z WITH STROKE */\n#define XK_gcaron                     0x10001e7  /* U+01E7 LATIN SMALL LETTER G WITH CARON */\n#define XK_ocaron                     0x10001d2  /* U+01D2 LATIN SMALL LETTER O WITH CARON */\n#define XK_obarred                    0x1000275  /* U+0275 LATIN SMALL LETTER BARRED O */\n#define XK_SCHWA                      0x100018f  /* U+018F LATIN CAPITAL LETTER SCHWA */\n#define XK_schwa                      0x1000259  /* U+0259 LATIN SMALL LETTER SCHWA */\n#define XK_EZH                        0x10001b7  /* U+01B7 LATIN CAPITAL LETTER EZH */\n#define XK_ezh                        0x1000292  /* U+0292 LATIN SMALL LETTER EZH */\n/* those are not really Caucasus */\n/* For Inupiak */\n#define XK_Lbelowdot                  0x1001e36  /* U+1E36 LATIN CAPITAL LETTER L WITH DOT BELOW */\n#define XK_lbelowdot                  0x1001e37  /* U+1E37 LATIN SMALL LETTER L WITH DOT BELOW */\n#endif /* XK_CAUCASUS */\n\n/*\n * Vietnamese\n */\n\n#ifdef XK_VIETNAMESE\n#define XK_Abelowdot                  0x1001ea0  /* U+1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW */\n#define XK_abelowdot                  0x1001ea1  /* U+1EA1 LATIN SMALL LETTER A WITH DOT BELOW */\n#define XK_Ahook                      0x1001ea2  /* U+1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE */\n#define XK_ahook                      0x1001ea3  /* U+1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE */\n#define XK_Acircumflexacute           0x1001ea4  /* U+1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */\n#define XK_acircumflexacute           0x1001ea5  /* U+1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */\n#define XK_Acircumflexgrave           0x1001ea6  /* U+1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */\n#define XK_acircumflexgrave           0x1001ea7  /* U+1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */\n#define XK_Acircumflexhook            0x1001ea8  /* U+1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_acircumflexhook            0x1001ea9  /* U+1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_Acircumflextilde           0x1001eaa  /* U+1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */\n#define XK_acircumflextilde           0x1001eab  /* U+1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */\n#define XK_Acircumflexbelowdot        0x1001eac  /* U+1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_acircumflexbelowdot        0x1001ead  /* U+1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_Abreveacute                0x1001eae  /* U+1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */\n#define XK_abreveacute                0x1001eaf  /* U+1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE */\n#define XK_Abrevegrave                0x1001eb0  /* U+1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */\n#define XK_abrevegrave                0x1001eb1  /* U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE */\n#define XK_Abrevehook                 0x1001eb2  /* U+1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */\n#define XK_abrevehook                 0x1001eb3  /* U+1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */\n#define XK_Abrevetilde                0x1001eb4  /* U+1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE */\n#define XK_abrevetilde                0x1001eb5  /* U+1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE */\n#define XK_Abrevebelowdot             0x1001eb6  /* U+1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */\n#define XK_abrevebelowdot             0x1001eb7  /* U+1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */\n#define XK_Ebelowdot                  0x1001eb8  /* U+1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW */\n#define XK_ebelowdot                  0x1001eb9  /* U+1EB9 LATIN SMALL LETTER E WITH DOT BELOW */\n#define XK_Ehook                      0x1001eba  /* U+1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE */\n#define XK_ehook                      0x1001ebb  /* U+1EBB LATIN SMALL LETTER E WITH HOOK ABOVE */\n#define XK_Etilde                     0x1001ebc  /* U+1EBC LATIN CAPITAL LETTER E WITH TILDE */\n#define XK_etilde                     0x1001ebd  /* U+1EBD LATIN SMALL LETTER E WITH TILDE */\n#define XK_Ecircumflexacute           0x1001ebe  /* U+1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */\n#define XK_ecircumflexacute           0x1001ebf  /* U+1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */\n#define XK_Ecircumflexgrave           0x1001ec0  /* U+1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */\n#define XK_ecircumflexgrave           0x1001ec1  /* U+1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */\n#define XK_Ecircumflexhook            0x1001ec2  /* U+1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_ecircumflexhook            0x1001ec3  /* U+1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_Ecircumflextilde           0x1001ec4  /* U+1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */\n#define XK_ecircumflextilde           0x1001ec5  /* U+1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */\n#define XK_Ecircumflexbelowdot        0x1001ec6  /* U+1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_ecircumflexbelowdot        0x1001ec7  /* U+1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_Ihook                      0x1001ec8  /* U+1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE */\n#define XK_ihook                      0x1001ec9  /* U+1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE */\n#define XK_Ibelowdot                  0x1001eca  /* U+1ECA LATIN CAPITAL LETTER I WITH DOT BELOW */\n#define XK_ibelowdot                  0x1001ecb  /* U+1ECB LATIN SMALL LETTER I WITH DOT BELOW */\n#define XK_Obelowdot                  0x1001ecc  /* U+1ECC LATIN CAPITAL LETTER O WITH DOT BELOW */\n#define XK_obelowdot                  0x1001ecd  /* U+1ECD LATIN SMALL LETTER O WITH DOT BELOW */\n#define XK_Ohook                      0x1001ece  /* U+1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE */\n#define XK_ohook                      0x1001ecf  /* U+1ECF LATIN SMALL LETTER O WITH HOOK ABOVE */\n#define XK_Ocircumflexacute           0x1001ed0  /* U+1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */\n#define XK_ocircumflexacute           0x1001ed1  /* U+1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */\n#define XK_Ocircumflexgrave           0x1001ed2  /* U+1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */\n#define XK_ocircumflexgrave           0x1001ed3  /* U+1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */\n#define XK_Ocircumflexhook            0x1001ed4  /* U+1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_ocircumflexhook            0x1001ed5  /* U+1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */\n#define XK_Ocircumflextilde           0x1001ed6  /* U+1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */\n#define XK_ocircumflextilde           0x1001ed7  /* U+1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */\n#define XK_Ocircumflexbelowdot        0x1001ed8  /* U+1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_ocircumflexbelowdot        0x1001ed9  /* U+1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */\n#define XK_Ohornacute                 0x1001eda  /* U+1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE */\n#define XK_ohornacute                 0x1001edb  /* U+1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE */\n#define XK_Ohorngrave                 0x1001edc  /* U+1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE */\n#define XK_ohorngrave                 0x1001edd  /* U+1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE */\n#define XK_Ohornhook                  0x1001ede  /* U+1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */\n#define XK_ohornhook                  0x1001edf  /* U+1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */\n#define XK_Ohorntilde                 0x1001ee0  /* U+1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE */\n#define XK_ohorntilde                 0x1001ee1  /* U+1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE */\n#define XK_Ohornbelowdot              0x1001ee2  /* U+1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */\n#define XK_ohornbelowdot              0x1001ee3  /* U+1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW */\n#define XK_Ubelowdot                  0x1001ee4  /* U+1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW */\n#define XK_ubelowdot                  0x1001ee5  /* U+1EE5 LATIN SMALL LETTER U WITH DOT BELOW */\n#define XK_Uhook                      0x1001ee6  /* U+1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE */\n#define XK_uhook                      0x1001ee7  /* U+1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE */\n#define XK_Uhornacute                 0x1001ee8  /* U+1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE */\n#define XK_uhornacute                 0x1001ee9  /* U+1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE */\n#define XK_Uhorngrave                 0x1001eea  /* U+1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE */\n#define XK_uhorngrave                 0x1001eeb  /* U+1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE */\n#define XK_Uhornhook                  0x1001eec  /* U+1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */\n#define XK_uhornhook                  0x1001eed  /* U+1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */\n#define XK_Uhorntilde                 0x1001eee  /* U+1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE */\n#define XK_uhorntilde                 0x1001eef  /* U+1EEF LATIN SMALL LETTER U WITH HORN AND TILDE */\n#define XK_Uhornbelowdot              0x1001ef0  /* U+1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */\n#define XK_uhornbelowdot              0x1001ef1  /* U+1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW */\n#define XK_Ybelowdot                  0x1001ef4  /* U+1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW */\n#define XK_ybelowdot                  0x1001ef5  /* U+1EF5 LATIN SMALL LETTER Y WITH DOT BELOW */\n#define XK_Yhook                      0x1001ef6  /* U+1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE */\n#define XK_yhook                      0x1001ef7  /* U+1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE */\n#define XK_Ytilde                     0x1001ef8  /* U+1EF8 LATIN CAPITAL LETTER Y WITH TILDE */\n#define XK_ytilde                     0x1001ef9  /* U+1EF9 LATIN SMALL LETTER Y WITH TILDE */\n#define XK_Ohorn                      0x10001a0  /* U+01A0 LATIN CAPITAL LETTER O WITH HORN */\n#define XK_ohorn                      0x10001a1  /* U+01A1 LATIN SMALL LETTER O WITH HORN */\n#define XK_Uhorn                      0x10001af  /* U+01AF LATIN CAPITAL LETTER U WITH HORN */\n#define XK_uhorn                      0x10001b0  /* U+01B0 LATIN SMALL LETTER U WITH HORN */\n#define XK_combining_tilde            0x1000303  /* U+0303 COMBINING TILDE */\n#define XK_combining_grave            0x1000300  /* U+0300 COMBINING GRAVE ACCENT */\n#define XK_combining_acute            0x1000301  /* U+0301 COMBINING ACUTE ACCENT */\n#define XK_combining_hook             0x1000309  /* U+0309 COMBINING HOOK ABOVE */\n#define XK_combining_belowdot         0x1000323  /* U+0323 COMBINING DOT BELOW */\n\n#endif /* XK_VIETNAMESE */\n\n#ifdef XK_CURRENCY\n#define XK_EcuSign                    0x10020a0  /* U+20A0 EURO-CURRENCY SIGN */\n#define XK_ColonSign                  0x10020a1  /* U+20A1 COLON SIGN */\n#define XK_CruzeiroSign               0x10020a2  /* U+20A2 CRUZEIRO SIGN */\n#define XK_FFrancSign                 0x10020a3  /* U+20A3 FRENCH FRANC SIGN */\n#define XK_LiraSign                   0x10020a4  /* U+20A4 LIRA SIGN */\n#define XK_MillSign                   0x10020a5  /* U+20A5 MILL SIGN */\n#define XK_NairaSign                  0x10020a6  /* U+20A6 NAIRA SIGN */\n#define XK_PesetaSign                 0x10020a7  /* U+20A7 PESETA SIGN */\n#define XK_RupeeSign                  0x10020a8  /* U+20A8 RUPEE SIGN */\n#define XK_WonSign                    0x10020a9  /* U+20A9 WON SIGN */\n#define XK_NewSheqelSign              0x10020aa  /* U+20AA NEW SHEQEL SIGN */\n#define XK_DongSign                   0x10020ab  /* U+20AB DONG SIGN */\n#define XK_EuroSign                      0x20ac  /* U+20AC EURO SIGN */\n#endif /* XK_CURRENCY */\n\n#ifdef XK_MATHEMATICAL\n/* one, two and three are defined above. */\n#define XK_zerosuperior               0x1002070  /* U+2070 SUPERSCRIPT ZERO */\n#define XK_foursuperior               0x1002074  /* U+2074 SUPERSCRIPT FOUR */\n#define XK_fivesuperior               0x1002075  /* U+2075 SUPERSCRIPT FIVE */\n#define XK_sixsuperior                0x1002076  /* U+2076 SUPERSCRIPT SIX */\n#define XK_sevensuperior              0x1002077  /* U+2077 SUPERSCRIPT SEVEN */\n#define XK_eightsuperior              0x1002078  /* U+2078 SUPERSCRIPT EIGHT */\n#define XK_ninesuperior               0x1002079  /* U+2079 SUPERSCRIPT NINE */\n#define XK_zerosubscript              0x1002080  /* U+2080 SUBSCRIPT ZERO */\n#define XK_onesubscript               0x1002081  /* U+2081 SUBSCRIPT ONE */\n#define XK_twosubscript               0x1002082  /* U+2082 SUBSCRIPT TWO */\n#define XK_threesubscript             0x1002083  /* U+2083 SUBSCRIPT THREE */\n#define XK_foursubscript              0x1002084  /* U+2084 SUBSCRIPT FOUR */\n#define XK_fivesubscript              0x1002085  /* U+2085 SUBSCRIPT FIVE */\n#define XK_sixsubscript               0x1002086  /* U+2086 SUBSCRIPT SIX */\n#define XK_sevensubscript             0x1002087  /* U+2087 SUBSCRIPT SEVEN */\n#define XK_eightsubscript             0x1002088  /* U+2088 SUBSCRIPT EIGHT */\n#define XK_ninesubscript              0x1002089  /* U+2089 SUBSCRIPT NINE */\n#define XK_partdifferential           0x1002202  /* U+2202 PARTIAL DIFFERENTIAL */\n#define XK_emptyset                   0x1002205  /* U+2205 EMPTY SET */\n#define XK_elementof                  0x1002208  /* U+2208 ELEMENT OF */\n#define XK_notelementof               0x1002209  /* U+2209 NOT AN ELEMENT OF */\n#define XK_containsas                 0x100220b  /* U+220B CONTAINS AS MEMBER */\n#define XK_squareroot                 0x100221a  /* U+221A SQUARE ROOT */\n#define XK_cuberoot                   0x100221b  /* U+221B CUBE ROOT */\n#define XK_fourthroot                 0x100221c  /* U+221C FOURTH ROOT */\n#define XK_dintegral                  0x100222c  /* U+222C DOUBLE INTEGRAL */\n#define XK_tintegral                  0x100222d  /* U+222D TRIPLE INTEGRAL */\n#define XK_because                    0x1002235  /* U+2235 BECAUSE */\n#define XK_approxeq                   0x1002248  /*(U+2248 ALMOST EQUAL TO)*/\n#define XK_notapproxeq                0x1002247  /*(U+2247 NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO)*/\n#define XK_notidentical               0x1002262  /* U+2262 NOT IDENTICAL TO */\n#define XK_stricteq                   0x1002263  /* U+2263 STRICTLY EQUIVALENT TO */\n#endif /* XK_MATHEMATICAL */\n\n#ifdef XK_BRAILLE\n#define XK_braille_dot_1                 0xfff1\n#define XK_braille_dot_2                 0xfff2\n#define XK_braille_dot_3                 0xfff3\n#define XK_braille_dot_4                 0xfff4\n#define XK_braille_dot_5                 0xfff5\n#define XK_braille_dot_6                 0xfff6\n#define XK_braille_dot_7                 0xfff7\n#define XK_braille_dot_8                 0xfff8\n#define XK_braille_dot_9                 0xfff9\n#define XK_braille_dot_10                0xfffa\n#define XK_braille_blank              0x1002800  /* U+2800 BRAILLE PATTERN BLANK */\n#define XK_braille_dots_1             0x1002801  /* U+2801 BRAILLE PATTERN DOTS-1 */\n#define XK_braille_dots_2             0x1002802  /* U+2802 BRAILLE PATTERN DOTS-2 */\n#define XK_braille_dots_12            0x1002803  /* U+2803 BRAILLE PATTERN DOTS-12 */\n#define XK_braille_dots_3             0x1002804  /* U+2804 BRAILLE PATTERN DOTS-3 */\n#define XK_braille_dots_13            0x1002805  /* U+2805 BRAILLE PATTERN DOTS-13 */\n#define XK_braille_dots_23            0x1002806  /* U+2806 BRAILLE PATTERN DOTS-23 */\n#define XK_braille_dots_123           0x1002807  /* U+2807 BRAILLE PATTERN DOTS-123 */\n#define XK_braille_dots_4             0x1002808  /* U+2808 BRAILLE PATTERN DOTS-4 */\n#define XK_braille_dots_14            0x1002809  /* U+2809 BRAILLE PATTERN DOTS-14 */\n#define XK_braille_dots_24            0x100280a  /* U+280A BRAILLE PATTERN DOTS-24 */\n#define XK_braille_dots_124           0x100280b  /* U+280B BRAILLE PATTERN DOTS-124 */\n#define XK_braille_dots_34            0x100280c  /* U+280C BRAILLE PATTERN DOTS-34 */\n#define XK_braille_dots_134           0x100280d  /* U+280D BRAILLE PATTERN DOTS-134 */\n#define XK_braille_dots_234           0x100280e  /* U+280E BRAILLE PATTERN DOTS-234 */\n#define XK_braille_dots_1234          0x100280f  /* U+280F BRAILLE PATTERN DOTS-1234 */\n#define XK_braille_dots_5             0x1002810  /* U+2810 BRAILLE PATTERN DOTS-5 */\n#define XK_braille_dots_15            0x1002811  /* U+2811 BRAILLE PATTERN DOTS-15 */\n#define XK_braille_dots_25            0x1002812  /* U+2812 BRAILLE PATTERN DOTS-25 */\n#define XK_braille_dots_125           0x1002813  /* U+2813 BRAILLE PATTERN DOTS-125 */\n#define XK_braille_dots_35            0x1002814  /* U+2814 BRAILLE PATTERN DOTS-35 */\n#define XK_braille_dots_135           0x1002815  /* U+2815 BRAILLE PATTERN DOTS-135 */\n#define XK_braille_dots_235           0x1002816  /* U+2816 BRAILLE PATTERN DOTS-235 */\n#define XK_braille_dots_1235          0x1002817  /* U+2817 BRAILLE PATTERN DOTS-1235 */\n#define XK_braille_dots_45            0x1002818  /* U+2818 BRAILLE PATTERN DOTS-45 */\n#define XK_braille_dots_145           0x1002819  /* U+2819 BRAILLE PATTERN DOTS-145 */\n#define XK_braille_dots_245           0x100281a  /* U+281A BRAILLE PATTERN DOTS-245 */\n#define XK_braille_dots_1245          0x100281b  /* U+281B BRAILLE PATTERN DOTS-1245 */\n#define XK_braille_dots_345           0x100281c  /* U+281C BRAILLE PATTERN DOTS-345 */\n#define XK_braille_dots_1345          0x100281d  /* U+281D BRAILLE PATTERN DOTS-1345 */\n#define XK_braille_dots_2345          0x100281e  /* U+281E BRAILLE PATTERN DOTS-2345 */\n#define XK_braille_dots_12345         0x100281f  /* U+281F BRAILLE PATTERN DOTS-12345 */\n#define XK_braille_dots_6             0x1002820  /* U+2820 BRAILLE PATTERN DOTS-6 */\n#define XK_braille_dots_16            0x1002821  /* U+2821 BRAILLE PATTERN DOTS-16 */\n#define XK_braille_dots_26            0x1002822  /* U+2822 BRAILLE PATTERN DOTS-26 */\n#define XK_braille_dots_126           0x1002823  /* U+2823 BRAILLE PATTERN DOTS-126 */\n#define XK_braille_dots_36            0x1002824  /* U+2824 BRAILLE PATTERN DOTS-36 */\n#define XK_braille_dots_136           0x1002825  /* U+2825 BRAILLE PATTERN DOTS-136 */\n#define XK_braille_dots_236           0x1002826  /* U+2826 BRAILLE PATTERN DOTS-236 */\n#define XK_braille_dots_1236          0x1002827  /* U+2827 BRAILLE PATTERN DOTS-1236 */\n#define XK_braille_dots_46            0x1002828  /* U+2828 BRAILLE PATTERN DOTS-46 */\n#define XK_braille_dots_146           0x1002829  /* U+2829 BRAILLE PATTERN DOTS-146 */\n#define XK_braille_dots_246           0x100282a  /* U+282A BRAILLE PATTERN DOTS-246 */\n#define XK_braille_dots_1246          0x100282b  /* U+282B BRAILLE PATTERN DOTS-1246 */\n#define XK_braille_dots_346           0x100282c  /* U+282C BRAILLE PATTERN DOTS-346 */\n#define XK_braille_dots_1346          0x100282d  /* U+282D BRAILLE PATTERN DOTS-1346 */\n#define XK_braille_dots_2346          0x100282e  /* U+282E BRAILLE PATTERN DOTS-2346 */\n#define XK_braille_dots_12346         0x100282f  /* U+282F BRAILLE PATTERN DOTS-12346 */\n#define XK_braille_dots_56            0x1002830  /* U+2830 BRAILLE PATTERN DOTS-56 */\n#define XK_braille_dots_156           0x1002831  /* U+2831 BRAILLE PATTERN DOTS-156 */\n#define XK_braille_dots_256           0x1002832  /* U+2832 BRAILLE PATTERN DOTS-256 */\n#define XK_braille_dots_1256          0x1002833  /* U+2833 BRAILLE PATTERN DOTS-1256 */\n#define XK_braille_dots_356           0x1002834  /* U+2834 BRAILLE PATTERN DOTS-356 */\n#define XK_braille_dots_1356          0x1002835  /* U+2835 BRAILLE PATTERN DOTS-1356 */\n#define XK_braille_dots_2356          0x1002836  /* U+2836 BRAILLE PATTERN DOTS-2356 */\n#define XK_braille_dots_12356         0x1002837  /* U+2837 BRAILLE PATTERN DOTS-12356 */\n#define XK_braille_dots_456           0x1002838  /* U+2838 BRAILLE PATTERN DOTS-456 */\n#define XK_braille_dots_1456          0x1002839  /* U+2839 BRAILLE PATTERN DOTS-1456 */\n#define XK_braille_dots_2456          0x100283a  /* U+283A BRAILLE PATTERN DOTS-2456 */\n#define XK_braille_dots_12456         0x100283b  /* U+283B BRAILLE PATTERN DOTS-12456 */\n#define XK_braille_dots_3456          0x100283c  /* U+283C BRAILLE PATTERN DOTS-3456 */\n#define XK_braille_dots_13456         0x100283d  /* U+283D BRAILLE PATTERN DOTS-13456 */\n#define XK_braille_dots_23456         0x100283e  /* U+283E BRAILLE PATTERN DOTS-23456 */\n#define XK_braille_dots_123456        0x100283f  /* U+283F BRAILLE PATTERN DOTS-123456 */\n#define XK_braille_dots_7             0x1002840  /* U+2840 BRAILLE PATTERN DOTS-7 */\n#define XK_braille_dots_17            0x1002841  /* U+2841 BRAILLE PATTERN DOTS-17 */\n#define XK_braille_dots_27            0x1002842  /* U+2842 BRAILLE PATTERN DOTS-27 */\n#define XK_braille_dots_127           0x1002843  /* U+2843 BRAILLE PATTERN DOTS-127 */\n#define XK_braille_dots_37            0x1002844  /* U+2844 BRAILLE PATTERN DOTS-37 */\n#define XK_braille_dots_137           0x1002845  /* U+2845 BRAILLE PATTERN DOTS-137 */\n#define XK_braille_dots_237           0x1002846  /* U+2846 BRAILLE PATTERN DOTS-237 */\n#define XK_braille_dots_1237          0x1002847  /* U+2847 BRAILLE PATTERN DOTS-1237 */\n#define XK_braille_dots_47            0x1002848  /* U+2848 BRAILLE PATTERN DOTS-47 */\n#define XK_braille_dots_147           0x1002849  /* U+2849 BRAILLE PATTERN DOTS-147 */\n#define XK_braille_dots_247           0x100284a  /* U+284A BRAILLE PATTERN DOTS-247 */\n#define XK_braille_dots_1247          0x100284b  /* U+284B BRAILLE PATTERN DOTS-1247 */\n#define XK_braille_dots_347           0x100284c  /* U+284C BRAILLE PATTERN DOTS-347 */\n#define XK_braille_dots_1347          0x100284d  /* U+284D BRAILLE PATTERN DOTS-1347 */\n#define XK_braille_dots_2347          0x100284e  /* U+284E BRAILLE PATTERN DOTS-2347 */\n#define XK_braille_dots_12347         0x100284f  /* U+284F BRAILLE PATTERN DOTS-12347 */\n#define XK_braille_dots_57            0x1002850  /* U+2850 BRAILLE PATTERN DOTS-57 */\n#define XK_braille_dots_157           0x1002851  /* U+2851 BRAILLE PATTERN DOTS-157 */\n#define XK_braille_dots_257           0x1002852  /* U+2852 BRAILLE PATTERN DOTS-257 */\n#define XK_braille_dots_1257          0x1002853  /* U+2853 BRAILLE PATTERN DOTS-1257 */\n#define XK_braille_dots_357           0x1002854  /* U+2854 BRAILLE PATTERN DOTS-357 */\n#define XK_braille_dots_1357          0x1002855  /* U+2855 BRAILLE PATTERN DOTS-1357 */\n#define XK_braille_dots_2357          0x1002856  /* U+2856 BRAILLE PATTERN DOTS-2357 */\n#define XK_braille_dots_12357         0x1002857  /* U+2857 BRAILLE PATTERN DOTS-12357 */\n#define XK_braille_dots_457           0x1002858  /* U+2858 BRAILLE PATTERN DOTS-457 */\n#define XK_braille_dots_1457          0x1002859  /* U+2859 BRAILLE PATTERN DOTS-1457 */\n#define XK_braille_dots_2457          0x100285a  /* U+285A BRAILLE PATTERN DOTS-2457 */\n#define XK_braille_dots_12457         0x100285b  /* U+285B BRAILLE PATTERN DOTS-12457 */\n#define XK_braille_dots_3457          0x100285c  /* U+285C BRAILLE PATTERN DOTS-3457 */\n#define XK_braille_dots_13457         0x100285d  /* U+285D BRAILLE PATTERN DOTS-13457 */\n#define XK_braille_dots_23457         0x100285e  /* U+285E BRAILLE PATTERN DOTS-23457 */\n#define XK_braille_dots_123457        0x100285f  /* U+285F BRAILLE PATTERN DOTS-123457 */\n#define XK_braille_dots_67            0x1002860  /* U+2860 BRAILLE PATTERN DOTS-67 */\n#define XK_braille_dots_167           0x1002861  /* U+2861 BRAILLE PATTERN DOTS-167 */\n#define XK_braille_dots_267           0x1002862  /* U+2862 BRAILLE PATTERN DOTS-267 */\n#define XK_braille_dots_1267          0x1002863  /* U+2863 BRAILLE PATTERN DOTS-1267 */\n#define XK_braille_dots_367           0x1002864  /* U+2864 BRAILLE PATTERN DOTS-367 */\n#define XK_braille_dots_1367          0x1002865  /* U+2865 BRAILLE PATTERN DOTS-1367 */\n#define XK_braille_dots_2367          0x1002866  /* U+2866 BRAILLE PATTERN DOTS-2367 */\n#define XK_braille_dots_12367         0x1002867  /* U+2867 BRAILLE PATTERN DOTS-12367 */\n#define XK_braille_dots_467           0x1002868  /* U+2868 BRAILLE PATTERN DOTS-467 */\n#define XK_braille_dots_1467          0x1002869  /* U+2869 BRAILLE PATTERN DOTS-1467 */\n#define XK_braille_dots_2467          0x100286a  /* U+286A BRAILLE PATTERN DOTS-2467 */\n#define XK_braille_dots_12467         0x100286b  /* U+286B BRAILLE PATTERN DOTS-12467 */\n#define XK_braille_dots_3467          0x100286c  /* U+286C BRAILLE PATTERN DOTS-3467 */\n#define XK_braille_dots_13467         0x100286d  /* U+286D BRAILLE PATTERN DOTS-13467 */\n#define XK_braille_dots_23467         0x100286e  /* U+286E BRAILLE PATTERN DOTS-23467 */\n#define XK_braille_dots_123467        0x100286f  /* U+286F BRAILLE PATTERN DOTS-123467 */\n#define XK_braille_dots_567           0x1002870  /* U+2870 BRAILLE PATTERN DOTS-567 */\n#define XK_braille_dots_1567          0x1002871  /* U+2871 BRAILLE PATTERN DOTS-1567 */\n#define XK_braille_dots_2567          0x1002872  /* U+2872 BRAILLE PATTERN DOTS-2567 */\n#define XK_braille_dots_12567         0x1002873  /* U+2873 BRAILLE PATTERN DOTS-12567 */\n#define XK_braille_dots_3567          0x1002874  /* U+2874 BRAILLE PATTERN DOTS-3567 */\n#define XK_braille_dots_13567         0x1002875  /* U+2875 BRAILLE PATTERN DOTS-13567 */\n#define XK_braille_dots_23567         0x1002876  /* U+2876 BRAILLE PATTERN DOTS-23567 */\n#define XK_braille_dots_123567        0x1002877  /* U+2877 BRAILLE PATTERN DOTS-123567 */\n#define XK_braille_dots_4567          0x1002878  /* U+2878 BRAILLE PATTERN DOTS-4567 */\n#define XK_braille_dots_14567         0x1002879  /* U+2879 BRAILLE PATTERN DOTS-14567 */\n#define XK_braille_dots_24567         0x100287a  /* U+287A BRAILLE PATTERN DOTS-24567 */\n#define XK_braille_dots_124567        0x100287b  /* U+287B BRAILLE PATTERN DOTS-124567 */\n#define XK_braille_dots_34567         0x100287c  /* U+287C BRAILLE PATTERN DOTS-34567 */\n#define XK_braille_dots_134567        0x100287d  /* U+287D BRAILLE PATTERN DOTS-134567 */\n#define XK_braille_dots_234567        0x100287e  /* U+287E BRAILLE PATTERN DOTS-234567 */\n#define XK_braille_dots_1234567       0x100287f  /* U+287F BRAILLE PATTERN DOTS-1234567 */\n#define XK_braille_dots_8             0x1002880  /* U+2880 BRAILLE PATTERN DOTS-8 */\n#define XK_braille_dots_18            0x1002881  /* U+2881 BRAILLE PATTERN DOTS-18 */\n#define XK_braille_dots_28            0x1002882  /* U+2882 BRAILLE PATTERN DOTS-28 */\n#define XK_braille_dots_128           0x1002883  /* U+2883 BRAILLE PATTERN DOTS-128 */\n#define XK_braille_dots_38            0x1002884  /* U+2884 BRAILLE PATTERN DOTS-38 */\n#define XK_braille_dots_138           0x1002885  /* U+2885 BRAILLE PATTERN DOTS-138 */\n#define XK_braille_dots_238           0x1002886  /* U+2886 BRAILLE PATTERN DOTS-238 */\n#define XK_braille_dots_1238          0x1002887  /* U+2887 BRAILLE PATTERN DOTS-1238 */\n#define XK_braille_dots_48            0x1002888  /* U+2888 BRAILLE PATTERN DOTS-48 */\n#define XK_braille_dots_148           0x1002889  /* U+2889 BRAILLE PATTERN DOTS-148 */\n#define XK_braille_dots_248           0x100288a  /* U+288A BRAILLE PATTERN DOTS-248 */\n#define XK_braille_dots_1248          0x100288b  /* U+288B BRAILLE PATTERN DOTS-1248 */\n#define XK_braille_dots_348           0x100288c  /* U+288C BRAILLE PATTERN DOTS-348 */\n#define XK_braille_dots_1348          0x100288d  /* U+288D BRAILLE PATTERN DOTS-1348 */\n#define XK_braille_dots_2348          0x100288e  /* U+288E BRAILLE PATTERN DOTS-2348 */\n#define XK_braille_dots_12348         0x100288f  /* U+288F BRAILLE PATTERN DOTS-12348 */\n#define XK_braille_dots_58            0x1002890  /* U+2890 BRAILLE PATTERN DOTS-58 */\n#define XK_braille_dots_158           0x1002891  /* U+2891 BRAILLE PATTERN DOTS-158 */\n#define XK_braille_dots_258           0x1002892  /* U+2892 BRAILLE PATTERN DOTS-258 */\n#define XK_braille_dots_1258          0x1002893  /* U+2893 BRAILLE PATTERN DOTS-1258 */\n#define XK_braille_dots_358           0x1002894  /* U+2894 BRAILLE PATTERN DOTS-358 */\n#define XK_braille_dots_1358          0x1002895  /* U+2895 BRAILLE PATTERN DOTS-1358 */\n#define XK_braille_dots_2358          0x1002896  /* U+2896 BRAILLE PATTERN DOTS-2358 */\n#define XK_braille_dots_12358         0x1002897  /* U+2897 BRAILLE PATTERN DOTS-12358 */\n#define XK_braille_dots_458           0x1002898  /* U+2898 BRAILLE PATTERN DOTS-458 */\n#define XK_braille_dots_1458          0x1002899  /* U+2899 BRAILLE PATTERN DOTS-1458 */\n#define XK_braille_dots_2458          0x100289a  /* U+289A BRAILLE PATTERN DOTS-2458 */\n#define XK_braille_dots_12458         0x100289b  /* U+289B BRAILLE PATTERN DOTS-12458 */\n#define XK_braille_dots_3458          0x100289c  /* U+289C BRAILLE PATTERN DOTS-3458 */\n#define XK_braille_dots_13458         0x100289d  /* U+289D BRAILLE PATTERN DOTS-13458 */\n#define XK_braille_dots_23458         0x100289e  /* U+289E BRAILLE PATTERN DOTS-23458 */\n#define XK_braille_dots_123458        0x100289f  /* U+289F BRAILLE PATTERN DOTS-123458 */\n#define XK_braille_dots_68            0x10028a0  /* U+28A0 BRAILLE PATTERN DOTS-68 */\n#define XK_braille_dots_168           0x10028a1  /* U+28A1 BRAILLE PATTERN DOTS-168 */\n#define XK_braille_dots_268           0x10028a2  /* U+28A2 BRAILLE PATTERN DOTS-268 */\n#define XK_braille_dots_1268          0x10028a3  /* U+28A3 BRAILLE PATTERN DOTS-1268 */\n#define XK_braille_dots_368           0x10028a4  /* U+28A4 BRAILLE PATTERN DOTS-368 */\n#define XK_braille_dots_1368          0x10028a5  /* U+28A5 BRAILLE PATTERN DOTS-1368 */\n#define XK_braille_dots_2368          0x10028a6  /* U+28A6 BRAILLE PATTERN DOTS-2368 */\n#define XK_braille_dots_12368         0x10028a7  /* U+28A7 BRAILLE PATTERN DOTS-12368 */\n#define XK_braille_dots_468           0x10028a8  /* U+28A8 BRAILLE PATTERN DOTS-468 */\n#define XK_braille_dots_1468          0x10028a9  /* U+28A9 BRAILLE PATTERN DOTS-1468 */\n#define XK_braille_dots_2468          0x10028aa  /* U+28AA BRAILLE PATTERN DOTS-2468 */\n#define XK_braille_dots_12468         0x10028ab  /* U+28AB BRAILLE PATTERN DOTS-12468 */\n#define XK_braille_dots_3468          0x10028ac  /* U+28AC BRAILLE PATTERN DOTS-3468 */\n#define XK_braille_dots_13468         0x10028ad  /* U+28AD BRAILLE PATTERN DOTS-13468 */\n#define XK_braille_dots_23468         0x10028ae  /* U+28AE BRAILLE PATTERN DOTS-23468 */\n#define XK_braille_dots_123468        0x10028af  /* U+28AF BRAILLE PATTERN DOTS-123468 */\n#define XK_braille_dots_568           0x10028b0  /* U+28B0 BRAILLE PATTERN DOTS-568 */\n#define XK_braille_dots_1568          0x10028b1  /* U+28B1 BRAILLE PATTERN DOTS-1568 */\n#define XK_braille_dots_2568          0x10028b2  /* U+28B2 BRAILLE PATTERN DOTS-2568 */\n#define XK_braille_dots_12568         0x10028b3  /* U+28B3 BRAILLE PATTERN DOTS-12568 */\n#define XK_braille_dots_3568          0x10028b4  /* U+28B4 BRAILLE PATTERN DOTS-3568 */\n#define XK_braille_dots_13568         0x10028b5  /* U+28B5 BRAILLE PATTERN DOTS-13568 */\n#define XK_braille_dots_23568         0x10028b6  /* U+28B6 BRAILLE PATTERN DOTS-23568 */\n#define XK_braille_dots_123568        0x10028b7  /* U+28B7 BRAILLE PATTERN DOTS-123568 */\n#define XK_braille_dots_4568          0x10028b8  /* U+28B8 BRAILLE PATTERN DOTS-4568 */\n#define XK_braille_dots_14568         0x10028b9  /* U+28B9 BRAILLE PATTERN DOTS-14568 */\n#define XK_braille_dots_24568         0x10028ba  /* U+28BA BRAILLE PATTERN DOTS-24568 */\n#define XK_braille_dots_124568        0x10028bb  /* U+28BB BRAILLE PATTERN DOTS-124568 */\n#define XK_braille_dots_34568         0x10028bc  /* U+28BC BRAILLE PATTERN DOTS-34568 */\n#define XK_braille_dots_134568        0x10028bd  /* U+28BD BRAILLE PATTERN DOTS-134568 */\n#define XK_braille_dots_234568        0x10028be  /* U+28BE BRAILLE PATTERN DOTS-234568 */\n#define XK_braille_dots_1234568       0x10028bf  /* U+28BF BRAILLE PATTERN DOTS-1234568 */\n#define XK_braille_dots_78            0x10028c0  /* U+28C0 BRAILLE PATTERN DOTS-78 */\n#define XK_braille_dots_178           0x10028c1  /* U+28C1 BRAILLE PATTERN DOTS-178 */\n#define XK_braille_dots_278           0x10028c2  /* U+28C2 BRAILLE PATTERN DOTS-278 */\n#define XK_braille_dots_1278          0x10028c3  /* U+28C3 BRAILLE PATTERN DOTS-1278 */\n#define XK_braille_dots_378           0x10028c4  /* U+28C4 BRAILLE PATTERN DOTS-378 */\n#define XK_braille_dots_1378          0x10028c5  /* U+28C5 BRAILLE PATTERN DOTS-1378 */\n#define XK_braille_dots_2378          0x10028c6  /* U+28C6 BRAILLE PATTERN DOTS-2378 */\n#define XK_braille_dots_12378         0x10028c7  /* U+28C7 BRAILLE PATTERN DOTS-12378 */\n#define XK_braille_dots_478           0x10028c8  /* U+28C8 BRAILLE PATTERN DOTS-478 */\n#define XK_braille_dots_1478          0x10028c9  /* U+28C9 BRAILLE PATTERN DOTS-1478 */\n#define XK_braille_dots_2478          0x10028ca  /* U+28CA BRAILLE PATTERN DOTS-2478 */\n#define XK_braille_dots_12478         0x10028cb  /* U+28CB BRAILLE PATTERN DOTS-12478 */\n#define XK_braille_dots_3478          0x10028cc  /* U+28CC BRAILLE PATTERN DOTS-3478 */\n#define XK_braille_dots_13478         0x10028cd  /* U+28CD BRAILLE PATTERN DOTS-13478 */\n#define XK_braille_dots_23478         0x10028ce  /* U+28CE BRAILLE PATTERN DOTS-23478 */\n#define XK_braille_dots_123478        0x10028cf  /* U+28CF BRAILLE PATTERN DOTS-123478 */\n#define XK_braille_dots_578           0x10028d0  /* U+28D0 BRAILLE PATTERN DOTS-578 */\n#define XK_braille_dots_1578          0x10028d1  /* U+28D1 BRAILLE PATTERN DOTS-1578 */\n#define XK_braille_dots_2578          0x10028d2  /* U+28D2 BRAILLE PATTERN DOTS-2578 */\n#define XK_braille_dots_12578         0x10028d3  /* U+28D3 BRAILLE PATTERN DOTS-12578 */\n#define XK_braille_dots_3578          0x10028d4  /* U+28D4 BRAILLE PATTERN DOTS-3578 */\n#define XK_braille_dots_13578         0x10028d5  /* U+28D5 BRAILLE PATTERN DOTS-13578 */\n#define XK_braille_dots_23578         0x10028d6  /* U+28D6 BRAILLE PATTERN DOTS-23578 */\n#define XK_braille_dots_123578        0x10028d7  /* U+28D7 BRAILLE PATTERN DOTS-123578 */\n#define XK_braille_dots_4578          0x10028d8  /* U+28D8 BRAILLE PATTERN DOTS-4578 */\n#define XK_braille_dots_14578         0x10028d9  /* U+28D9 BRAILLE PATTERN DOTS-14578 */\n#define XK_braille_dots_24578         0x10028da  /* U+28DA BRAILLE PATTERN DOTS-24578 */\n#define XK_braille_dots_124578        0x10028db  /* U+28DB BRAILLE PATTERN DOTS-124578 */\n#define XK_braille_dots_34578         0x10028dc  /* U+28DC BRAILLE PATTERN DOTS-34578 */\n#define XK_braille_dots_134578        0x10028dd  /* U+28DD BRAILLE PATTERN DOTS-134578 */\n#define XK_braille_dots_234578        0x10028de  /* U+28DE BRAILLE PATTERN DOTS-234578 */\n#define XK_braille_dots_1234578       0x10028df  /* U+28DF BRAILLE PATTERN DOTS-1234578 */\n#define XK_braille_dots_678           0x10028e0  /* U+28E0 BRAILLE PATTERN DOTS-678 */\n#define XK_braille_dots_1678          0x10028e1  /* U+28E1 BRAILLE PATTERN DOTS-1678 */\n#define XK_braille_dots_2678          0x10028e2  /* U+28E2 BRAILLE PATTERN DOTS-2678 */\n#define XK_braille_dots_12678         0x10028e3  /* U+28E3 BRAILLE PATTERN DOTS-12678 */\n#define XK_braille_dots_3678          0x10028e4  /* U+28E4 BRAILLE PATTERN DOTS-3678 */\n#define XK_braille_dots_13678         0x10028e5  /* U+28E5 BRAILLE PATTERN DOTS-13678 */\n#define XK_braille_dots_23678         0x10028e6  /* U+28E6 BRAILLE PATTERN DOTS-23678 */\n#define XK_braille_dots_123678        0x10028e7  /* U+28E7 BRAILLE PATTERN DOTS-123678 */\n#define XK_braille_dots_4678          0x10028e8  /* U+28E8 BRAILLE PATTERN DOTS-4678 */\n#define XK_braille_dots_14678         0x10028e9  /* U+28E9 BRAILLE PATTERN DOTS-14678 */\n#define XK_braille_dots_24678         0x10028ea  /* U+28EA BRAILLE PATTERN DOTS-24678 */\n#define XK_braille_dots_124678        0x10028eb  /* U+28EB BRAILLE PATTERN DOTS-124678 */\n#define XK_braille_dots_34678         0x10028ec  /* U+28EC BRAILLE PATTERN DOTS-34678 */\n#define XK_braille_dots_134678        0x10028ed  /* U+28ED BRAILLE PATTERN DOTS-134678 */\n#define XK_braille_dots_234678        0x10028ee  /* U+28EE BRAILLE PATTERN DOTS-234678 */\n#define XK_braille_dots_1234678       0x10028ef  /* U+28EF BRAILLE PATTERN DOTS-1234678 */\n#define XK_braille_dots_5678          0x10028f0  /* U+28F0 BRAILLE PATTERN DOTS-5678 */\n#define XK_braille_dots_15678         0x10028f1  /* U+28F1 BRAILLE PATTERN DOTS-15678 */\n#define XK_braille_dots_25678         0x10028f2  /* U+28F2 BRAILLE PATTERN DOTS-25678 */\n#define XK_braille_dots_125678        0x10028f3  /* U+28F3 BRAILLE PATTERN DOTS-125678 */\n#define XK_braille_dots_35678         0x10028f4  /* U+28F4 BRAILLE PATTERN DOTS-35678 */\n#define XK_braille_dots_135678        0x10028f5  /* U+28F5 BRAILLE PATTERN DOTS-135678 */\n#define XK_braille_dots_235678        0x10028f6  /* U+28F6 BRAILLE PATTERN DOTS-235678 */\n#define XK_braille_dots_1235678       0x10028f7  /* U+28F7 BRAILLE PATTERN DOTS-1235678 */\n#define XK_braille_dots_45678         0x10028f8  /* U+28F8 BRAILLE PATTERN DOTS-45678 */\n#define XK_braille_dots_145678        0x10028f9  /* U+28F9 BRAILLE PATTERN DOTS-145678 */\n#define XK_braille_dots_245678        0x10028fa  /* U+28FA BRAILLE PATTERN DOTS-245678 */\n#define XK_braille_dots_1245678       0x10028fb  /* U+28FB BRAILLE PATTERN DOTS-1245678 */\n#define XK_braille_dots_345678        0x10028fc  /* U+28FC BRAILLE PATTERN DOTS-345678 */\n#define XK_braille_dots_1345678       0x10028fd  /* U+28FD BRAILLE PATTERN DOTS-1345678 */\n#define XK_braille_dots_2345678       0x10028fe  /* U+28FE BRAILLE PATTERN DOTS-2345678 */\n#define XK_braille_dots_12345678      0x10028ff  /* U+28FF BRAILLE PATTERN DOTS-12345678 */\n#endif /* XK_BRAILLE */\n\n/*\n * Sinhala (http://unicode.org/charts/PDF/U0D80.pdf)\n * http://www.nongnu.org/sinhala/doc/transliteration/sinhala-transliteration_6.html\n */\n\n#ifdef XK_SINHALA\n#define XK_Sinh_ng                    0x1000d82  /* U+0D82 SINHALA SIGN ANUSVARAYA */\n#define XK_Sinh_h2                    0x1000d83  /* U+0D83 SINHALA SIGN VISARGAYA */\n#define XK_Sinh_a                     0x1000d85  /* U+0D85 SINHALA LETTER AYANNA */\n#define XK_Sinh_aa                    0x1000d86  /* U+0D86 SINHALA LETTER AAYANNA */\n#define XK_Sinh_ae                    0x1000d87  /* U+0D87 SINHALA LETTER AEYANNA */\n#define XK_Sinh_aee                   0x1000d88  /* U+0D88 SINHALA LETTER AEEYANNA */\n#define XK_Sinh_i                     0x1000d89  /* U+0D89 SINHALA LETTER IYANNA */\n#define XK_Sinh_ii                    0x1000d8a  /* U+0D8A SINHALA LETTER IIYANNA */\n#define XK_Sinh_u                     0x1000d8b  /* U+0D8B SINHALA LETTER UYANNA */\n#define XK_Sinh_uu                    0x1000d8c  /* U+0D8C SINHALA LETTER UUYANNA */\n#define XK_Sinh_ri                    0x1000d8d  /* U+0D8D SINHALA LETTER IRUYANNA */\n#define XK_Sinh_rii                   0x1000d8e  /* U+0D8E SINHALA LETTER IRUUYANNA */\n#define XK_Sinh_lu                    0x1000d8f  /* U+0D8F SINHALA LETTER ILUYANNA */\n#define XK_Sinh_luu                   0x1000d90  /* U+0D90 SINHALA LETTER ILUUYANNA */\n#define XK_Sinh_e                     0x1000d91  /* U+0D91 SINHALA LETTER EYANNA */\n#define XK_Sinh_ee                    0x1000d92  /* U+0D92 SINHALA LETTER EEYANNA */\n#define XK_Sinh_ai                    0x1000d93  /* U+0D93 SINHALA LETTER AIYANNA */\n#define XK_Sinh_o                     0x1000d94  /* U+0D94 SINHALA LETTER OYANNA */\n#define XK_Sinh_oo                    0x1000d95  /* U+0D95 SINHALA LETTER OOYANNA */\n#define XK_Sinh_au                    0x1000d96  /* U+0D96 SINHALA LETTER AUYANNA */\n#define XK_Sinh_ka                    0x1000d9a  /* U+0D9A SINHALA LETTER ALPAPRAANA KAYANNA */\n#define XK_Sinh_kha                   0x1000d9b  /* U+0D9B SINHALA LETTER MAHAAPRAANA KAYANNA */\n#define XK_Sinh_ga                    0x1000d9c  /* U+0D9C SINHALA LETTER ALPAPRAANA GAYANNA */\n#define XK_Sinh_gha                   0x1000d9d  /* U+0D9D SINHALA LETTER MAHAAPRAANA GAYANNA */\n#define XK_Sinh_ng2                   0x1000d9e  /* U+0D9E SINHALA LETTER KANTAJA NAASIKYAYA */\n#define XK_Sinh_nga                   0x1000d9f  /* U+0D9F SINHALA LETTER SANYAKA GAYANNA */\n#define XK_Sinh_ca                    0x1000da0  /* U+0DA0 SINHALA LETTER ALPAPRAANA CAYANNA */\n#define XK_Sinh_cha                   0x1000da1  /* U+0DA1 SINHALA LETTER MAHAAPRAANA CAYANNA */\n#define XK_Sinh_ja                    0x1000da2  /* U+0DA2 SINHALA LETTER ALPAPRAANA JAYANNA */\n#define XK_Sinh_jha                   0x1000da3  /* U+0DA3 SINHALA LETTER MAHAAPRAANA JAYANNA */\n#define XK_Sinh_nya                   0x1000da4  /* U+0DA4 SINHALA LETTER TAALUJA NAASIKYAYA */\n#define XK_Sinh_jnya                  0x1000da5  /* U+0DA5 SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA */\n#define XK_Sinh_nja                   0x1000da6  /* U+0DA6 SINHALA LETTER SANYAKA JAYANNA */\n#define XK_Sinh_tta                   0x1000da7  /* U+0DA7 SINHALA LETTER ALPAPRAANA TTAYANNA */\n#define XK_Sinh_ttha                  0x1000da8  /* U+0DA8 SINHALA LETTER MAHAAPRAANA TTAYANNA */\n#define XK_Sinh_dda                   0x1000da9  /* U+0DA9 SINHALA LETTER ALPAPRAANA DDAYANNA */\n#define XK_Sinh_ddha                  0x1000daa  /* U+0DAA SINHALA LETTER MAHAAPRAANA DDAYANNA */\n#define XK_Sinh_nna                   0x1000dab  /* U+0DAB SINHALA LETTER MUURDHAJA NAYANNA */\n#define XK_Sinh_ndda                  0x1000dac  /* U+0DAC SINHALA LETTER SANYAKA DDAYANNA */\n#define XK_Sinh_tha                   0x1000dad  /* U+0DAD SINHALA LETTER ALPAPRAANA TAYANNA */\n#define XK_Sinh_thha                  0x1000dae  /* U+0DAE SINHALA LETTER MAHAAPRAANA TAYANNA */\n#define XK_Sinh_dha                   0x1000daf  /* U+0DAF SINHALA LETTER ALPAPRAANA DAYANNA */\n#define XK_Sinh_dhha                  0x1000db0  /* U+0DB0 SINHALA LETTER MAHAAPRAANA DAYANNA */\n#define XK_Sinh_na                    0x1000db1  /* U+0DB1 SINHALA LETTER DANTAJA NAYANNA */\n#define XK_Sinh_ndha                  0x1000db3  /* U+0DB3 SINHALA LETTER SANYAKA DAYANNA */\n#define XK_Sinh_pa                    0x1000db4  /* U+0DB4 SINHALA LETTER ALPAPRAANA PAYANNA */\n#define XK_Sinh_pha                   0x1000db5  /* U+0DB5 SINHALA LETTER MAHAAPRAANA PAYANNA */\n#define XK_Sinh_ba                    0x1000db6  /* U+0DB6 SINHALA LETTER ALPAPRAANA BAYANNA */\n#define XK_Sinh_bha                   0x1000db7  /* U+0DB7 SINHALA LETTER MAHAAPRAANA BAYANNA */\n#define XK_Sinh_ma                    0x1000db8  /* U+0DB8 SINHALA LETTER MAYANNA */\n#define XK_Sinh_mba                   0x1000db9  /* U+0DB9 SINHALA LETTER AMBA BAYANNA */\n#define XK_Sinh_ya                    0x1000dba  /* U+0DBA SINHALA LETTER YAYANNA */\n#define XK_Sinh_ra                    0x1000dbb  /* U+0DBB SINHALA LETTER RAYANNA */\n#define XK_Sinh_la                    0x1000dbd  /* U+0DBD SINHALA LETTER DANTAJA LAYANNA */\n#define XK_Sinh_va                    0x1000dc0  /* U+0DC0 SINHALA LETTER VAYANNA */\n#define XK_Sinh_sha                   0x1000dc1  /* U+0DC1 SINHALA LETTER TAALUJA SAYANNA */\n#define XK_Sinh_ssha                  0x1000dc2  /* U+0DC2 SINHALA LETTER MUURDHAJA SAYANNA */\n#define XK_Sinh_sa                    0x1000dc3  /* U+0DC3 SINHALA LETTER DANTAJA SAYANNA */\n#define XK_Sinh_ha                    0x1000dc4  /* U+0DC4 SINHALA LETTER HAYANNA */\n#define XK_Sinh_lla                   0x1000dc5  /* U+0DC5 SINHALA LETTER MUURDHAJA LAYANNA */\n#define XK_Sinh_fa                    0x1000dc6  /* U+0DC6 SINHALA LETTER FAYANNA */\n#define XK_Sinh_al                    0x1000dca  /* U+0DCA SINHALA SIGN AL-LAKUNA */\n#define XK_Sinh_aa2                   0x1000dcf  /* U+0DCF SINHALA VOWEL SIGN AELA-PILLA */\n#define XK_Sinh_ae2                   0x1000dd0  /* U+0DD0 SINHALA VOWEL SIGN KETTI AEDA-PILLA */\n#define XK_Sinh_aee2                  0x1000dd1  /* U+0DD1 SINHALA VOWEL SIGN DIGA AEDA-PILLA */\n#define XK_Sinh_i2                    0x1000dd2  /* U+0DD2 SINHALA VOWEL SIGN KETTI IS-PILLA */\n#define XK_Sinh_ii2                   0x1000dd3  /* U+0DD3 SINHALA VOWEL SIGN DIGA IS-PILLA */\n#define XK_Sinh_u2                    0x1000dd4  /* U+0DD4 SINHALA VOWEL SIGN KETTI PAA-PILLA */\n#define XK_Sinh_uu2                   0x1000dd6  /* U+0DD6 SINHALA VOWEL SIGN DIGA PAA-PILLA */\n#define XK_Sinh_ru2                   0x1000dd8  /* U+0DD8 SINHALA VOWEL SIGN GAETTA-PILLA */\n#define XK_Sinh_e2                    0x1000dd9  /* U+0DD9 SINHALA VOWEL SIGN KOMBUVA */\n#define XK_Sinh_ee2                   0x1000dda  /* U+0DDA SINHALA VOWEL SIGN DIGA KOMBUVA */\n#define XK_Sinh_ai2                   0x1000ddb  /* U+0DDB SINHALA VOWEL SIGN KOMBU DEKA */\n#define XK_Sinh_o2                    0x1000ddc  /* U+0DDC SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA */\n#define XK_Sinh_oo2                   0x1000ddd  /* U+0DDD SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA */\n#define XK_Sinh_au2                   0x1000dde  /* U+0DDE SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA */\n#define XK_Sinh_lu2                   0x1000ddf  /* U+0DDF SINHALA VOWEL SIGN GAYANUKITTA */\n#define XK_Sinh_ruu2                  0x1000df2  /* U+0DF2 SINHALA VOWEL SIGN DIGA GAETTA-PILLA */\n#define XK_Sinh_luu2                  0x1000df3  /* U+0DF3 SINHALA VOWEL SIGN DIGA GAYANUKITTA */\n#define XK_Sinh_kunddaliya            0x1000df4  /* U+0DF4 SINHALA PUNCTUATION KUNDDALIYA */\n#endif /* XK_SINHALA */\n"
  },
  {
    "path": "common/rfb/ks_tables.h",
    "content": "/* This file is generated from keysymdef.h. */\n/* Do not edit. */\n\n#ifdef NEEDKTABLE\nconst unsigned char _XkeyTable[] = {\n0,\n0x80, 0xaa, 0x00, 0x00, 0x00, 0x00, 'V','o','i','d','S','y','m','b','o','l',0,\n0xa3, 0xff, 0x00, 0x00, 0xff, 0x08, 'B','a','c','k','S','p','a','c','e',0,\n0x02, 0x74, 0x00, 0x00, 0xff, 0x09, 'T','a','b',0,\n0x5a, 0x42, 0x00, 0x00, 0xff, 0x0a, 'L','i','n','e','f','e','e','d',0,\n0x0a, 0x58, 0x00, 0x00, 0xff, 0x0b, 'C','l','e','a','r',0,\n0x17, 0x56, 0x00, 0x00, 0xff, 0x0d, 'R','e','t','u','r','n',0,\n0x0b, 0x27, 0x00, 0x00, 0xff, 0x13, 'P','a','u','s','e',0,\n0xef, 0x3d, 0x00, 0x00, 0xff, 0x14, 'S','c','r','o','l','l','_','L','o','c','k',0,\n0x30, 0x8b, 0x00, 0x00, 0xff, 0x15, 'S','y','s','_','R','e','q',0,\n0x15, 0xb1, 0x00, 0x00, 0xff, 0x1b, 'E','s','c','a','p','e',0,\n0x15, 0x11, 0x00, 0x00, 0xff, 0xff, 'D','e','l','e','t','e',0,\n0xbd, 0x77, 0x00, 0x00, 0xff, 0x20, 'M','u','l','t','i','_','k','e','y',0,\n0xad, 0x3e, 0x00, 0x00, 0xff, 0x37, 'C','o','d','e','i','n','p','u','t',0,\n0x1a, 0x01, 0x00, 0x00, 0xff, 0x3c, 'S','i','n','g','l','e','C','a','n','d','i','d','a','t','e',0,\n0x32, 0x01, 0x00, 0x00, 0xff, 0x3d, 'M','u','l','t','i','p','l','e','C','a','n','d','i','d','a','t','e',0,\n0x6a, 0x01, 0x00, 0x00, 0xff, 0x3e, 'P','r','e','v','i','o','u','s','C','a','n','d','i','d','a','t','e',0,\n0x0a, 0xad, 0x00, 0x00, 0xff, 0x21, 'K','a','n','j','i',0,\n0x5d, 0x5c, 0x00, 0x00, 0xff, 0x22, 'M','u','h','e','n','k','a','n',0,\n0xbe, 0xc1, 0x00, 0x00, 0xff, 0x23, 'H','e','n','k','a','n','_','M','o','d','e',0,\n0x15, 0x9c, 0x00, 0x00, 0xff, 0x23, 'H','e','n','k','a','n',0,\n0x17, 0x59, 0x00, 0x00, 0xff, 0x24, 'R','o','m','a','j','i',0,\n0x58, 0x89, 0x00, 0x00, 0xff, 0x25, 'H','i','r','a','g','a','n','a',0,\n0x58, 0x69, 0x00, 0x00, 0xff, 0x26, 'K','a','t','a','k','a','n','a',0,\n0xc9, 0x69, 0x00, 0x00, 0xff, 0x27, 'H','i','r','a','g','a','n','a','_','K','a','t','a','k','a','n','a',0,\n0x30, 0x27, 0x00, 0x00, 0xff, 0x28, 'Z','e','n','k','a','k','u',0,\n0x2b, 0x27, 0x00, 0x00, 0xff, 0x29, 'H','a','n','k','a','k','u',0,\n0x81, 0xa7, 0x00, 0x00, 0xff, 0x2a, 'Z','e','n','k','a','k','u','_','H','a','n','k','a','k','u',0,\n0x30, 0xc7, 0x00, 0x00, 0xff, 0x2b, 'T','o','u','r','o','k','u',0,\n0x16, 0x75, 0x00, 0x00, 0xff, 0x2c, 'M','a','s','s','y','o',0,\n0xae, 0x5d, 0x00, 0x00, 0xff, 0x2d, 'K','a','n','a','_','L','o','c','k',0,\n0x5d, 0x74, 0x00, 0x00, 0xff, 0x2e, 'K','a','n','a','_','S','h','i','f','t',0,\n0x60, 0xf4, 0x00, 0x00, 0xff, 0x2f, 'E','i','s','u','_','S','h','i','f','t',0,\n0xc6, 0xc1, 0x00, 0x00, 0xff, 0x30, 'E','i','s','u','_','t','o','g','g','l','e',0,\n0x82, 0xef, 0x00, 0x00, 0xff, 0x37, 'K','a','n','j','i','_','B','a','n','g','o','u',0,\n0x5f, 0x43, 0x00, 0x00, 0xff, 0x3d, 'Z','e','n','_','K','o','h','o',0,\n0x56, 0xa3, 0x00, 0x00, 0xff, 0x3e, 'M','a','e','_','K','o','h','o',0,\n0x05, 0x3b, 0x00, 0x00, 0xff, 0x50, 'H','o','m','e',0,\n0x05, 0x34, 0x00, 0x00, 0xff, 0x51, 'L','e','f','t',0,\n0x01, 0x1a, 0x00, 0x00, 0xff, 0x52, 'U','p',0,\n0x0b, 0x48, 0x00, 0x00, 0xff, 0x53, 'R','i','g','h','t',0,\n0x05, 0x38, 0x00, 0x00, 0xff, 0x54, 'D','o','w','n',0,\n0x0b, 0x84, 0x00, 0x00, 0xff, 0x55, 'P','r','i','o','r',0,\n0x2c, 0x4e, 0x00, 0x00, 0xff, 0x55, 'P','a','g','e','_','U','p',0,\n0x05, 0x68, 0x00, 0x00, 0xff, 0x56, 'N','e','x','t',0,\n0xb2, 0x08, 0x00, 0x00, 0xff, 0x56, 'P','a','g','e','_','D','o','w','n',0,\n0x02, 0x54, 0x00, 0x00, 0xff, 0x57, 'E','n','d',0,\n0x0a, 0x24, 0x00, 0x00, 0xff, 0x58, 'B','e','g','i','n',0,\n0x16, 0xde, 0x00, 0x00, 0xff, 0x60, 'S','e','l','e','c','t',0,\n0x0b, 0x84, 0x00, 0x00, 0xff, 0x61, 'P','r','i','n','t',0,\n0x2c, 0xc9, 0x00, 0x00, 0xff, 0x62, 'E','x','e','c','u','t','e',0,\n0x16, 0x84, 0x00, 0x00, 0xff, 0x63, 'I','n','s','e','r','t',0,\n0x05, 0x97, 0x00, 0x00, 0xff, 0x65, 'U','n','d','o',0,\n0x05, 0x5b, 0x00, 0x00, 0xff, 0x66, 'R','e','d','o',0,\n0x05, 0x4d, 0x00, 0x00, 0xff, 0x67, 'M','e','n','u',0,\n0x05, 0x14, 0x00, 0x00, 0xff, 0x68, 'F','i','n','d',0,\n0x14, 0xa2, 0x00, 0x00, 0xff, 0x69, 'C','a','n','c','e','l',0,\n0x05, 0x1c, 0x00, 0x00, 0xff, 0x6a, 'H','e','l','p',0,\n0x0a, 0x71, 0x00, 0x00, 0xff, 0x6b, 'B','r','e','a','k',0,\n0xdc, 0x56, 0x00, 0x00, 0xff, 0x7e, 'M','o','d','e','_','s','w','i','t','c','h',0,\n0xbf, 0xd6, 0x00, 0x00, 0xff, 0x7e, 's','c','r','i','p','t','_','s','w','i','t','c','h',0,\n0x5d, 0x1d, 0x00, 0x00, 0xff, 0x7f, 'N','u','m','_','L','o','c','k',0,\n0x50, 0xbf, 0x00, 0x00, 0xff, 0x80, 'K','P','_','S','p','a','c','e',0,\n0x13, 0xcc, 0x00, 0x00, 0xff, 0x89, 'K','P','_','T','a','b',0,\n0x50, 0x2c, 0x00, 0x00, 0xff, 0x8d, 'K','P','_','E','n','t','e','r',0,\n0x09, 0x69, 0x00, 0x00, 0xff, 0x91, 'K','P','_','F','1',0,\n0x09, 0x6a, 0x00, 0x00, 0xff, 0x92, 'K','P','_','F','2',0,\n0x09, 0x6b, 0x00, 0x00, 0xff, 0x93, 'K','P','_','F','3',0,\n0x09, 0x6c, 0x00, 0x00, 0xff, 0x94, 'K','P','_','F','4',0,\n0x27, 0xeb, 0x00, 0x00, 0xff, 0x95, 'K','P','_','H','o','m','e',0,\n0x27, 0xe4, 0x00, 0x00, 0xff, 0x96, 'K','P','_','L','e','f','t',0,\n0x09, 0xc6, 0x00, 0x00, 0xff, 0x97, 'K','P','_','U','p',0,\n0x50, 0xa8, 0x00, 0x00, 0xff, 0x98, 'K','P','_','R','i','g','h','t',0,\n0x27, 0xe8, 0x00, 0x00, 0xff, 0x99, 'K','P','_','D','o','w','n',0,\n0x50, 0xe4, 0x00, 0x00, 0xff, 0x9a, 'K','P','_','P','r','i','o','r',0,\n0x41, 0xce, 0x00, 0x00, 0xff, 0x9a, 'K','P','_','P','a','g','e','_','U','p',0,\n0x28, 0x18, 0x00, 0x00, 0xff, 0x9b, 'K','P','_','N','e','x','t',0,\n0x08, 0x08, 0x00, 0x00, 0xff, 0x9b, 'K','P','_','P','a','g','e','_','D','o','w','n',0,\n0x13, 0xac, 0x00, 0x00, 0xff, 0x9c, 'K','P','_','E','n','d',0,\n0x4f, 0x84, 0x00, 0x00, 0xff, 0x9d, 'K','P','_','B','e','g','i','n',0,\n0xa1, 0x44, 0x00, 0x00, 0xff, 0x9e, 'K','P','_','I','n','s','e','r','t',0,\n0x9f, 0xd1, 0x00, 0x00, 0xff, 0x9f, 'K','P','_','D','e','l','e','t','e',0,\n0x50, 0x3a, 0x00, 0x00, 0xff, 0xbd, 'K','P','_','E','q','u','a','l',0,\n0x89, 0xd9, 0x00, 0x00, 0xff, 0xaa, 'K','P','_','M','u','l','t','i','p','l','y',0,\n0x13, 0x88, 0x00, 0x00, 0xff, 0xab, 'K','P','_','A','d','d',0,\n0x10, 0xe8, 0x00, 0x00, 0xff, 0xac, 'K','P','_','S','e','p','a','r','a','t','o','r',0,\n0x8b, 0x8e, 0x00, 0x00, 0xff, 0xad, 'K','P','_','S','u','b','t','r','a','c','t',0,\n0x3f, 0x7a, 0x00, 0x00, 0xff, 0xae, 'K','P','_','D','e','c','i','m','a','l',0,\n0xa0, 0x51, 0x00, 0x00, 0xff, 0xaf, 'K','P','_','D','i','v','i','d','e',0,\n0x04, 0x86, 0x00, 0x00, 0xff, 0xb0, 'K','P','_','0',0,\n0x04, 0x87, 0x00, 0x00, 0xff, 0xb1, 'K','P','_','1',0,\n0x04, 0x88, 0x00, 0x00, 0xff, 0xb2, 'K','P','_','2',0,\n0x04, 0x89, 0x00, 0x00, 0xff, 0xb3, 'K','P','_','3',0,\n0x04, 0x8a, 0x00, 0x00, 0xff, 0xb4, 'K','P','_','4',0,\n0x04, 0x8b, 0x00, 0x00, 0xff, 0xb5, 'K','P','_','5',0,\n0x04, 0x8c, 0x00, 0x00, 0xff, 0xb6, 'K','P','_','6',0,\n0x04, 0x8d, 0x00, 0x00, 0xff, 0xb7, 'K','P','_','7',0,\n0x04, 0x8e, 0x00, 0x00, 0xff, 0xb8, 'K','P','_','8',0,\n0x04, 0x8f, 0x00, 0x00, 0xff, 0xb9, 'K','P','_','9',0,\n0x00, 0xbd, 0x00, 0x00, 0xff, 0xbe, 'F','1',0,\n0x00, 0xbe, 0x00, 0x00, 0xff, 0xbf, 'F','2',0,\n0x00, 0xbf, 0x00, 0x00, 0xff, 0xc0, 'F','3',0,\n0x00, 0xc0, 0x00, 0x00, 0xff, 0xc1, 'F','4',0,\n0x00, 0xc1, 0x00, 0x00, 0xff, 0xc2, 'F','5',0,\n0x00, 0xc2, 0x00, 0x00, 0xff, 0xc3, 'F','6',0,\n0x00, 0xc3, 0x00, 0x00, 0xff, 0xc4, 'F','7',0,\n0x00, 0xc4, 0x00, 0x00, 0xff, 0xc5, 'F','8',0,\n0x00, 0xc5, 0x00, 0x00, 0xff, 0xc6, 'F','9',0,\n0x01, 0xaa, 0x00, 0x00, 0xff, 0xc7, 'F','1','0',0,\n0x01, 0xab, 0x00, 0x00, 0xff, 0xc8, 'F','1','1',0,\n0x00, 0xc9, 0x00, 0x00, 0xff, 0xc8, 'L','1',0,\n0x01, 0xac, 0x00, 0x00, 0xff, 0xc9, 'F','1','2',0,\n0x00, 0xca, 0x00, 0x00, 0xff, 0xc9, 'L','2',0,\n0x01, 0xad, 0x00, 0x00, 0xff, 0xca, 'F','1','3',0,\n0x00, 0xcb, 0x00, 0x00, 0xff, 0xca, 'L','3',0,\n0x01, 0xae, 0x00, 0x00, 0xff, 0xcb, 'F','1','4',0,\n0x00, 0xcc, 0x00, 0x00, 0xff, 0xcb, 'L','4',0,\n0x01, 0xaf, 0x00, 0x00, 0xff, 0xcc, 'F','1','5',0,\n0x00, 0xcd, 0x00, 0x00, 0xff, 0xcc, 'L','5',0,\n0x01, 0xb0, 0x00, 0x00, 0xff, 0xcd, 'F','1','6',0,\n0x00, 0xce, 0x00, 0x00, 0xff, 0xcd, 'L','6',0,\n0x01, 0xb1, 0x00, 0x00, 0xff, 0xce, 'F','1','7',0,\n0x00, 0xcf, 0x00, 0x00, 0xff, 0xce, 'L','7',0,\n0x01, 0xb2, 0x00, 0x00, 0xff, 0xcf, 'F','1','8',0,\n0x00, 0xd0, 0x00, 0x00, 0xff, 0xcf, 'L','8',0,\n0x01, 0xb3, 0x00, 0x00, 0xff, 0xd0, 'F','1','9',0,\n0x00, 0xd1, 0x00, 0x00, 0xff, 0xd0, 'L','9',0,\n0x01, 0xac, 0x00, 0x00, 0xff, 0xd1, 'F','2','0',0,\n0x01, 0xc2, 0x00, 0x00, 0xff, 0xd1, 'L','1','0',0,\n0x01, 0xad, 0x00, 0x00, 0xff, 0xd2, 'F','2','1',0,\n0x00, 0xd5, 0x00, 0x00, 0xff, 0xd2, 'R','1',0,\n0x01, 0xae, 0x00, 0x00, 0xff, 0xd3, 'F','2','2',0,\n0x00, 0xd6, 0x00, 0x00, 0xff, 0xd3, 'R','2',0,\n0x01, 0xaf, 0x00, 0x00, 0xff, 0xd4, 'F','2','3',0,\n0x00, 0xd7, 0x00, 0x00, 0xff, 0xd4, 'R','3',0,\n0x01, 0xb0, 0x00, 0x00, 0xff, 0xd5, 'F','2','4',0,\n0x00, 0xd8, 0x00, 0x00, 0xff, 0xd5, 'R','4',0,\n0x01, 0xb1, 0x00, 0x00, 0xff, 0xd6, 'F','2','5',0,\n0x00, 0xd9, 0x00, 0x00, 0xff, 0xd6, 'R','5',0,\n0x01, 0xb2, 0x00, 0x00, 0xff, 0xd7, 'F','2','6',0,\n0x00, 0xda, 0x00, 0x00, 0xff, 0xd7, 'R','6',0,\n0x01, 0xb3, 0x00, 0x00, 0xff, 0xd8, 'F','2','7',0,\n0x00, 0xdb, 0x00, 0x00, 0xff, 0xd8, 'R','7',0,\n0x01, 0xb4, 0x00, 0x00, 0xff, 0xd9, 'F','2','8',0,\n0x00, 0xdc, 0x00, 0x00, 0xff, 0xd9, 'R','8',0,\n0x01, 0xb5, 0x00, 0x00, 0xff, 0xda, 'F','2','9',0,\n0x00, 0xdd, 0x00, 0x00, 0xff, 0xda, 'R','9',0,\n0x01, 0xae, 0x00, 0x00, 0xff, 0xdb, 'F','3','0',0,\n0x01, 0xda, 0x00, 0x00, 0xff, 0xdb, 'R','1','0',0,\n0x01, 0xaf, 0x00, 0x00, 0xff, 0xdc, 'F','3','1',0,\n0x01, 0xdb, 0x00, 0x00, 0xff, 0xdc, 'R','1','1',0,\n0x01, 0xb0, 0x00, 0x00, 0xff, 0xdd, 'F','3','2',0,\n0x01, 0xdc, 0x00, 0x00, 0xff, 0xdd, 'R','1','2',0,\n0x01, 0xb1, 0x00, 0x00, 0xff, 0xde, 'F','3','3',0,\n0x01, 0xdd, 0x00, 0x00, 0xff, 0xde, 'R','1','3',0,\n0x01, 0xb2, 0x00, 0x00, 0xff, 0xdf, 'F','3','4',0,\n0x01, 0xde, 0x00, 0x00, 0xff, 0xdf, 'R','1','4',0,\n0x01, 0xb3, 0x00, 0x00, 0xff, 0xe0, 'F','3','5',0,\n0x01, 0xdf, 0x00, 0x00, 0xff, 0xe0, 'R','1','5',0,\n0x2e, 0x5a, 0x00, 0x00, 0xff, 0xe1, 'S','h','i','f','t','_','L',0,\n0x2e, 0x60, 0x00, 0x00, 0xff, 0xe2, 'S','h','i','f','t','_','R',0,\n0xb1, 0xd2, 0x00, 0x00, 0xff, 0xe3, 'C','o','n','t','r','o','l','_','L',0,\n0xb1, 0xd8, 0x00, 0x00, 0xff, 0xe4, 'C','o','n','t','r','o','l','_','R',0,\n0xa9, 0x1d, 0x00, 0x00, 0xff, 0xe5, 'C','a','p','s','_','L','o','c','k',0,\n0x75, 0xbd, 0x00, 0x00, 0xff, 0xe6, 'S','h','i','f','t','_','L','o','c','k',0,\n0x16, 0x1e, 0x00, 0x00, 0xff, 0xe7, 'M','e','t','a','_','L',0,\n0x16, 0x24, 0x00, 0x00, 0xff, 0xe8, 'M','e','t','a','_','R',0,\n0x0a, 0x4a, 0x00, 0x00, 0xff, 0xe9, 'A','l','t','_','L',0,\n0x0a, 0x50, 0x00, 0x00, 0xff, 0xea, 'A','l','t','_','R',0,\n0x30, 0x5a, 0x00, 0x00, 0xff, 0xeb, 'S','u','p','e','r','_','L',0,\n0x30, 0x60, 0x00, 0x00, 0xff, 0xec, 'S','u','p','e','r','_','R',0,\n0x2e, 0x1a, 0x00, 0x00, 0xff, 0xed, 'H','y','p','e','r','_','L',0,\n0x2e, 0x20, 0x00, 0x00, 0xff, 0xee, 'H','y','p','e','r','_','R',0,\n0x4e, 0x5d, 0x00, 0x00, 0xfe, 0x01, 'I','S','O','_','L','o','c','k',0,\n0xae, 0x26, 0x00, 0x00, 0xfe, 0x02, 'I','S','O','_','L','e','v','e','l','2','_','L','a','t','c','h',0,\n0xae, 0xf4, 0x00, 0x00, 0xfe, 0x03, 'I','S','O','_','L','e','v','e','l','3','_','S','h','i','f','t',0,\n0xae, 0x66, 0x00, 0x00, 0xfe, 0x04, 'I','S','O','_','L','e','v','e','l','3','_','L','a','t','c','h',0,\n0x57, 0x1d, 0x00, 0x00, 0xfe, 0x05, 'I','S','O','_','L','e','v','e','l','3','_','L','o','c','k',0,\n0xaf, 0x74, 0x00, 0x00, 0xfe, 0x11, 'I','S','O','_','L','e','v','e','l','5','_','S','h','i','f','t',0,\n0xae, 0xe6, 0x00, 0x00, 0xfe, 0x12, 'I','S','O','_','L','e','v','e','l','5','_','L','a','t','c','h',0,\n0x57, 0x5d, 0x00, 0x00, 0xfe, 0x13, 'I','S','O','_','L','e','v','e','l','5','_','L','o','c','k',0,\n0x64, 0xb4, 0x00, 0x00, 0xff, 0x7e, 'I','S','O','_','G','r','o','u','p','_','S','h','i','f','t',0,\n0x64, 0x26, 0x00, 0x00, 0xfe, 0x06, 'I','S','O','_','G','r','o','u','p','_','L','a','t','c','h',0,\n0xb1, 0xfd, 0x00, 0x00, 0xfe, 0x07, 'I','S','O','_','G','r','o','u','p','_','L','o','c','k',0,\n0xb4, 0xf6, 0x00, 0x00, 0xfe, 0x08, 'I','S','O','_','N','e','x','t','_','G','r','o','u','p',0,\n0xa9, 0xfd, 0x00, 0x00, 0xfe, 0x09, 'I','S','O','_','N','e','x','t','_','G','r','o','u','p','_','L','o','c','k',0,\n0xbc, 0xf6, 0x00, 0x00, 0xfe, 0x0a, 'I','S','O','_','P','r','e','v','_','G','r','o','u','p',0,\n0xa9, 0xfd, 0x00, 0x00, 0xfe, 0x0b, 'I','S','O','_','P','r','e','v','_','G','r','o','u','p','_','L','o','c','k',0,\n0x51, 0x76, 0x00, 0x00, 0xfe, 0x0c, 'I','S','O','_','F','i','r','s','t','_','G','r','o','u','p',0,\n0x39, 0xfd, 0x00, 0x00, 0xfe, 0x0d, 'I','S','O','_','F','i','r','s','t','_','G','r','o','u','p','_','L','o','c','k',0,\n0xaa, 0x76, 0x00, 0x00, 0xfe, 0x0e, 'I','S','O','_','L','a','s','t','_','G','r','o','u','p',0,\n0x59, 0xfd, 0x00, 0x00, 0xfe, 0x0f, 'I','S','O','_','L','a','s','t','_','G','r','o','u','p','_','L','o','c','k',0,\n0xe9, 0xac, 0x00, 0x00, 0xfe, 0x20, 'I','S','O','_','L','e','f','t','_','T','a','b',0,\n0xe1, 0x3e, 0x00, 0x00, 0xfe, 0x21, 'I','S','O','_','M','o','v','e','_','L','i','n','e','_','U','p',0,\n0x85, 0xc8, 0x00, 0x00, 0xfe, 0x22, 'I','S','O','_','M','o','v','e','_','L','i','n','e','_','D','o','w','n',0,\n0x8e, 0x3e, 0x00, 0x00, 0xfe, 0x23, 'I','S','O','_','P','a','r','t','i','a','l','_','L','i','n','e','_','U','p',0,\n0x39, 0xc8, 0x00, 0x00, 0xfe, 0x24, 'I','S','O','_','P','a','r','t','i','a','l','_','L','i','n','e','_','D','o','w','n',0,\n0x83, 0x04, 0x00, 0x00, 0xfe, 0x25, 'I','S','O','_','P','a','r','t','i','a','l','_','S','p','a','c','e','_','L','e','f','t',0,\n0x06, 0xe8, 0x00, 0x00, 0xfe, 0x26, 'I','S','O','_','P','a','r','t','i','a','l','_','S','p','a','c','e','_','R','i','g','h','t',0,\n0xe6, 0xa4, 0x00, 0x00, 0xfe, 0x27, 'I','S','O','_','S','e','t','_','M','a','r','g','i','n','_','L','e','f','t',0,\n0xce, 0x28, 0x00, 0x00, 0xfe, 0x28, 'I','S','O','_','S','e','t','_','M','a','r','g','i','n','_','R','i','g','h','t',0,\n0x36, 0xa4, 0x00, 0x00, 0xfe, 0x29, 'I','S','O','_','R','e','l','e','a','s','e','_','M','a','r','g','i','n','_','L','e','f','t',0,\n0x6e, 0x28, 0x00, 0x00, 0xfe, 0x2a, 'I','S','O','_','R','e','l','e','a','s','e','_','M','a','r','g','i','n','_','R','i','g','h','t',0,\n0x48, 0x2b, 0x00, 0x00, 0xfe, 0x2b, 'I','S','O','_','R','e','l','e','a','s','e','_','B','o','t','h','_','M','a','r','g','i','n','s',0,\n0xae, 0xa4, 0x00, 0x00, 0xfe, 0x2c, 'I','S','O','_','F','a','s','t','_','C','u','r','s','o','r','_','L','e','f','t',0,\n0x5e, 0x28, 0x00, 0x00, 0xfe, 0x2d, 'I','S','O','_','F','a','s','t','_','C','u','r','s','o','r','_','R','i','g','h','t',0,\n0xeb, 0x76, 0x00, 0x00, 0xfe, 0x2e, 'I','S','O','_','F','a','s','t','_','C','u','r','s','o','r','_','U','p',0,\n0xae, 0xa8, 0x00, 0x00, 0xfe, 0x2f, 'I','S','O','_','F','a','s','t','_','C','u','r','s','o','r','_','D','o','w','n',0,\n0x81, 0x05, 0x00, 0x00, 0xfe, 0x30, 'I','S','O','_','C','o','n','t','i','n','u','o','u','s','_','U','n','d','e','r','l','i','n','e',0,\n0x81, 0x05, 0x00, 0x00, 0xfe, 0x31, 'I','S','O','_','D','i','s','c','o','n','t','i','n','u','o','u','s','_','U','n','d','e','r','l','i','n','e',0,\n0xd3, 0x25, 0x00, 0x00, 0xfe, 0x32, 'I','S','O','_','E','m','p','h','a','s','i','z','e',0,\n0xe3, 0xde, 0x00, 0x00, 0xfe, 0x33, 'I','S','O','_','C','e','n','t','e','r','_','O','b','j','e','c','t',0,\n0x9c, 0xec, 0x00, 0x00, 0xfe, 0x34, 'I','S','O','_','E','n','t','e','r',0,\n0x8f, 0x35, 0x00, 0x00, 0xfe, 0x50, 'd','e','a','d','_','g','r','a','v','e',0,\n0x8e, 0xa9, 0x00, 0x00, 0xfe, 0x51, 'd','e','a','d','_','a','c','u','t','e',0,\n0xe8, 0x52, 0x00, 0x00, 0xfe, 0x52, 'd','e','a','d','_','c','i','r','c','u','m','f','l','e','x',0,\n0x8f, 0xc5, 0x00, 0x00, 0xfe, 0x53, 'd','e','a','d','_','t','i','l','d','e',0,\n0x00, 0x71, 0x00, 0x00, 0xfe, 0x53, 'd','e','a','d','_','p','e','r','i','s','p','o','m','e','n','i',0,\n0x1e, 0x9c, 0x00, 0x00, 0xfe, 0x54, 'd','e','a','d','_','m','a','c','r','o','n',0,\n0x8e, 0xf5, 0x00, 0x00, 0xfe, 0x55, 'd','e','a','d','_','b','r','e','v','e',0,\n0x77, 0x4a, 0x00, 0x00, 0xfe, 0x56, 'd','e','a','d','_','a','b','o','v','e','d','o','t',0,\n0xf0, 0xb9, 0x00, 0x00, 0xfe, 0x57, 'd','e','a','d','_','d','i','a','e','r','e','s','i','s',0,\n0xef, 0x47, 0x00, 0x00, 0xfe, 0x58, 'd','e','a','d','_','a','b','o','v','e','r','i','n','g',0,\n0xdf, 0xe9, 0x00, 0x00, 0xfe, 0x59, 'd','e','a','d','_','d','o','u','b','l','e','a','c','u','t','e',0,\n0x8e, 0xac, 0x00, 0x00, 0xfe, 0x5a, 'd','e','a','d','_','c','a','r','o','n',0,\n0x3b, 0x51, 0x00, 0x00, 0xfe, 0x5b, 'd','e','a','d','_','c','e','d','i','l','l','a',0,\n0x1f, 0x75, 0x00, 0x00, 0xfe, 0x5c, 'd','e','a','d','_','o','g','o','n','e','k',0,\n0xc7, 0x7d, 0x00, 0x00, 0xfe, 0x5d, 'd','e','a','d','_','i','o','t','a',0,\n0x36, 0x1c, 0x00, 0x00, 0xfe, 0x5e, 'd','e','a','d','_','v','o','i','c','e','d','_','s','o','u','n','d',0,\n0xf6, 0x1c, 0x00, 0x00, 0xfe, 0x5f, 'd','e','a','d','_','s','e','m','i','v','o','i','c','e','d','_','s','o','u','n','d',0,\n0x78, 0x4a, 0x00, 0x00, 0xfe, 0x60, 'd','e','a','d','_','b','e','l','o','w','d','o','t',0,\n0xc7, 0x75, 0x00, 0x00, 0xfe, 0x61, 'd','e','a','d','_','h','o','o','k',0,\n0xc7, 0x7e, 0x00, 0x00, 0xfe, 0x62, 'd','e','a','d','_','h','o','r','n',0,\n0x20, 0xe7, 0x00, 0x00, 0xfe, 0x63, 'd','e','a','d','_','s','t','r','o','k','e',0,\n0xde, 0x37, 0x00, 0x00, 0xfe, 0x64, 'd','e','a','d','_','a','b','o','v','e','c','o','m','m','a',0,\n0x8f, 0xdd, 0x00, 0x00, 0xfe, 0x64, 'd','e','a','d','_','p','s','i','l','i',0,\n0x67, 0xd7, 0x00, 0x00, 0xfe, 0x65, 'd','e','a','d','_','a','b','o','v','e','r','e','v','e','r','s','e','d','c','o','m','m','a',0,\n0x8e, 0xa7, 0x00, 0x00, 0xfe, 0x65, 'd','e','a','d','_','d','a','s','i','a',0,\n0xe0, 0x75, 0x00, 0x00, 0xfe, 0x66, 'd','e','a','d','_','d','o','u','b','l','e','g','r','a','v','e',0,\n0xf1, 0x47, 0x00, 0x00, 0xfe, 0x67, 'd','e','a','d','_','b','e','l','o','w','r','i','n','g',0,\n0xc5, 0x1c, 0x00, 0x00, 0xfe, 0x68, 'd','e','a','d','_','b','e','l','o','w','m','a','c','r','o','n',0,\n0x50, 0x52, 0x00, 0x00, 0xfe, 0x69, 'd','e','a','d','_','b','e','l','o','w','c','i','r','c','u','m','f','l','e','x',0,\n0xe3, 0x05, 0x00, 0x00, 0xfe, 0x6a, 'd','e','a','d','_','b','e','l','o','w','t','i','l','d','e',0,\n0xe2, 0x35, 0x00, 0x00, 0xfe, 0x6b, 'd','e','a','d','_','b','e','l','o','w','b','r','e','v','e',0,\n0x24, 0xb9, 0x00, 0x00, 0xfe, 0x6c, 'd','e','a','d','_','b','e','l','o','w','d','i','a','e','r','e','s','i','s',0,\n0xe0, 0x55, 0x00, 0x00, 0xfe, 0x6d, 'd','e','a','d','_','i','n','v','e','r','t','e','d','b','r','e','v','e',0,\n0xe2, 0x37, 0x00, 0x00, 0xfe, 0x6e, 'd','e','a','d','_','b','e','l','o','w','c','o','m','m','a',0,\n0x7d, 0x3f, 0x00, 0x00, 0xfe, 0x6f, 'd','e','a','d','_','c','u','r','r','e','n','c','y',0,\n0x18, 0x87, 0x00, 0x00, 0xfe, 0x80, 'd','e','a','d','_','a',0,\n0x18, 0x67, 0x00, 0x00, 0xfe, 0x81, 'd','e','a','d','_','A',0,\n0x18, 0x8b, 0x00, 0x00, 0xfe, 0x82, 'd','e','a','d','_','e',0,\n0x18, 0x6b, 0x00, 0x00, 0xfe, 0x83, 'd','e','a','d','_','E',0,\n0x18, 0x8f, 0x00, 0x00, 0xfe, 0x84, 'd','e','a','d','_','i',0,\n0x18, 0x6f, 0x00, 0x00, 0xfe, 0x85, 'd','e','a','d','_','I',0,\n0x18, 0x95, 0x00, 0x00, 0xfe, 0x86, 'd','e','a','d','_','o',0,\n0x18, 0x75, 0x00, 0x00, 0xfe, 0x87, 'd','e','a','d','_','O',0,\n0x18, 0x9b, 0x00, 0x00, 0xfe, 0x88, 'd','e','a','d','_','u',0,\n0x18, 0x7b, 0x00, 0x00, 0xfe, 0x89, 'd','e','a','d','_','U',0,\n0x8f, 0x97, 0x00, 0x00, 0xfe, 0x8a, 'd','e','a','d','_','s','c','h','w','a',0,\n0x8b, 0xb7, 0x00, 0x00, 0xfe, 0x8b, 'd','e','a','d','_','S','C','H','W','A',0,\n0x09, 0x17, 0x00, 0x00, 0xfe, 0x8a, 'd','e','a','d','_','s','m','a','l','l','_','s','c','h','w','a',0,\n0x02, 0x97, 0x00, 0x00, 0xfe, 0x8b, 'd','e','a','d','_','c','a','p','i','t','a','l','_','s','c','h','w','a',0,\n0x8f, 0x29, 0x00, 0x00, 0xfe, 0x8c, 'd','e','a','d','_','g','r','e','e','k',0,\n0x8e, 0xf1, 0x00, 0x00, 0xfe, 0x8d, 'd','e','a','d','_','h','a','m','z','a',0,\n0x1f, 0xac, 0x00, 0x00, 0xfe, 0xd0, 'F','i','r','s','t','_','V','i','r','t','u','a','l','_','S','c','r','e','e','n',0,\n0x1f, 0xac, 0x00, 0x00, 0xfe, 0xd1, 'P','r','e','v','_','V','i','r','t','u','a','l','_','S','c','r','e','e','n',0,\n0x1f, 0xac, 0x00, 0x00, 0xfe, 0xd2, 'N','e','x','t','_','V','i','r','t','u','a','l','_','S','c','r','e','e','n',0,\n0x1f, 0xac, 0x00, 0x00, 0xfe, 0xd4, 'L','a','s','t','_','V','i','r','t','u','a','l','_','S','c','r','e','e','n',0,\n0xe7, 0x94, 0x00, 0x00, 0xfe, 0xd5, 'T','e','r','m','i','n','a','t','e','_','S','e','r','v','e','r',0,\n0xae, 0x0d, 0x00, 0x00, 0xfe, 0x70, 'A','c','c','e','s','s','X','_','E','n','a','b','l','e',0,\n0x1f, 0x8d, 0x00, 0x00, 0xfe, 0x71, 'A','c','c','e','s','s','X','_','F','e','e','d','b','a','c','k','_','E','n','a','b','l','e',0,\n0xa5, 0x8d, 0x00, 0x00, 0xfe, 0x72, 'R','e','p','e','a','t','K','e','y','s','_','E','n','a','b','l','e',0,\n0xbd, 0x8d, 0x00, 0x00, 0xfe, 0x73, 'S','l','o','w','K','e','y','s','_','E','n','a','b','l','e',0,\n0xad, 0x8d, 0x00, 0x00, 0xfe, 0x74, 'B','o','u','n','c','e','K','e','y','s','_','E','n','a','b','l','e',0,\n0xed, 0x8d, 0x00, 0x00, 0xfe, 0x75, 'S','t','i','c','k','y','K','e','y','s','_','E','n','a','b','l','e',0,\n0x0d, 0x8d, 0x00, 0x00, 0xfe, 0x76, 'M','o','u','s','e','K','e','y','s','_','E','n','a','b','l','e',0,\n0x32, 0x0d, 0x00, 0x00, 0xfe, 0x77, 'M','o','u','s','e','K','e','y','s','_','A','c','c','e','l','_','E','n','a','b','l','e',0,\n0x90, 0x8d, 0x00, 0x00, 0xfe, 0x78, 'O','v','e','r','l','a','y','1','_','E','n','a','b','l','e',0,\n0x91, 0x0d, 0x00, 0x00, 0xfe, 0x79, 'O','v','e','r','l','a','y','2','_','E','n','a','b','l','e',0,\n0x09, 0x0d, 0x00, 0x00, 0xfe, 0x7a, 'A','u','d','i','b','l','e','B','e','l','l','_','E','n','a','b','l','e',0,\n0xe8, 0xa4, 0x00, 0x00, 0xfe, 0xe0, 'P','o','i','n','t','e','r','_','L','e','f','t',0,\n0xd2, 0x28, 0x00, 0x00, 0xfe, 0xe1, 'P','o','i','n','t','e','r','_','R','i','g','h','t',0,\n0x79, 0xf6, 0x00, 0x00, 0xfe, 0xe2, 'P','o','i','n','t','e','r','_','U','p',0,\n0xe8, 0xa8, 0x00, 0x00, 0xfe, 0xe3, 'P','o','i','n','t','e','r','_','D','o','w','n',0,\n0xa4, 0x94, 0x00, 0x00, 0xfe, 0xe4, 'P','o','i','n','t','e','r','_','U','p','L','e','f','t',0,\n0x4a, 0x08, 0x00, 0x00, 0xfe, 0xe5, 'P','o','i','n','t','e','r','_','U','p','R','i','g','h','t',0,\n0x8f, 0xb4, 0x00, 0x00, 0xfe, 0xe6, 'P','o','i','n','t','e','r','_','D','o','w','n','L','e','f','t',0,\n0x20, 0x48, 0x00, 0x00, 0xfe, 0xe7, 'P','o','i','n','t','e','r','_','D','o','w','n','R','i','g','h','t',0,\n0x8c, 0x74, 0x00, 0x00, 0xfe, 0xe8, 'P','o','i','n','t','e','r','_','B','u','t','t','o','n','_','D','f','l','t',0,\n0x48, 0x49, 0x00, 0x00, 0xfe, 0xe9, 'P','o','i','n','t','e','r','_','B','u','t','t','o','n','1',0,\n0x48, 0x4a, 0x00, 0x00, 0xfe, 0xea, 'P','o','i','n','t','e','r','_','B','u','t','t','o','n','2',0,\n0x48, 0x4b, 0x00, 0x00, 0xfe, 0xeb, 'P','o','i','n','t','e','r','_','B','u','t','t','o','n','3',0,\n0x48, 0x4c, 0x00, 0x00, 0xfe, 0xec, 'P','o','i','n','t','e','r','_','B','u','t','t','o','n','4',0,\n0x48, 0x4d, 0x00, 0x00, 0xfe, 0xed, 'P','o','i','n','t','e','r','_','B','u','t','t','o','n','5',0,\n0x37, 0x94, 0x00, 0x00, 0xfe, 0xee, 'P','o','i','n','t','e','r','_','D','b','l','C','l','i','c','k','_','D','f','l','t',0,\n0x12, 0xfb, 0x00, 0x00, 0xfe, 0xef, 'P','o','i','n','t','e','r','_','D','b','l','C','l','i','c','k','1',0,\n0x12, 0xfc, 0x00, 0x00, 0xfe, 0xf0, 'P','o','i','n','t','e','r','_','D','b','l','C','l','i','c','k','2',0,\n0x12, 0xfd, 0x00, 0x00, 0xfe, 0xf1, 'P','o','i','n','t','e','r','_','D','b','l','C','l','i','c','k','3',0,\n0x12, 0xfe, 0x00, 0x00, 0xfe, 0xf2, 'P','o','i','n','t','e','r','_','D','b','l','C','l','i','c','k','4',0,\n0x12, 0xff, 0x00, 0x00, 0xfe, 0xf3, 'P','o','i','n','t','e','r','_','D','b','l','C','l','i','c','k','5',0,\n0x1b, 0x14, 0x00, 0x00, 0xfe, 0xf4, 'P','o','i','n','t','e','r','_','D','r','a','g','_','D','f','l','t',0,\n0xd1, 0x33, 0x00, 0x00, 0xfe, 0xf5, 'P','o','i','n','t','e','r','_','D','r','a','g','1',0,\n0xd1, 0x34, 0x00, 0x00, 0xfe, 0xf6, 'P','o','i','n','t','e','r','_','D','r','a','g','2',0,\n0xd1, 0x35, 0x00, 0x00, 0xfe, 0xf7, 'P','o','i','n','t','e','r','_','D','r','a','g','3',0,\n0xd1, 0x36, 0x00, 0x00, 0xfe, 0xf8, 'P','o','i','n','t','e','r','_','D','r','a','g','4',0,\n0xd1, 0x37, 0x00, 0x00, 0xfe, 0xfd, 'P','o','i','n','t','e','r','_','D','r','a','g','5',0,\n0x36, 0x21, 0x00, 0x00, 0xfe, 0xf9, 'P','o','i','n','t','e','r','_','E','n','a','b','l','e','K','e','y','s',0,\n0x25, 0xf1, 0x00, 0x00, 0xfe, 0xfa, 'P','o','i','n','t','e','r','_','A','c','c','e','l','e','r','a','t','e',0,\n0x65, 0x48, 0x00, 0x00, 0xfe, 0xfb, 'P','o','i','n','t','e','r','_','D','f','l','t','B','t','n','N','e','x','t',0,\n0x65, 0x68, 0x00, 0x00, 0xfe, 0xfc, 'P','o','i','n','t','e','r','_','D','f','l','t','B','t','n','P','r','e','v',0,\n0x01, 0x2e, 0x00, 0x00, 0xfe, 0xa0, 'c','h',0,\n0x00, 0xee, 0x00, 0x00, 0xfe, 0xa1, 'C','h',0,\n0x00, 0xce, 0x00, 0x00, 0xfe, 0xa2, 'C','H',0,\n0x02, 0xb2, 0x00, 0x00, 0xfe, 0xa3, 'c','_','h',0,\n0x02, 0x32, 0x00, 0x00, 0xfe, 0xa4, 'C','_','h',0,\n0x02, 0x12, 0x00, 0x00, 0xfe, 0xa5, 'C','_','H',0,\n0x6a, 0x79, 0x00, 0x00, 0xfd, 0x01, '3','2','7','0','_','D','u','p','l','i','c','a','t','e',0,\n0x62, 0xbb, 0x00, 0x00, 0xfd, 0x02, '3','2','7','0','_','F','i','e','l','d','M','a','r','k',0,\n0xad, 0x82, 0x00, 0x00, 0xfd, 0x03, '3','2','7','0','_','R','i','g','h','t','2',0,\n0xd5, 0xfa, 0x00, 0x00, 0xfd, 0x04, '3','2','7','0','_','L','e','f','t','2',0,\n0x56, 0x1c, 0x00, 0x00, 0xfd, 0x05, '3','2','7','0','_','B','a','c','k','T','a','b',0,\n0xb2, 0x70, 0x00, 0x00, 0xfd, 0x06, '3','2','7','0','_','E','r','a','s','e','E','O','F',0,\n0xcc, 0xfe, 0x00, 0x00, 0xfd, 0x07, '3','2','7','0','_','E','r','a','s','e','I','n','p','u','t',0,\n0xd6, 0xb2, 0x00, 0x00, 0xfd, 0x08, '3','2','7','0','_','R','e','s','e','t',0,\n0x6b, 0x52, 0x00, 0x00, 0xfd, 0x09, '3','2','7','0','_','Q','u','i','t',0,\n0x34, 0xcb, 0x00, 0x00, 0xfd, 0x0a, '3','2','7','0','_','P','A','1',0,\n0x34, 0xcc, 0x00, 0x00, 0xfd, 0x0b, '3','2','7','0','_','P','A','2',0,\n0x34, 0xcd, 0x00, 0x00, 0xfd, 0x0c, '3','2','7','0','_','P','A','3',0,\n0x6b, 0x3e, 0x00, 0x00, 0xfd, 0x0d, '3','2','7','0','_','T','e','s','t',0,\n0x6a, 0xde, 0x00, 0x00, 0xfd, 0x0e, '3','2','7','0','_','A','t','t','n',0,\n0xad, 0xeb, 0x00, 0x00, 0xfd, 0x0f, '3','2','7','0','_','C','u','r','s','o','r','B','l','i','n','k',0,\n0x60, 0x5c, 0x00, 0x00, 0xfd, 0x10, '3','2','7','0','_','A','l','t','C','u','r','s','o','r',0,\n0xb3, 0x45, 0x00, 0x00, 0xfd, 0x11, '3','2','7','0','_','K','e','y','C','l','i','c','k',0,\n0x6b, 0x1e, 0x00, 0x00, 0xfd, 0x12, '3','2','7','0','_','J','u','m','p',0,\n0xd5, 0xf4, 0x00, 0x00, 0xfd, 0x13, '3','2','7','0','_','I','d','e','n','t',0,\n0x6b, 0x51, 0x00, 0x00, 0xfd, 0x14, '3','2','7','0','_','R','u','l','e',0,\n0x6a, 0xdd, 0x00, 0x00, 0xfd, 0x15, '3','2','7','0','_','C','o','p','y',0,\n0x6b, 0x1b, 0x00, 0x00, 0xfd, 0x16, '3','2','7','0','_','P','l','a','y',0,\n0xd6, 0xe2, 0x00, 0x00, 0xfd, 0x17, '3','2','7','0','_','S','e','t','u','p',0,\n0xad, 0x6c, 0x00, 0x00, 0xfd, 0x18, '3','2','7','0','_','R','e','c','o','r','d',0,\n0xfb, 0xac, 0x00, 0x00, 0xfd, 0x19, '3','2','7','0','_','C','h','a','n','g','e','S','c','r','e','e','n',0,\n0xc2, 0xcc, 0x00, 0x00, 0xfd, 0x1a, '3','2','7','0','_','D','e','l','e','t','e','W','o','r','d',0,\n0xb2, 0x5e, 0x00, 0x00, 0xfd, 0x1b, '3','2','7','0','_','E','x','S','e','l','e','c','t',0,\n0x5d, 0xde, 0x00, 0x00, 0xfd, 0x1c, '3','2','7','0','_','C','u','r','s','o','r','S','e','l','e','c','t',0,\n0xcf, 0xec, 0x00, 0x00, 0xfd, 0x1d, '3','2','7','0','_','P','r','i','n','t','S','c','r','e','e','n',0,\n0xd6, 0x2c, 0x00, 0x00, 0xfd, 0x1e, '3','2','7','0','_','E','n','t','e','r',0,\n0x0d, 0x5f, 0x00, 0x00, 0x00, 0x20, 's','p','a','c','e',0,\n0x1a, 0x17, 0x00, 0x00, 0x00, 0x21, 'e','x','c','l','a','m',0,\n0x70, 0xc8, 0x00, 0x00, 0x00, 0x22, 'q','u','o','t','e','d','b','l',0,\n0xba, 0x38, 0x00, 0x00, 0x00, 0x23, 'n','u','m','b','e','r','s','i','g','n',0,\n0x19, 0xb4, 0x00, 0x00, 0x00, 0x24, 'd','o','l','l','a','r',0,\n0x35, 0xbc, 0x00, 0x00, 0x00, 0x25, 'p','e','r','c','e','n','t',0,\n0xcd, 0x9c, 0x00, 0x00, 0x00, 0x26, 'a','m','p','e','r','s','a','n','d',0,\n0xa2, 0x4d, 0x00, 0x00, 0x00, 0x27, 'a','p','o','s','t','r','o','p','h','e',0,\n0xc5, 0x68, 0x00, 0x00, 0x00, 0x27, 'q','u','o','t','e','r','i','g','h','t',0,\n0xd6, 0xb4, 0x00, 0x00, 0x00, 0x28, 'p','a','r','e','n','l','e','f','t',0,\n0xae, 0x48, 0x00, 0x00, 0x00, 0x29, 'p','a','r','e','n','r','i','g','h','t',0,\n0x68, 0x95, 0x00, 0x00, 0x00, 0x2a, 'a','s','t','e','r','i','s','k',0,\n0x06, 0x8d, 0x00, 0x00, 0x00, 0x2b, 'p','l','u','s',0,\n0x0c, 0x97, 0x00, 0x00, 0x00, 0x2c, 'c','o','m','m','a',0,\n0x0d, 0x2d, 0x00, 0x00, 0x00, 0x2d, 'm','i','n','u','s',0,\n0x1a, 0xc6, 0x00, 0x00, 0x00, 0x2e, 'p','e','r','i','o','d',0,\n0x0d, 0x62, 0x00, 0x00, 0x00, 0x2f, 's','l','a','s','h',0,\n0x00, 0x30, 0x00, 0x00, 0x00, 0x30, '0',0,\n0x00, 0x31, 0x00, 0x00, 0x00, 0x31, '1',0,\n0x00, 0x32, 0x00, 0x00, 0x00, 0x32, '2',0,\n0x00, 0x33, 0x00, 0x00, 0x00, 0x33, '3',0,\n0x00, 0x34, 0x00, 0x00, 0x00, 0x34, '4',0,\n0x00, 0x35, 0x00, 0x00, 0x00, 0x35, '5',0,\n0x00, 0x36, 0x00, 0x00, 0x00, 0x36, '6',0,\n0x00, 0x37, 0x00, 0x00, 0x00, 0x37, '7',0,\n0x00, 0x38, 0x00, 0x00, 0x00, 0x38, '8',0,\n0x00, 0x39, 0x00, 0x00, 0x00, 0x39, '9',0,\n0x0c, 0xa4, 0x00, 0x00, 0x00, 0x3a, 'c','o','l','o','n',0,\n0xda, 0x84, 0x00, 0x00, 0x00, 0x3b, 's','e','m','i','c','o','l','o','n',0,\n0x06, 0x4d, 0x00, 0x00, 0x00, 0x3c, 'l','e','s','s',0,\n0x0c, 0xda, 0x00, 0x00, 0x00, 0x3d, 'e','q','u','a','l',0,\n0x34, 0x64, 0x00, 0x00, 0x00, 0x3e, 'g','r','e','a','t','e','r',0,\n0x70, 0x20, 0x00, 0x00, 0x00, 0x3f, 'q','u','e','s','t','i','o','n',0,\n0x01, 0x36, 0x00, 0x00, 0x00, 0x40, 'a','t',0,\n0x00, 0x41, 0x00, 0x00, 0x00, 0x41, 'A',0,\n0x00, 0x42, 0x00, 0x00, 0x00, 0x42, 'B',0,\n0x00, 0x43, 0x00, 0x00, 0x00, 0x43, 'C',0,\n0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 'D',0,\n0x00, 0x45, 0x00, 0x00, 0x00, 0x45, 'E',0,\n0x00, 0x46, 0x00, 0x00, 0x00, 0x46, 'F',0,\n0x00, 0x47, 0x00, 0x00, 0x00, 0x47, 'G',0,\n0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 'H',0,\n0x00, 0x49, 0x00, 0x00, 0x00, 0x49, 'I',0,\n0x00, 0x4a, 0x00, 0x00, 0x00, 0x4a, 'J',0,\n0x00, 0x4b, 0x00, 0x00, 0x00, 0x4b, 'K',0,\n0x00, 0x4c, 0x00, 0x00, 0x00, 0x4c, 'L',0,\n0x00, 0x4d, 0x00, 0x00, 0x00, 0x4d, 'M',0,\n0x00, 0x4e, 0x00, 0x00, 0x00, 0x4e, 'N',0,\n0x00, 0x4f, 0x00, 0x00, 0x00, 0x4f, 'O',0,\n0x00, 0x50, 0x00, 0x00, 0x00, 0x50, 'P',0,\n0x00, 0x51, 0x00, 0x00, 0x00, 0x51, 'Q',0,\n0x00, 0x52, 0x00, 0x00, 0x00, 0x52, 'R',0,\n0x00, 0x53, 0x00, 0x00, 0x00, 0x53, 'S',0,\n0x00, 0x54, 0x00, 0x00, 0x00, 0x54, 'T',0,\n0x00, 0x55, 0x00, 0x00, 0x00, 0x55, 'U',0,\n0x00, 0x56, 0x00, 0x00, 0x00, 0x56, 'V',0,\n0x00, 0x57, 0x00, 0x00, 0x00, 0x57, 'W',0,\n0x00, 0x58, 0x00, 0x00, 0x00, 0x58, 'X',0,\n0x00, 0x59, 0x00, 0x00, 0x00, 0x59, 'Y',0,\n0x00, 0x5a, 0x00, 0x00, 0x00, 0x5a, 'Z',0,\n0x33, 0x54, 0x00, 0x00, 0x00, 0x5b, 'b','r','a','c','k','e','t','l','e','f','t',0,\n0xc6, 0x02, 0x00, 0x00, 0x00, 0x5c, 'b','a','c','k','s','l','a','s','h',0,\n0x67, 0x88, 0x00, 0x00, 0x00, 0x5d, 'b','r','a','c','k','e','t','r','i','g','h','t',0,\n0x35, 0x23, 0x00, 0x00, 0x00, 0x5e, 'a','s','c','i','i','c','i','r','c','u','m',0,\n0xbe, 0xcd, 0x00, 0x00, 0x00, 0x5f, 'u','n','d','e','r','s','c','o','r','e',0,\n0x0c, 0xd5, 0x00, 0x00, 0x00, 0x60, 'g','r','a','v','e',0,\n0xe2, 0x44, 0x00, 0x00, 0x00, 0x60, 'q','u','o','t','e','l','e','f','t',0,\n0x00, 0x61, 0x00, 0x00, 0x00, 0x61, 'a',0,\n0x00, 0x62, 0x00, 0x00, 0x00, 0x62, 'b',0,\n0x00, 0x63, 0x00, 0x00, 0x00, 0x63, 'c',0,\n0x00, 0x64, 0x00, 0x00, 0x00, 0x64, 'd',0,\n0x00, 0x65, 0x00, 0x00, 0x00, 0x65, 'e',0,\n0x00, 0x66, 0x00, 0x00, 0x00, 0x66, 'f',0,\n0x00, 0x67, 0x00, 0x00, 0x00, 0x67, 'g',0,\n0x00, 0x68, 0x00, 0x00, 0x00, 0x68, 'h',0,\n0x00, 0x69, 0x00, 0x00, 0x00, 0x69, 'i',0,\n0x00, 0x6a, 0x00, 0x00, 0x00, 0x6a, 'j',0,\n0x00, 0x6b, 0x00, 0x00, 0x00, 0x6b, 'k',0,\n0x00, 0x6c, 0x00, 0x00, 0x00, 0x6c, 'l',0,\n0x00, 0x6d, 0x00, 0x00, 0x00, 0x6d, 'm',0,\n0x00, 0x6e, 0x00, 0x00, 0x00, 0x6e, 'n',0,\n0x00, 0x6f, 0x00, 0x00, 0x00, 0x6f, 'o',0,\n0x00, 0x70, 0x00, 0x00, 0x00, 0x70, 'p',0,\n0x00, 0x71, 0x00, 0x00, 0x00, 0x71, 'q',0,\n0x00, 0x72, 0x00, 0x00, 0x00, 0x72, 'r',0,\n0x00, 0x73, 0x00, 0x00, 0x00, 0x73, 's',0,\n0x00, 0x74, 0x00, 0x00, 0x00, 0x74, 't',0,\n0x00, 0x75, 0x00, 0x00, 0x00, 0x75, 'u',0,\n0x00, 0x76, 0x00, 0x00, 0x00, 0x76, 'v',0,\n0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 'w',0,\n0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 'x',0,\n0x00, 0x79, 0x00, 0x00, 0x00, 0x79, 'y',0,\n0x00, 0x7a, 0x00, 0x00, 0x00, 0x7a, 'z',0,\n0xcc, 0x24, 0x00, 0x00, 0x00, 0x7b, 'b','r','a','c','e','l','e','f','t',0,\n0x02, 0xbc, 0x00, 0x00, 0x00, 0x7c, 'b','a','r',0,\n0x99, 0x28, 0x00, 0x00, 0x00, 0x7d, 'b','r','a','c','e','r','i','g','h','t',0,\n0x9b, 0x45, 0x00, 0x00, 0x00, 0x7e, 'a','s','c','i','i','t','i','l','d','e',0,\n0xc7, 0x7f, 0x00, 0x00, 0x00, 0xa0, 'n','o','b','r','e','a','k','s','p','a','c','e',0,\n0xa7, 0xa8, 0x00, 0x00, 0x00, 0xa1, 'e','x','c','l','a','m','d','o','w','n',0,\n0x05, 0xfc, 0x00, 0x00, 0x00, 0xa2, 'c','e','n','t',0,\n0x70, 0x87, 0x00, 0x00, 0x00, 0xa3, 's','t','e','r','l','i','n','g',0,\n0x6a, 0x3f, 0x00, 0x00, 0x00, 0xa4, 'c','u','r','r','e','n','c','y',0,\n0x03, 0x1c, 0x00, 0x00, 0x00, 0xa5, 'y','e','n',0,\n0xd0, 0x9c, 0x00, 0x00, 0x00, 0xa6, 'b','r','o','k','e','n','b','a','r',0,\n0x36, 0x20, 0x00, 0x00, 0x00, 0xa7, 's','e','c','t','i','o','n',0,\n0xca, 0xb9, 0x00, 0x00, 0x00, 0xa8, 'd','i','a','e','r','e','s','i','s',0,\n0xd2, 0xe8, 0x00, 0x00, 0x00, 0xa9, 'c','o','p','y','r','i','g','h','t',0,\n0x6a, 0xc5, 0x00, 0x00, 0x00, 0xaa, 'o','r','d','f','e','m','i','n','i','n','e',0,\n0x67, 0xd4, 0x00, 0x00, 0x00, 0xab, 'g','u','i','l','l','e','m','e','t','l','e','f','t',0,\n0x69, 0x14, 0x00, 0x00, 0x00, 0xab, 'g','u','i','l','l','e','m','o','t','l','e','f','t',0,\n0x37, 0x18, 0x00, 0x00, 0x00, 0xac, 'n','o','t','s','i','g','n',0,\n0x1a, 0xe8, 0x00, 0x00, 0x00, 0xad, 'h','y','p','h','e','n',0,\n0xb2, 0x7e, 0x00, 0x00, 0x00, 0xae, 'r','e','g','i','s','t','e','r','e','d',0,\n0x19, 0xdc, 0x00, 0x00, 0x00, 0xaf, 'm','a','c','r','o','n',0,\n0x18, 0xff, 0x00, 0x00, 0x00, 0xb0, 'd','e','g','r','e','e',0,\n0xde, 0xcd, 0x00, 0x00, 0x00, 0xb1, 'p','l','u','s','m','i','n','u','s',0,\n0x9e, 0x94, 0x00, 0x00, 0x00, 0xb2, 't','w','o','s','u','p','e','r','i','o','r',0,\n0xe8, 0x94, 0x00, 0x00, 0x00, 0xb3, 't','h','r','e','e','s','u','p','e','r','i','o','r',0,\n0x0c, 0x49, 0x00, 0x00, 0x00, 0xb4, 'a','c','u','t','e',0,\n0x01, 0x4f, 0x00, 0x00, 0x00, 0xb5, 'm','u',0,\n0xd5, 0xec, 0x00, 0x00, 0x00, 0xb6, 'p','a','r','a','g','r','a','p','h',0,\n0x2b, 0xde, 0x00, 0x00, 0x00, 0xb7, 'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,\n0x31, 0xd1, 0x00, 0x00, 0x00, 0xb8, 'c','e','d','i','l','l','a',0,\n0x6e, 0x94, 0x00, 0x00, 0x00, 0xb9, 'o','n','e','s','u','p','e','r','i','o','r',0,\n0xdc, 0x35, 0x00, 0x00, 0x00, 0xba, 'o','r','d','m','a','s','c','u','l','i','n','e',0,\n0xd4, 0x35, 0x00, 0x00, 0x00, 0xba, 'm','a','s','c','u','l','i','n','e',0,\n0xd0, 0x88, 0x00, 0x00, 0x00, 0xbb, 'g','u','i','l','l','e','m','e','t','r','i','g','h','t',0,\n0xd3, 0x08, 0x00, 0x00, 0x00, 0xbb, 'g','u','i','l','l','e','m','o','t','r','i','g','h','t',0,\n0xb6, 0x0c, 0x00, 0x00, 0x00, 0xbc, 'o','n','e','q','u','a','r','t','e','r',0,\n0x35, 0xd2, 0x00, 0x00, 0x00, 0xbd, 'o','n','e','h','a','l','f',0,\n0xe6, 0x8b, 0x00, 0x00, 0x00, 0xbe, 't','h','r','e','e','q','u','a','r','t','e','r','s',0,\n0x08, 0x38, 0x00, 0x00, 0x00, 0xbf, 'q','u','e','s','t','i','o','n','d','o','w','n',0,\n0x14, 0xf5, 0x00, 0x00, 0x00, 0xc0, 'A','g','r','a','v','e',0,\n0x14, 0x69, 0x00, 0x00, 0x00, 0xc1, 'A','a','c','u','t','e',0,\n0xa0, 0x52, 0x00, 0x00, 0x00, 0xc2, 'A','c','i','r','c','u','m','f','l','e','x',0,\n0x15, 0x85, 0x00, 0x00, 0x00, 0xc3, 'A','t','i','l','d','e',0,\n0x4c, 0xb9, 0x00, 0x00, 0x00, 0xc4, 'A','d','i','a','e','r','e','s','i','s',0,\n0x0a, 0x87, 0x00, 0x00, 0x00, 0xc5, 'A','r','i','n','g',0,\n0x00, 0xc7, 0x00, 0x00, 0x00, 0xc6, 'A','E',0,\n0x53, 0x51, 0x00, 0x00, 0x00, 0xc7, 'C','c','e','d','i','l','l','a',0,\n0x15, 0x75, 0x00, 0x00, 0x00, 0xc8, 'E','g','r','a','v','e',0,\n0x14, 0xe9, 0x00, 0x00, 0x00, 0xc9, 'E','a','c','u','t','e',0,\n0xb0, 0x52, 0x00, 0x00, 0x00, 0xca, 'E','c','i','r','c','u','m','f','l','e','x',0,\n0x54, 0xb9, 0x00, 0x00, 0x00, 0xcb, 'E','d','i','a','e','r','e','s','i','s',0,\n0x15, 0xf5, 0x00, 0x00, 0x00, 0xcc, 'I','g','r','a','v','e',0,\n0x15, 0x69, 0x00, 0x00, 0x00, 0xcd, 'I','a','c','u','t','e',0,\n0xc0, 0x52, 0x00, 0x00, 0x00, 0xce, 'I','c','i','r','c','u','m','f','l','e','x',0,\n0x5c, 0xb9, 0x00, 0x00, 0x00, 0xcf, 'I','d','i','a','e','r','e','s','i','s',0,\n0x02, 0x04, 0x00, 0x00, 0x00, 0xd0, 'E','T','H',0,\n0x02, 0x64, 0x00, 0x00, 0x00, 0xd0, 'E','t','h',0,\n0x17, 0x25, 0x00, 0x00, 0x00, 0xd1, 'N','t','i','l','d','e',0,\n0x16, 0xb5, 0x00, 0x00, 0x00, 0xd2, 'O','g','r','a','v','e',0,\n0x16, 0x29, 0x00, 0x00, 0x00, 0xd3, 'O','a','c','u','t','e',0,\n0xd8, 0x52, 0x00, 0x00, 0x00, 0xd4, 'O','c','i','r','c','u','m','f','l','e','x',0,\n0x17, 0x45, 0x00, 0x00, 0x00, 0xd5, 'O','t','i','l','d','e',0,\n0x68, 0xb9, 0x00, 0x00, 0x00, 0xd6, 'O','d','i','a','e','r','e','s','i','s',0,\n0x6e, 0xd9, 0x00, 0x00, 0x00, 0xd7, 'm','u','l','t','i','p','l','y',0,\n0x17, 0x42, 0x00, 0x00, 0x00, 0xd8, 'O','s','l','a','s','h',0,\n0x5c, 0x9b, 0x00, 0x00, 0x00, 0xd8, 'O','o','b','l','i','q','u','e',0,\n0x17, 0x75, 0x00, 0x00, 0x00, 0xd9, 'U','g','r','a','v','e',0,\n0x16, 0xe9, 0x00, 0x00, 0x00, 0xda, 'U','a','c','u','t','e',0,\n0xf0, 0x52, 0x00, 0x00, 0x00, 0xdb, 'U','c','i','r','c','u','m','f','l','e','x',0,\n0x74, 0xb9, 0x00, 0x00, 0x00, 0xdc, 'U','d','i','a','e','r','e','s','i','s',0,\n0x17, 0x69, 0x00, 0x00, 0x00, 0xdd, 'Y','a','c','u','t','e',0,\n0x09, 0xae, 0x00, 0x00, 0x00, 0xde, 'T','H','O','R','N',0,\n0x0b, 0x8e, 0x00, 0x00, 0x00, 0xde, 'T','h','o','r','n',0,\n0x1b, 0xa8, 0x00, 0x00, 0x00, 0xdf, 's','s','h','a','r','p',0,\n0x18, 0xf5, 0x00, 0x00, 0x00, 0xe0, 'a','g','r','a','v','e',0,\n0x18, 0x69, 0x00, 0x00, 0x00, 0xe1, 'a','a','c','u','t','e',0,\n0x20, 0x52, 0x00, 0x00, 0x00, 0xe2, 'a','c','i','r','c','u','m','f','l','e','x',0,\n0x19, 0x85, 0x00, 0x00, 0x00, 0xe3, 'a','t','i','l','d','e',0,\n0x8c, 0xb9, 0x00, 0x00, 0x00, 0xe4, 'a','d','i','a','e','r','e','s','i','s',0,\n0x0c, 0x87, 0x00, 0x00, 0x00, 0xe5, 'a','r','i','n','g',0,\n0x01, 0x27, 0x00, 0x00, 0x00, 0xe6, 'a','e',0,\n0x63, 0x51, 0x00, 0x00, 0x00, 0xe7, 'c','c','e','d','i','l','l','a',0,\n0x19, 0x75, 0x00, 0x00, 0x00, 0xe8, 'e','g','r','a','v','e',0,\n0x18, 0xe9, 0x00, 0x00, 0x00, 0xe9, 'e','a','c','u','t','e',0,\n0x30, 0x52, 0x00, 0x00, 0x00, 0xea, 'e','c','i','r','c','u','m','f','l','e','x',0,\n0x94, 0xb9, 0x00, 0x00, 0x00, 0xeb, 'e','d','i','a','e','r','e','s','i','s',0,\n0x19, 0xf5, 0x00, 0x00, 0x00, 0xec, 'i','g','r','a','v','e',0,\n0x19, 0x69, 0x00, 0x00, 0x00, 0xed, 'i','a','c','u','t','e',0,\n0x40, 0x52, 0x00, 0x00, 0x00, 0xee, 'i','c','i','r','c','u','m','f','l','e','x',0,\n0x9c, 0xb9, 0x00, 0x00, 0x00, 0xef, 'i','d','i','a','e','r','e','s','i','s',0,\n0x02, 0xe4, 0x00, 0x00, 0x00, 0xf0, 'e','t','h',0,\n0x1b, 0x25, 0x00, 0x00, 0x00, 0xf1, 'n','t','i','l','d','e',0,\n0x1a, 0xb5, 0x00, 0x00, 0x00, 0xf2, 'o','g','r','a','v','e',0,\n0x1a, 0x29, 0x00, 0x00, 0x00, 0xf3, 'o','a','c','u','t','e',0,\n0x58, 0x52, 0x00, 0x00, 0x00, 0xf4, 'o','c','i','r','c','u','m','f','l','e','x',0,\n0x1b, 0x45, 0x00, 0x00, 0x00, 0xf5, 'o','t','i','l','d','e',0,\n0xa8, 0xb9, 0x00, 0x00, 0x00, 0xf6, 'o','d','i','a','e','r','e','s','i','s',0,\n0x68, 0x18, 0x00, 0x00, 0x00, 0xf7, 'd','i','v','i','s','i','o','n',0,\n0x1b, 0x42, 0x00, 0x00, 0x00, 0xf8, 'o','s','l','a','s','h',0,\n0x6c, 0x9b, 0x00, 0x00, 0x00, 0xf8, 'o','o','b','l','i','q','u','e',0,\n0x1b, 0x75, 0x00, 0x00, 0x00, 0xf9, 'u','g','r','a','v','e',0,\n0x1a, 0xe9, 0x00, 0x00, 0x00, 0xfa, 'u','a','c','u','t','e',0,\n0x70, 0x52, 0x00, 0x00, 0x00, 0xfb, 'u','c','i','r','c','u','m','f','l','e','x',0,\n0xb4, 0xb9, 0x00, 0x00, 0x00, 0xfc, 'u','d','i','a','e','r','e','s','i','s',0,\n0x1b, 0x69, 0x00, 0x00, 0x00, 0xfd, 'y','a','c','u','t','e',0,\n0x0d, 0x8e, 0x00, 0x00, 0x00, 0xfe, 't','h','o','r','n',0,\n0xbc, 0xb9, 0x00, 0x00, 0x00, 0xff, 'y','d','i','a','e','r','e','s','i','s',0,\n0x2a, 0xf5, 0x00, 0x00, 0x01, 0xa1, 'A','o','g','o','n','e','k',0,\n0x0c, 0x95, 0x00, 0x00, 0x01, 0xa2, 'b','r','e','v','e',0,\n0x2f, 0x27, 0x00, 0x00, 0x01, 0xa3, 'L','s','t','r','o','k','e',0,\n0x15, 0xcc, 0x00, 0x00, 0x01, 0xa5, 'L','c','a','r','o','n',0,\n0x16, 0xa9, 0x00, 0x00, 0x01, 0xa6, 'S','a','c','u','t','e',0,\n0x16, 0xac, 0x00, 0x00, 0x01, 0xa9, 'S','c','a','r','o','n',0,\n0x5b, 0x51, 0x00, 0x00, 0x01, 0xaa, 'S','c','e','d','i','l','l','a',0,\n0x16, 0xcc, 0x00, 0x00, 0x01, 0xab, 'T','c','a','r','o','n',0,\n0x17, 0x89, 0x00, 0x00, 0x01, 0xac, 'Z','a','c','u','t','e',0,\n0x17, 0x8c, 0x00, 0x00, 0x01, 0xae, 'Z','c','a','r','o','n',0,\n0xbe, 0x4a, 0x00, 0x00, 0x01, 0xaf, 'Z','a','b','o','v','e','d','o','t',0,\n0x32, 0xf5, 0x00, 0x00, 0x01, 0xb1, 'a','o','g','o','n','e','k',0,\n0x1a, 0xb5, 0x00, 0x00, 0x01, 0xb2, 'o','g','o','n','e','k',0,\n0x37, 0x27, 0x00, 0x00, 0x01, 0xb3, 'l','s','t','r','o','k','e',0,\n0x19, 0xcc, 0x00, 0x00, 0x01, 0xb5, 'l','c','a','r','o','n',0,\n0x1a, 0xa9, 0x00, 0x00, 0x01, 0xb6, 's','a','c','u','t','e',0,\n0x0c, 0x4c, 0x00, 0x00, 0x01, 0xb7, 'c','a','r','o','n',0,\n0x1a, 0xac, 0x00, 0x00, 0x01, 0xb9, 's','c','a','r','o','n',0,\n0x6b, 0x51, 0x00, 0x00, 0x01, 0xba, 's','c','e','d','i','l','l','a',0,\n0x1a, 0xcc, 0x00, 0x00, 0x01, 0xbb, 't','c','a','r','o','n',0,\n0x1b, 0x89, 0x00, 0x00, 0x01, 0xbc, 'z','a','c','u','t','e',0,\n0x47, 0xe9, 0x00, 0x00, 0x01, 0xbd, 'd','o','u','b','l','e','a','c','u','t','e',0,\n0x1b, 0x8c, 0x00, 0x00, 0x01, 0xbe, 'z','c','a','r','o','n',0,\n0xde, 0x4a, 0x00, 0x00, 0x01, 0xbf, 'z','a','b','o','v','e','d','o','t',0,\n0x16, 0x89, 0x00, 0x00, 0x01, 0xc0, 'R','a','c','u','t','e',0,\n0x14, 0xb5, 0x00, 0x00, 0x01, 0xc3, 'A','b','r','e','v','e',0,\n0x15, 0xc9, 0x00, 0x00, 0x01, 0xc5, 'L','a','c','u','t','e',0,\n0x14, 0xa9, 0x00, 0x00, 0x01, 0xc6, 'C','a','c','u','t','e',0,\n0x14, 0xac, 0x00, 0x00, 0x01, 0xc8, 'C','c','a','r','o','n',0,\n0x2b, 0xf5, 0x00, 0x00, 0x01, 0xca, 'E','o','g','o','n','e','k',0,\n0x14, 0xec, 0x00, 0x00, 0x01, 0xcc, 'E','c','a','r','o','n',0,\n0x14, 0xcc, 0x00, 0x00, 0x01, 0xcf, 'D','c','a','r','o','n',0,\n0x2d, 0x27, 0x00, 0x00, 0x01, 0xd0, 'D','s','t','r','o','k','e',0,\n0x16, 0x09, 0x00, 0x00, 0x01, 0xd1, 'N','a','c','u','t','e',0,\n0x16, 0x0c, 0x00, 0x00, 0x01, 0xd2, 'N','c','a','r','o','n',0,\n0xbf, 0xe9, 0x00, 0x00, 0x01, 0xd5, 'O','d','o','u','b','l','e','a','c','u','t','e',0,\n0x16, 0x8c, 0x00, 0x00, 0x01, 0xd8, 'R','c','a','r','o','n',0,\n0x0b, 0xc7, 0x00, 0x00, 0x01, 0xd9, 'U','r','i','n','g',0,\n0xef, 0xe9, 0x00, 0x00, 0x01, 0xdb, 'U','d','o','u','b','l','e','a','c','u','t','e',0,\n0x5b, 0xd1, 0x00, 0x00, 0x01, 0xde, 'T','c','e','d','i','l','l','a',0,\n0x1a, 0x89, 0x00, 0x00, 0x01, 0xe0, 'r','a','c','u','t','e',0,\n0x18, 0xb5, 0x00, 0x00, 0x01, 0xe3, 'a','b','r','e','v','e',0,\n0x19, 0xc9, 0x00, 0x00, 0x01, 0xe5, 'l','a','c','u','t','e',0,\n0x18, 0xa9, 0x00, 0x00, 0x01, 0xe6, 'c','a','c','u','t','e',0,\n0x18, 0xac, 0x00, 0x00, 0x01, 0xe8, 'c','c','a','r','o','n',0,\n0x33, 0xf5, 0x00, 0x00, 0x01, 0xea, 'e','o','g','o','n','e','k',0,\n0x18, 0xec, 0x00, 0x00, 0x01, 0xec, 'e','c','a','r','o','n',0,\n0x18, 0xcc, 0x00, 0x00, 0x01, 0xef, 'd','c','a','r','o','n',0,\n0x35, 0x27, 0x00, 0x00, 0x01, 0xf0, 'd','s','t','r','o','k','e',0,\n0x1a, 0x09, 0x00, 0x00, 0x01, 0xf1, 'n','a','c','u','t','e',0,\n0x1a, 0x0c, 0x00, 0x00, 0x01, 0xf2, 'n','c','a','r','o','n',0,\n0xbf, 0xe9, 0x00, 0x00, 0x01, 0xf5, 'o','d','o','u','b','l','e','a','c','u','t','e',0,\n0x1a, 0x8c, 0x00, 0x00, 0x01, 0xf8, 'r','c','a','r','o','n',0,\n0x0d, 0xc7, 0x00, 0x00, 0x01, 0xf9, 'u','r','i','n','g',0,\n0xef, 0xe9, 0x00, 0x00, 0x01, 0xfb, 'u','d','o','u','b','l','e','a','c','u','t','e',0,\n0x6b, 0xd1, 0x00, 0x00, 0x01, 0xfe, 't','c','e','d','i','l','l','a',0,\n0x64, 0x4a, 0x00, 0x00, 0x01, 0xff, 'a','b','o','v','e','d','o','t',0,\n0x2e, 0x27, 0x00, 0x00, 0x02, 0xa1, 'H','s','t','r','o','k','e',0,\n0xbc, 0x52, 0x00, 0x00, 0x02, 0xa6, 'H','c','i','r','c','u','m','f','l','e','x',0,\n0xad, 0x4a, 0x00, 0x00, 0x02, 0xa9, 'I','a','b','o','v','e','d','o','t',0,\n0x15, 0x75, 0x00, 0x00, 0x02, 0xab, 'G','b','r','e','v','e',0,\n0xc4, 0x52, 0x00, 0x00, 0x02, 0xac, 'J','c','i','r','c','u','m','f','l','e','x',0,\n0x36, 0x27, 0x00, 0x00, 0x02, 0xb1, 'h','s','t','r','o','k','e',0,\n0x3c, 0x52, 0x00, 0x00, 0x02, 0xb6, 'h','c','i','r','c','u','m','f','l','e','x',0,\n0x68, 0xed, 0x00, 0x00, 0x02, 0xb9, 'i','d','o','t','l','e','s','s',0,\n0x19, 0x75, 0x00, 0x00, 0x02, 0xbb, 'g','b','r','e','v','e',0,\n0x44, 0x52, 0x00, 0x00, 0x02, 0xbc, 'j','c','i','r','c','u','m','f','l','e','x',0,\n0xa7, 0x4a, 0x00, 0x00, 0x02, 0xc5, 'C','a','b','o','v','e','d','o','t',0,\n0xa8, 0x52, 0x00, 0x00, 0x02, 0xc6, 'C','c','i','r','c','u','m','f','l','e','x',0,\n0xab, 0x4a, 0x00, 0x00, 0x02, 0xd5, 'G','a','b','o','v','e','d','o','t',0,\n0xb8, 0x52, 0x00, 0x00, 0x02, 0xd8, 'G','c','i','r','c','u','m','f','l','e','x',0,\n0x17, 0x35, 0x00, 0x00, 0x02, 0xdd, 'U','b','r','e','v','e',0,\n0xe8, 0x52, 0x00, 0x00, 0x02, 0xde, 'S','c','i','r','c','u','m','f','l','e','x',0,\n0xc7, 0x4a, 0x00, 0x00, 0x02, 0xe5, 'c','a','b','o','v','e','d','o','t',0,\n0x28, 0x52, 0x00, 0x00, 0x02, 0xe6, 'c','c','i','r','c','u','m','f','l','e','x',0,\n0xcb, 0x4a, 0x00, 0x00, 0x02, 0xf5, 'g','a','b','o','v','e','d','o','t',0,\n0x38, 0x52, 0x00, 0x00, 0x02, 0xf8, 'g','c','i','r','c','u','m','f','l','e','x',0,\n0x1b, 0x35, 0x00, 0x00, 0x02, 0xfd, 'u','b','r','e','v','e',0,\n0x68, 0x52, 0x00, 0x00, 0x02, 0xfe, 's','c','i','r','c','u','m','f','l','e','x',0,\n0x02, 0xf1, 0x00, 0x00, 0x03, 0xa2, 'k','r','a',0,\n0x0c, 0xb9, 0x00, 0x00, 0x03, 0xa2, 'k','a','p','p','a',0,\n0x5a, 0xd1, 0x00, 0x00, 0x03, 0xa3, 'R','c','e','d','i','l','l','a',0,\n0x16, 0x85, 0x00, 0x00, 0x03, 0xa5, 'I','t','i','l','d','e',0,\n0x57, 0xd1, 0x00, 0x00, 0x03, 0xa6, 'L','c','e','d','i','l','l','a',0,\n0x2b, 0x1c, 0x00, 0x00, 0x03, 0xaa, 'E','m','a','c','r','o','n',0,\n0x55, 0x51, 0x00, 0x00, 0x03, 0xab, 'G','c','e','d','i','l','l','a',0,\n0x17, 0xe2, 0x00, 0x00, 0x03, 0xac, 'T','s','l','a','s','h',0,\n0x6a, 0xd1, 0x00, 0x00, 0x03, 0xb3, 'r','c','e','d','i','l','l','a',0,\n0x1a, 0x85, 0x00, 0x00, 0x03, 0xb5, 'i','t','i','l','d','e',0,\n0x67, 0xd1, 0x00, 0x00, 0x03, 0xb6, 'l','c','e','d','i','l','l','a',0,\n0x33, 0x1c, 0x00, 0x00, 0x03, 0xba, 'e','m','a','c','r','o','n',0,\n0x65, 0x51, 0x00, 0x00, 0x03, 0xbb, 'g','c','e','d','i','l','l','a',0,\n0x1b, 0xe2, 0x00, 0x00, 0x03, 0xbc, 't','s','l','a','s','h',0,\n0x01, 0xf7, 0x00, 0x00, 0x03, 0xbd, 'E','N','G',0,\n0x02, 0xd7, 0x00, 0x00, 0x03, 0xbf, 'e','n','g',0,\n0x2a, 0x1c, 0x00, 0x00, 0x03, 0xc0, 'A','m','a','c','r','o','n',0,\n0x2c, 0xf5, 0x00, 0x00, 0x03, 0xc7, 'I','o','g','o','n','e','k',0,\n0xa9, 0x4a, 0x00, 0x00, 0x03, 0xcc, 'E','a','b','o','v','e','d','o','t',0,\n0x2c, 0x1c, 0x00, 0x00, 0x03, 0xcf, 'I','m','a','c','r','o','n',0,\n0x58, 0xd1, 0x00, 0x00, 0x03, 0xd1, 'N','c','e','d','i','l','l','a',0,\n0x2d, 0x9c, 0x00, 0x00, 0x03, 0xd2, 'O','m','a','c','r','o','n',0,\n0x57, 0x51, 0x00, 0x00, 0x03, 0xd3, 'K','c','e','d','i','l','l','a',0,\n0x2f, 0xf5, 0x00, 0x00, 0x03, 0xd9, 'U','o','g','o','n','e','k',0,\n0x18, 0x05, 0x00, 0x00, 0x03, 0xdd, 'U','t','i','l','d','e',0,\n0x2f, 0x1c, 0x00, 0x00, 0x03, 0xde, 'U','m','a','c','r','o','n',0,\n0x32, 0x1c, 0x00, 0x00, 0x03, 0xe0, 'a','m','a','c','r','o','n',0,\n0x34, 0xf5, 0x00, 0x00, 0x03, 0xe7, 'i','o','g','o','n','e','k',0,\n0xc9, 0x4a, 0x00, 0x00, 0x03, 0xec, 'e','a','b','o','v','e','d','o','t',0,\n0x34, 0x1c, 0x00, 0x00, 0x03, 0xef, 'i','m','a','c','r','o','n',0,\n0x68, 0xd1, 0x00, 0x00, 0x03, 0xf1, 'n','c','e','d','i','l','l','a',0,\n0x35, 0x9c, 0x00, 0x00, 0x03, 0xf2, 'o','m','a','c','r','o','n',0,\n0x67, 0x51, 0x00, 0x00, 0x03, 0xf3, 'k','c','e','d','i','l','l','a',0,\n0x37, 0xf5, 0x00, 0x00, 0x03, 0xf9, 'u','o','g','o','n','e','k',0,\n0x1c, 0x05, 0x00, 0x00, 0x03, 0xfd, 'u','t','i','l','d','e',0,\n0x37, 0x1c, 0x00, 0x00, 0x03, 0xfe, 'u','m','a','c','r','o','n',0,\n0xf8, 0x52, 0x01, 0x00, 0x01, 0x74, 'W','c','i','r','c','u','m','f','l','e','x',0,\n0x78, 0x52, 0x01, 0x00, 0x01, 0x75, 'w','c','i','r','c','u','m','f','l','e','x',0,\n0x00, 0x52, 0x01, 0x00, 0x01, 0x76, 'Y','c','i','r','c','u','m','f','l','e','x',0,\n0x80, 0x52, 0x01, 0x00, 0x01, 0x77, 'y','c','i','r','c','u','m','f','l','e','x',0,\n0xa6, 0x4a, 0x01, 0x00, 0x1e, 0x02, 'B','a','b','o','v','e','d','o','t',0,\n0xc6, 0x4a, 0x01, 0x00, 0x1e, 0x03, 'b','a','b','o','v','e','d','o','t',0,\n0xa8, 0x4a, 0x01, 0x00, 0x1e, 0x0a, 'D','a','b','o','v','e','d','o','t',0,\n0xc8, 0x4a, 0x01, 0x00, 0x1e, 0x0b, 'd','a','b','o','v','e','d','o','t',0,\n0xaa, 0x4a, 0x01, 0x00, 0x1e, 0x1e, 'F','a','b','o','v','e','d','o','t',0,\n0xca, 0x4a, 0x01, 0x00, 0x1e, 0x1f, 'f','a','b','o','v','e','d','o','t',0,\n0xb1, 0x4a, 0x01, 0x00, 0x1e, 0x40, 'M','a','b','o','v','e','d','o','t',0,\n0xd1, 0x4a, 0x01, 0x00, 0x1e, 0x41, 'm','a','b','o','v','e','d','o','t',0,\n0xb4, 0x4a, 0x01, 0x00, 0x1e, 0x56, 'P','a','b','o','v','e','d','o','t',0,\n0xd4, 0x4a, 0x01, 0x00, 0x1e, 0x57, 'p','a','b','o','v','e','d','o','t',0,\n0xb7, 0x4a, 0x01, 0x00, 0x1e, 0x60, 'S','a','b','o','v','e','d','o','t',0,\n0xd7, 0x4a, 0x01, 0x00, 0x1e, 0x61, 's','a','b','o','v','e','d','o','t',0,\n0xb8, 0x4a, 0x01, 0x00, 0x1e, 0x6a, 'T','a','b','o','v','e','d','o','t',0,\n0xd8, 0x4a, 0x01, 0x00, 0x1e, 0x6b, 't','a','b','o','v','e','d','o','t',0,\n0x17, 0xb5, 0x01, 0x00, 0x1e, 0x80, 'W','g','r','a','v','e',0,\n0x1b, 0xb5, 0x01, 0x00, 0x1e, 0x81, 'w','g','r','a','v','e',0,\n0x17, 0x29, 0x01, 0x00, 0x1e, 0x82, 'W','a','c','u','t','e',0,\n0x1b, 0x29, 0x01, 0x00, 0x1e, 0x83, 'w','a','c','u','t','e',0,\n0x78, 0xb9, 0x01, 0x00, 0x1e, 0x84, 'W','d','i','a','e','r','e','s','i','s',0,\n0xb8, 0xb9, 0x01, 0x00, 0x1e, 0x85, 'w','d','i','a','e','r','e','s','i','s',0,\n0x17, 0xf5, 0x01, 0x00, 0x1e, 0xf2, 'Y','g','r','a','v','e',0,\n0x1b, 0xf5, 0x01, 0x00, 0x1e, 0xf3, 'y','g','r','a','v','e',0,\n0x00, 0xe3, 0x00, 0x00, 0x13, 0xbc, 'O','E',0,\n0x01, 0x43, 0x00, 0x00, 0x13, 0xbd, 'o','e',0,\n0x7c, 0xb9, 0x00, 0x00, 0x13, 0xbe, 'Y','d','i','a','e','r','e','s','i','s',0,\n0x6f, 0x05, 0x00, 0x00, 0x04, 0x7e, 'o','v','e','r','l','i','n','e',0,\n0xfc, 0x36, 0x00, 0x00, 0x04, 0xa1, 'k','a','n','a','_','f','u','l','l','s','t','o','p',0,\n0xa6, 0x52, 0x00, 0x00, 0x04, 0xa2, 'k','a','n','a','_','o','p','e','n','i','n','g','b','r','a','c','k','e','t',0,\n0x4a, 0x52, 0x00, 0x00, 0x04, 0xa3, 'k','a','n','a','_','c','l','o','s','i','n','g','b','r','a','c','k','e','t',0,\n0x9e, 0xb7, 0x00, 0x00, 0x04, 0xa4, 'k','a','n','a','_','c','o','m','m','a',0,\n0xcc, 0xc5, 0x00, 0x00, 0x04, 0xa5, 'k','a','n','a','_','c','o','n','j','u','n','c','t','i','v','e',0,\n0xf5, 0xca, 0x00, 0x00, 0x04, 0xa5, 'k','a','n','a','_','m','i','d','d','l','e','d','o','t',0,\n0x33, 0x41, 0x00, 0x00, 0x04, 0xa6, 'k','a','n','a','_','W','O',0,\n0x19, 0x83, 0x00, 0x00, 0x04, 0xa7, 'k','a','n','a','_','a',0,\n0x19, 0x8b, 0x00, 0x00, 0x04, 0xa8, 'k','a','n','a','_','i',0,\n0x19, 0x97, 0x00, 0x00, 0x04, 0xa9, 'k','a','n','a','_','u',0,\n0x19, 0x87, 0x00, 0x00, 0x04, 0xaa, 'k','a','n','a','_','e',0,\n0x19, 0x91, 0x00, 0x00, 0x04, 0xab, 'k','a','n','a','_','o',0,\n0x33, 0x97, 0x00, 0x00, 0x04, 0xac, 'k','a','n','a','_','y','a',0,\n0x33, 0xab, 0x00, 0x00, 0x04, 0xad, 'k','a','n','a','_','y','u',0,\n0x33, 0xa5, 0x00, 0x00, 0x04, 0xae, 'k','a','n','a','_','y','o',0,\n0x67, 0xb3, 0x00, 0x00, 0x04, 0xaf, 'k','a','n','a','_','t','s','u',0,\n0x33, 0xa1, 0x00, 0x00, 0x04, 0xaf, 'k','a','n','a','_','t','u',0,\n0xfa, 0xfc, 0x00, 0x00, 0x04, 0xb0, 'p','r','o','l','o','n','g','e','d','s','o','u','n','d',0,\n0x19, 0x63, 0x00, 0x00, 0x04, 0xb1, 'k','a','n','a','_','A',0,\n0x19, 0x6b, 0x00, 0x00, 0x04, 0xb2, 'k','a','n','a','_','I',0,\n0x19, 0x77, 0x00, 0x00, 0x04, 0xb3, 'k','a','n','a','_','U',0,\n0x19, 0x67, 0x00, 0x00, 0x04, 0xb4, 'k','a','n','a','_','E',0,\n0x19, 0x71, 0x00, 0x00, 0x04, 0xb5, 'k','a','n','a','_','O',0,\n0x33, 0x1b, 0x00, 0x00, 0x04, 0xb6, 'k','a','n','a','_','K','A',0,\n0x33, 0x23, 0x00, 0x00, 0x04, 0xb7, 'k','a','n','a','_','K','I',0,\n0x33, 0x2f, 0x00, 0x00, 0x04, 0xb8, 'k','a','n','a','_','K','U',0,\n0x33, 0x1f, 0x00, 0x00, 0x04, 0xb9, 'k','a','n','a','_','K','E',0,\n0x33, 0x29, 0x00, 0x00, 0x04, 0xba, 'k','a','n','a','_','K','O',0,\n0x33, 0x2b, 0x00, 0x00, 0x04, 0xbb, 'k','a','n','a','_','S','A',0,\n0x66, 0xad, 0x00, 0x00, 0x04, 0xbc, 'k','a','n','a','_','S','H','I',0,\n0x33, 0x3f, 0x00, 0x00, 0x04, 0xbd, 'k','a','n','a','_','S','U',0,\n0x33, 0x2f, 0x00, 0x00, 0x04, 0xbe, 'k','a','n','a','_','S','E',0,\n0x33, 0x39, 0x00, 0x00, 0x04, 0xbf, 'k','a','n','a','_','S','O',0,\n0x33, 0x2d, 0x00, 0x00, 0x04, 0xc0, 'k','a','n','a','_','T','A',0,\n0x66, 0x6d, 0x00, 0x00, 0x04, 0xc1, 'k','a','n','a','_','C','H','I',0,\n0x33, 0x35, 0x00, 0x00, 0x04, 0xc1, 'k','a','n','a','_','T','I',0,\n0x66, 0xd3, 0x00, 0x00, 0x04, 0xc2, 'k','a','n','a','_','T','S','U',0,\n0x33, 0x41, 0x00, 0x00, 0x04, 0xc2, 'k','a','n','a','_','T','U',0,\n0x33, 0x31, 0x00, 0x00, 0x04, 0xc3, 'k','a','n','a','_','T','E',0,\n0x33, 0x3b, 0x00, 0x00, 0x04, 0xc4, 'k','a','n','a','_','T','O',0,\n0x33, 0x21, 0x00, 0x00, 0x04, 0xc5, 'k','a','n','a','_','N','A',0,\n0x33, 0x29, 0x00, 0x00, 0x04, 0xc6, 'k','a','n','a','_','N','I',0,\n0x33, 0x35, 0x00, 0x00, 0x04, 0xc7, 'k','a','n','a','_','N','U',0,\n0x33, 0x25, 0x00, 0x00, 0x04, 0xc8, 'k','a','n','a','_','N','E',0,\n0x33, 0x2f, 0x00, 0x00, 0x04, 0xc9, 'k','a','n','a','_','N','O',0,\n0x33, 0x15, 0x00, 0x00, 0x04, 0xca, 'k','a','n','a','_','H','A',0,\n0x33, 0x1d, 0x00, 0x00, 0x04, 0xcb, 'k','a','n','a','_','H','I',0,\n0x33, 0x25, 0x00, 0x00, 0x04, 0xcc, 'k','a','n','a','_','F','U',0,\n0x33, 0x29, 0x00, 0x00, 0x04, 0xcc, 'k','a','n','a','_','H','U',0,\n0x33, 0x19, 0x00, 0x00, 0x04, 0xcd, 'k','a','n','a','_','H','E',0,\n0x33, 0x23, 0x00, 0x00, 0x04, 0xce, 'k','a','n','a','_','H','O',0,\n0x33, 0x1f, 0x00, 0x00, 0x04, 0xcf, 'k','a','n','a','_','M','A',0,\n0x33, 0x27, 0x00, 0x00, 0x04, 0xd0, 'k','a','n','a','_','M','I',0,\n0x33, 0x33, 0x00, 0x00, 0x04, 0xd1, 'k','a','n','a','_','M','U',0,\n0x33, 0x23, 0x00, 0x00, 0x04, 0xd2, 'k','a','n','a','_','M','E',0,\n0x33, 0x2d, 0x00, 0x00, 0x04, 0xd3, 'k','a','n','a','_','M','O',0,\n0x33, 0x37, 0x00, 0x00, 0x04, 0xd4, 'k','a','n','a','_','Y','A',0,\n0x33, 0x4b, 0x00, 0x00, 0x04, 0xd5, 'k','a','n','a','_','Y','U',0,\n0x33, 0x45, 0x00, 0x00, 0x04, 0xd6, 'k','a','n','a','_','Y','O',0,\n0x33, 0x29, 0x00, 0x00, 0x04, 0xd7, 'k','a','n','a','_','R','A',0,\n0x33, 0x31, 0x00, 0x00, 0x04, 0xd8, 'k','a','n','a','_','R','I',0,\n0x33, 0x3d, 0x00, 0x00, 0x04, 0xd9, 'k','a','n','a','_','R','U',0,\n0x33, 0x2d, 0x00, 0x00, 0x04, 0xda, 'k','a','n','a','_','R','E',0,\n0x33, 0x37, 0x00, 0x00, 0x04, 0xdb, 'k','a','n','a','_','R','O',0,\n0x33, 0x33, 0x00, 0x00, 0x04, 0xdc, 'k','a','n','a','_','W','A',0,\n0x19, 0x70, 0x00, 0x00, 0x04, 0xdd, 'k','a','n','a','_','N',0,\n0x83, 0xfc, 0x00, 0x00, 0x04, 0xde, 'v','o','i','c','e','d','s','o','u','n','d',0,\n0xfb, 0xfc, 0x00, 0x00, 0x04, 0xdf, 's','e','m','i','v','o','i','c','e','d','s','o','u','n','d',0,\n0x40, 0x56, 0x00, 0x00, 0xff, 0x7e, 'k','a','n','a','_','s','w','i','t','c','h',0,\n0x2a, 0xea, 0x01, 0x00, 0x06, 0xf0, 'F','a','r','s','i','_','0',0,\n0x2a, 0xeb, 0x01, 0x00, 0x06, 0xf1, 'F','a','r','s','i','_','1',0,\n0x2a, 0xec, 0x01, 0x00, 0x06, 0xf2, 'F','a','r','s','i','_','2',0,\n0x2a, 0xed, 0x01, 0x00, 0x06, 0xf3, 'F','a','r','s','i','_','3',0,\n0x2a, 0xee, 0x01, 0x00, 0x06, 0xf4, 'F','a','r','s','i','_','4',0,\n0x2a, 0xef, 0x01, 0x00, 0x06, 0xf5, 'F','a','r','s','i','_','5',0,\n0x2a, 0xf0, 0x01, 0x00, 0x06, 0xf6, 'F','a','r','s','i','_','6',0,\n0x2a, 0xf1, 0x01, 0x00, 0x06, 0xf7, 'F','a','r','s','i','_','7',0,\n0x2a, 0xf2, 0x01, 0x00, 0x06, 0xf8, 'F','a','r','s','i','_','8',0,\n0x2a, 0xf3, 0x01, 0x00, 0x06, 0xf9, 'F','a','r','s','i','_','9',0,\n0x6a, 0x3c, 0x01, 0x00, 0x06, 0x6a, 'A','r','a','b','i','c','_','p','e','r','c','e','n','t',0,\n0x0e, 0xd8, 0x01, 0x00, 0x06, 0x70, 'A','r','a','b','i','c','_','s','u','p','e','r','s','c','r','i','p','t','_','a','l','e','f',0,\n0xad, 0x32, 0x01, 0x00, 0x06, 0x79, 'A','r','a','b','i','c','_','t','t','e','h',0,\n0x56, 0x3a, 0x01, 0x00, 0x06, 0x7e, 'A','r','a','b','i','c','_','p','e','h',0,\n0x5a, 0x4a, 0x01, 0x00, 0x06, 0x86, 'A','r','a','b','i','c','_','t','c','h','e','h',0,\n0xac, 0x6e, 0x01, 0x00, 0x06, 0x88, 'A','r','a','b','i','c','_','d','d','a','l',0,\n0xad, 0x1a, 0x01, 0x00, 0x06, 0x91, 'A','r','a','b','i','c','_','r','r','e','h',0,\n0x59, 0xb7, 0x00, 0x00, 0x05, 0xac, 'A','r','a','b','i','c','_','c','o','m','m','a',0,\n0xd4, 0x36, 0x01, 0x00, 0x06, 0xd4, 'A','r','a','b','i','c','_','f','u','l','l','s','t','o','p',0,\n0x55, 0x02, 0x01, 0x00, 0x06, 0x60, 'A','r','a','b','i','c','_','0',0,\n0x55, 0x03, 0x01, 0x00, 0x06, 0x61, 'A','r','a','b','i','c','_','1',0,\n0x55, 0x04, 0x01, 0x00, 0x06, 0x62, 'A','r','a','b','i','c','_','2',0,\n0x55, 0x05, 0x01, 0x00, 0x06, 0x63, 'A','r','a','b','i','c','_','3',0,\n0x55, 0x06, 0x01, 0x00, 0x06, 0x64, 'A','r','a','b','i','c','_','4',0,\n0x55, 0x07, 0x01, 0x00, 0x06, 0x65, 'A','r','a','b','i','c','_','5',0,\n0x55, 0x08, 0x01, 0x00, 0x06, 0x66, 'A','r','a','b','i','c','_','6',0,\n0x55, 0x09, 0x01, 0x00, 0x06, 0x67, 'A','r','a','b','i','c','_','7',0,\n0x55, 0x0a, 0x01, 0x00, 0x06, 0x68, 'A','r','a','b','i','c','_','8',0,\n0x55, 0x0b, 0x01, 0x00, 0x06, 0x69, 'A','r','a','b','i','c','_','9',0,\n0xac, 0x84, 0x00, 0x00, 0x05, 0xbb, 'A','r','a','b','i','c','_','s','e','m','i','c','o','l','o','n',0,\n0x30, 0x2b, 0x00, 0x00, 0x05, 0xbf, 'A','r','a','b','i','c','_','q','u','e','s','t','i','o','n','_','m','a','r','k',0,\n0x59, 0xb1, 0x00, 0x00, 0x05, 0xc1, 'A','r','a','b','i','c','_','h','a','m','z','a',0,\n0x86, 0xe8, 0x00, 0x00, 0x05, 0xc2, 'A','r','a','b','i','c','_','m','a','d','d','a','o','n','a','l','e','f',0,\n0x86, 0xe8, 0x00, 0x00, 0x05, 0xc3, 'A','r','a','b','i','c','_','h','a','m','z','a','o','n','a','l','e','f',0,\n0x43, 0x95, 0x00, 0x00, 0x05, 0xc4, 'A','r','a','b','i','c','_','h','a','m','z','a','o','n','w','a','w',0,\n0x40, 0xa8, 0x00, 0x00, 0x05, 0xc5, 'A','r','a','b','i','c','_','h','a','m','z','a','u','n','d','e','r','a','l','e','f',0,\n0x43, 0x96, 0x00, 0x00, 0x05, 0xc6, 'A','r','a','b','i','c','_','h','a','m','z','a','o','n','y','e','h',0,\n0xac, 0x78, 0x00, 0x00, 0x05, 0xc7, 'A','r','a','b','i','c','_','a','l','e','f',0,\n0x56, 0x02, 0x00, 0x00, 0x05, 0xc8, 'A','r','a','b','i','c','_','b','e','h',0,\n0x59, 0xad, 0x00, 0x00, 0x05, 0xc9, 'A','r','a','b','i','c','_','t','e','h','m','a','r','b','u','t','a',0,\n0x56, 0x4a, 0x00, 0x00, 0x05, 0xca, 'A','r','a','b','i','c','_','t','e','h',0,\n0xad, 0x02, 0x00, 0x00, 0x05, 0xcb, 'A','r','a','b','i','c','_','t','h','e','h',0,\n0xac, 0xab, 0x00, 0x00, 0x05, 0xcc, 'A','r','a','b','i','c','_','j','e','e','m',0,\n0x56, 0x12, 0x00, 0x00, 0x05, 0xcd, 'A','r','a','b','i','c','_','h','a','h',0,\n0xac, 0xb2, 0x00, 0x00, 0x05, 0xce, 'A','r','a','b','i','c','_','k','h','a','h',0,\n0x56, 0x06, 0x00, 0x00, 0x05, 0xcf, 'A','r','a','b','i','c','_','d','a','l',0,\n0xac, 0xfe, 0x00, 0x00, 0x05, 0xd0, 'A','r','a','b','i','c','_','t','h','a','l',0,\n0xaa, 0xe9, 0x00, 0x00, 0x05, 0xd1, 'A','r','a','b','i','c','_','r','a',0,\n0xad, 0x24, 0x00, 0x00, 0x05, 0xd2, 'A','r','a','b','i','c','_','z','a','i','n',0,\n0xac, 0xf4, 0x00, 0x00, 0x05, 0xd3, 'A','r','a','b','i','c','_','s','e','e','n',0,\n0x5a, 0x5c, 0x00, 0x00, 0x05, 0xd4, 'A','r','a','b','i','c','_','s','h','e','e','n',0,\n0x56, 0x3a, 0x00, 0x00, 0x05, 0xd5, 'A','r','a','b','i','c','_','s','a','d',0,\n0x55, 0xfe, 0x00, 0x00, 0x05, 0xd6, 'A','r','a','b','i','c','_','d','a','d',0,\n0x56, 0x42, 0x00, 0x00, 0x05, 0xd7, 'A','r','a','b','i','c','_','t','a','h',0,\n0x56, 0x5a, 0x00, 0x00, 0x05, 0xd8, 'A','r','a','b','i','c','_','z','a','h',0,\n0x56, 0x0c, 0x00, 0x00, 0x05, 0xd9, 'A','r','a','b','i','c','_','a','i','n',0,\n0x59, 0x94, 0x00, 0x00, 0x05, 0xda, 'A','r','a','b','i','c','_','g','h','a','i','n',0,\n0x6b, 0x62, 0x00, 0x00, 0x05, 0xe0, 'A','r','a','b','i','c','_','t','a','t','w','e','e','l',0,\n0x56, 0x12, 0x00, 0x00, 0x05, 0xe1, 'A','r','a','b','i','c','_','f','e','h',0,\n0x56, 0x34, 0x00, 0x00, 0x05, 0xe2, 'A','r','a','b','i','c','_','q','a','f',0,\n0x56, 0x1c, 0x00, 0x00, 0x05, 0xe3, 'A','r','a','b','i','c','_','k','a','f',0,\n0x56, 0x27, 0x00, 0x00, 0x05, 0xe4, 'A','r','a','b','i','c','_','l','a','m',0,\n0xac, 0xc3, 0x00, 0x00, 0x05, 0xe5, 'A','r','a','b','i','c','_','m','e','e','m',0,\n0xad, 0x08, 0x00, 0x00, 0x05, 0xe6, 'A','r','a','b','i','c','_','n','o','o','n',0,\n0xaa, 0xd5, 0x00, 0x00, 0x05, 0xe7, 'A','r','a','b','i','c','_','h','a',0,\n0x56, 0x1a, 0x00, 0x00, 0x05, 0xe7, 'A','r','a','b','i','c','_','h','e','h',0,\n0x56, 0x5d, 0x00, 0x00, 0x05, 0xe8, 'A','r','a','b','i','c','_','w','a','w',0,\n0x70, 0xc1, 0x00, 0x00, 0x05, 0xe9, 'A','r','a','b','i','c','_','a','l','e','f','m','a','k','s','u','r','a',0,\n0x56, 0x5e, 0x00, 0x00, 0x05, 0xea, 'A','r','a','b','i','c','_','y','e','h',0,\n0xcf, 0x48, 0x00, 0x00, 0x05, 0xeb, 'A','r','a','b','i','c','_','f','a','t','h','a','t','a','n',0,\n0xcd, 0xb8, 0x00, 0x00, 0x05, 0xec, 'A','r','a','b','i','c','_','d','a','m','m','a','t','a','n',0,\n0xd2, 0x48, 0x00, 0x00, 0x05, 0xed, 'A','r','a','b','i','c','_','k','a','s','r','a','t','a','n',0,\n0x59, 0x89, 0x00, 0x00, 0x05, 0xee, 'A','r','a','b','i','c','_','f','a','t','h','a',0,\n0x59, 0x57, 0x00, 0x00, 0x05, 0xef, 'A','r','a','b','i','c','_','d','a','m','m','a',0,\n0x59, 0xe9, 0x00, 0x00, 0x05, 0xf0, 'A','r','a','b','i','c','_','k','a','s','r','a',0,\n0xb4, 0xe1, 0x00, 0x00, 0x05, 0xf1, 'A','r','a','b','i','c','_','s','h','a','d','d','a',0,\n0x5a, 0xfc, 0x00, 0x00, 0x05, 0xf2, 'A','r','a','b','i','c','_','s','u','k','u','n',0,\n0x84, 0x4d, 0x01, 0x00, 0x06, 0x53, 'A','r','a','b','i','c','_','m','a','d','d','a','_','a','b','o','v','e',0,\n0x84, 0x4d, 0x01, 0x00, 0x06, 0x54, 'A','r','a','b','i','c','_','h','a','m','z','a','_','a','b','o','v','e',0,\n0x84, 0x6d, 0x01, 0x00, 0x06, 0x55, 'A','r','a','b','i','c','_','h','a','m','z','a','_','b','e','l','o','w',0,\n0x56, 0x22, 0x01, 0x00, 0x06, 0x98, 'A','r','a','b','i','c','_','j','e','h',0,\n0x56, 0x52, 0x01, 0x00, 0x06, 0xa4, 'A','r','a','b','i','c','_','v','e','h',0,\n0x59, 0xca, 0x01, 0x00, 0x06, 0xa9, 'A','r','a','b','i','c','_','k','e','h','e','h',0,\n0x56, 0x0c, 0x01, 0x00, 0x06, 0xaf, 'A','r','a','b','i','c','_','g','a','f',0,\n0xb5, 0xbd, 0x01, 0x00, 0x06, 0xba, 'A','r','a','b','i','c','_','n','o','o','n','_','g','h','u','n','n','a',0,\n0xcb, 0xf3, 0x01, 0x00, 0x06, 0xbe, 'A','r','a','b','i','c','_','h','e','h','_','d','o','a','c','h','a','s','h','m','e','e',0,\n0xad, 0xfe, 0x01, 0x00, 0x06, 0xcc, 'F','a','r','s','i','_','y','e','h',0,\n0x9f, 0xfe, 0x01, 0x00, 0x06, 0xcc, 'A','r','a','b','i','c','_','f','a','r','s','i','_','y','e','h',0,\n0xaf, 0x7f, 0x01, 0x00, 0x06, 0xd2, 'A','r','a','b','i','c','_','y','e','h','_','b','a','r','e','e',0,\n0xcf, 0x52, 0x01, 0x00, 0x06, 0xc1, 'A','r','a','b','i','c','_','h','e','h','_','g','o','a','l',0,\n0xb6, 0x56, 0x00, 0x00, 0xff, 0x7e, 'A','r','a','b','i','c','_','s','w','i','t','c','h',0,\n0x29, 0x44, 0x01, 0x00, 0x04, 0x92, 'C','y','r','i','l','l','i','c','_','G','H','E','_','b','a','r',0,\n0x37, 0x44, 0x01, 0x00, 0x04, 0x93, 'C','y','r','i','l','l','i','c','_','g','h','e','_','b','a','r',0,\n0x9e, 0x2c, 0x01, 0x00, 0x04, 0x96, 'C','y','r','i','l','l','i','c','_','Z','H','E','_','d','e','s','c','e','n','d','e','r',0,\n0x1e, 0x2c, 0x01, 0x00, 0x04, 0x97, 'C','y','r','i','l','l','i','c','_','z','h','e','_','d','e','s','c','e','n','d','e','r',0,\n0x76, 0x2c, 0x01, 0x00, 0x04, 0x9a, 'C','y','r','i','l','l','i','c','_','K','A','_','d','e','s','c','e','n','d','e','r',0,\n0xf6, 0x2c, 0x01, 0x00, 0x04, 0x9b, 'C','y','r','i','l','l','i','c','_','k','a','_','d','e','s','c','e','n','d','e','r',0,\n0x17, 0x27, 0x01, 0x00, 0x04, 0x9c, 'C','y','r','i','l','l','i','c','_','K','A','_','v','e','r','t','s','t','r','o','k','e',0,\n0x17, 0x27, 0x01, 0x00, 0x04, 0x9d, 'C','y','r','i','l','l','i','c','_','k','a','_','v','e','r','t','s','t','r','o','k','e',0,\n0x7a, 0x2c, 0x01, 0x00, 0x04, 0xa2, 'C','y','r','i','l','l','i','c','_','E','N','_','d','e','s','c','e','n','d','e','r',0,\n0xfa, 0x2c, 0x01, 0x00, 0x04, 0xa3, 'C','y','r','i','l','l','i','c','_','e','n','_','d','e','s','c','e','n','d','e','r',0,\n0x9d, 0xf8, 0x01, 0x00, 0x04, 0xae, 'C','y','r','i','l','l','i','c','_','U','_','s','t','r','a','i','g','h','t',0,\n0xdd, 0xf8, 0x01, 0x00, 0x04, 0xaf, 'C','y','r','i','l','l','i','c','_','u','_','s','t','r','a','i','g','h','t',0,\n0xe5, 0x34, 0x01, 0x00, 0x04, 0xb0, 'C','y','r','i','l','l','i','c','_','U','_','s','t','r','a','i','g','h','t','_','b','a','r',0,\n0xe5, 0x34, 0x01, 0x00, 0x04, 0xb1, 'C','y','r','i','l','l','i','c','_','u','_','s','t','r','a','i','g','h','t','_','b','a','r',0,\n0x5e, 0x2c, 0x01, 0x00, 0x04, 0xb2, 'C','y','r','i','l','l','i','c','_','H','A','_','d','e','s','c','e','n','d','e','r',0,\n0xde, 0x2c, 0x01, 0x00, 0x04, 0xb3, 'C','y','r','i','l','l','i','c','_','h','a','_','d','e','s','c','e','n','d','e','r',0,\n0x2e, 0x2c, 0x01, 0x00, 0x04, 0xb6, 'C','y','r','i','l','l','i','c','_','C','H','E','_','d','e','s','c','e','n','d','e','r',0,\n0xae, 0x2c, 0x01, 0x00, 0x04, 0xb7, 'C','y','r','i','l','l','i','c','_','c','h','e','_','d','e','s','c','e','n','d','e','r',0,\n0x87, 0x27, 0x01, 0x00, 0x04, 0xb8, 'C','y','r','i','l','l','i','c','_','C','H','E','_','v','e','r','t','s','t','r','o','k','e',0,\n0x87, 0x27, 0x01, 0x00, 0x04, 0xb9, 'C','y','r','i','l','l','i','c','_','c','h','e','_','v','e','r','t','s','t','r','o','k','e',0,\n0x65, 0x19, 0x01, 0x00, 0x04, 0xba, 'C','y','r','i','l','l','i','c','_','S','H','H','A',0,\n0x66, 0xf9, 0x01, 0x00, 0x04, 0xbb, 'C','y','r','i','l','l','i','c','_','s','h','h','a',0,\n0xca, 0x77, 0x01, 0x00, 0x04, 0xd8, 'C','y','r','i','l','l','i','c','_','S','C','H','W','A',0,\n0xce, 0x57, 0x01, 0x00, 0x04, 0xd9, 'C','y','r','i','l','l','i','c','_','s','c','h','w','a',0,\n0x5f, 0x1c, 0x01, 0x00, 0x04, 0xe2, 'C','y','r','i','l','l','i','c','_','I','_','m','a','c','r','o','n',0,\n0x6f, 0x1c, 0x01, 0x00, 0x04, 0xe3, 'C','y','r','i','l','l','i','c','_','i','_','m','a','c','r','o','n',0,\n0xcb, 0xc4, 0x01, 0x00, 0x04, 0xe8, 'C','y','r','i','l','l','i','c','_','O','_','b','a','r',0,\n0xcd, 0xc4, 0x01, 0x00, 0x04, 0xe9, 'C','y','r','i','l','l','i','c','_','o','_','b','a','r',0,\n0x65, 0x1c, 0x01, 0x00, 0x04, 0xee, 'C','y','r','i','l','l','i','c','_','U','_','m','a','c','r','o','n',0,\n0x75, 0x1c, 0x01, 0x00, 0x04, 0xef, 'C','y','r','i','l','l','i','c','_','u','_','m','a','c','r','o','n',0,\n0xec, 0x01, 0x00, 0x00, 0x06, 0xa1, 'S','e','r','b','i','a','n','_','d','j','e',0,\n0xfd, 0xfd, 0x00, 0x00, 0x06, 0xa2, 'M','a','c','e','d','o','n','i','a','_','g','j','e',0,\n0xd9, 0x65, 0x00, 0x00, 0x06, 0xa3, 'C','y','r','i','l','l','i','c','_','i','o',0,\n0x02, 0x53, 0x00, 0x00, 0x06, 0xa4, 'U','k','r','a','i','n','i','a','n','_','i','e',0,\n0x01, 0x55, 0x00, 0x00, 0x06, 0xa4, 'U','k','r','a','n','i','a','n','_','j','e',0,\n0xfe, 0x03, 0x00, 0x00, 0x06, 0xa5, 'M','a','c','e','d','o','n','i','a','_','d','s','e',0,\n0x00, 0xf7, 0x00, 0x00, 0x06, 0xa6, 'U','k','r','a','i','n','i','a','n','_','i',0,\n0x80, 0x77, 0x00, 0x00, 0x06, 0xa6, 'U','k','r','a','n','i','a','n','_','i',0,\n0x02, 0x77, 0x00, 0x00, 0x06, 0xa7, 'U','k','r','a','i','n','i','a','n','_','y','i',0,\n0x01, 0x77, 0x00, 0x00, 0x06, 0xa7, 'U','k','r','a','n','i','a','n','_','y','i',0,\n0xd9, 0x5d, 0x00, 0x00, 0x06, 0xa8, 'C','y','r','i','l','l','i','c','_','j','e',0,\n0x75, 0xd5, 0x00, 0x00, 0x06, 0xa8, 'S','e','r','b','i','a','n','_','j','e',0,\n0xb3, 0x31, 0x00, 0x00, 0x06, 0xa9, 'C','y','r','i','l','l','i','c','_','l','j','e',0,\n0xec, 0x21, 0x00, 0x00, 0x06, 0xa9, 'S','e','r','b','i','a','n','_','l','j','e',0,\n0xb3, 0x39, 0x00, 0x00, 0x06, 0xaa, 'C','y','r','i','l','l','i','c','_','n','j','e',0,\n0xec, 0x29, 0x00, 0x00, 0x06, 0xaa, 'S','e','r','b','i','a','n','_','n','j','e',0,\n0xd9, 0x11, 0x00, 0x00, 0x06, 0xab, 'S','e','r','b','i','a','n','_','t','s','h','e',0,\n0xfe, 0x0d, 0x00, 0x00, 0x06, 0xac, 'M','a','c','e','d','o','n','i','a','_','k','j','e',0,\n0x12, 0x26, 0x00, 0x00, 0x06, 0xad, 'U','k','r','a','i','n','i','a','n','_','g','h','e','_','w','i','t','h','_','u','p','t','u','r','n',0,\n0x51, 0x3d, 0x00, 0x00, 0x06, 0xae, 'B','y','e','l','o','r','u','s','s','i','a','n','_','s','h','o','r','t','u',0,\n0x66, 0xcd, 0x00, 0x00, 0x06, 0xaf, 'C','y','r','i','l','l','i','c','_','d','z','h','e',0,\n0xec, 0x21, 0x00, 0x00, 0x06, 0xaf, 'S','e','r','b','i','a','n','_','d','z','e',0,\n0xbc, 0x68, 0x00, 0x00, 0x06, 0xb0, 'n','u','m','e','r','o','s','i','g','n',0,\n0xeb, 0x21, 0x00, 0x00, 0x06, 0xb1, 'S','e','r','b','i','a','n','_','D','J','E',0,\n0xfd, 0x1d, 0x00, 0x00, 0x06, 0xb2, 'M','a','c','e','d','o','n','i','a','_','G','J','E',0,\n0xd9, 0x05, 0x00, 0x00, 0x06, 0xb3, 'C','y','r','i','l','l','i','c','_','I','O',0,\n0x01, 0xf3, 0x00, 0x00, 0x06, 0xb4, 'U','k','r','a','i','n','i','a','n','_','I','E',0,\n0x00, 0xf5, 0x00, 0x00, 0x06, 0xb4, 'U','k','r','a','n','i','a','n','_','J','E',0,\n0xfd, 0x23, 0x00, 0x00, 0x06, 0xb5, 'M','a','c','e','d','o','n','i','a','_','D','S','E',0,\n0x00, 0xd7, 0x00, 0x00, 0x06, 0xb6, 'U','k','r','a','i','n','i','a','n','_','I',0,\n0x80, 0x57, 0x00, 0x00, 0x06, 0xb6, 'U','k','r','a','n','i','a','n','_','I',0,\n0x02, 0x17, 0x00, 0x00, 0x06, 0xb7, 'U','k','r','a','i','n','i','a','n','_','Y','I',0,\n0x01, 0x17, 0x00, 0x00, 0x06, 0xb7, 'U','k','r','a','n','i','a','n','_','Y','I',0,\n0xd8, 0xfd, 0x00, 0x00, 0x06, 0xb8, 'C','y','r','i','l','l','i','c','_','J','E',0,\n0x75, 0x75, 0x00, 0x00, 0x06, 0xb8, 'S','e','r','b','i','a','n','_','J','E',0,\n0xb2, 0x51, 0x00, 0x00, 0x06, 0xb9, 'C','y','r','i','l','l','i','c','_','L','J','E',0,\n0xeb, 0x41, 0x00, 0x00, 0x06, 0xb9, 'S','e','r','b','i','a','n','_','L','J','E',0,\n0xb2, 0x59, 0x00, 0x00, 0x06, 0xba, 'C','y','r','i','l','l','i','c','_','N','J','E',0,\n0xeb, 0x49, 0x00, 0x00, 0x06, 0xba, 'S','e','r','b','i','a','n','_','N','J','E',0,\n0xd7, 0x31, 0x00, 0x00, 0x06, 0xbb, 'S','e','r','b','i','a','n','_','T','S','H','E',0,\n0xfd, 0x2d, 0x00, 0x00, 0x06, 0xbc, 'M','a','c','e','d','o','n','i','a','_','K','J','E',0,\n0x1a, 0x46, 0x00, 0x00, 0x06, 0xbd, 'U','k','r','a','i','n','i','a','n','_','G','H','E','_','W','I','T','H','_','U','P','T','U','R','N',0,\n0x49, 0x5d, 0x00, 0x00, 0x06, 0xbe, 'B','y','e','l','o','r','u','s','s','i','a','n','_','S','H','O','R','T','U',0,\n0x64, 0xed, 0x00, 0x00, 0x06, 0xbf, 'C','y','r','i','l','l','i','c','_','D','Z','H','E',0,\n0xeb, 0x41, 0x00, 0x00, 0x06, 0xbf, 'S','e','r','b','i','a','n','_','D','Z','E',0,\n0xd9, 0x8b, 0x00, 0x00, 0x06, 0xc0, 'C','y','r','i','l','l','i','c','_','y','u',0,\n0x6c, 0x73, 0x00, 0x00, 0x06, 0xc1, 'C','y','r','i','l','l','i','c','_','a',0,\n0xd9, 0x4d, 0x00, 0x00, 0x06, 0xc2, 'C','y','r','i','l','l','i','c','_','b','e',0,\n0xb3, 0x63, 0x00, 0x00, 0x06, 0xc3, 'C','y','r','i','l','l','i','c','_','t','s','e',0,\n0xd9, 0x51, 0x00, 0x00, 0x06, 0xc4, 'C','y','r','i','l','l','i','c','_','d','e',0,\n0xd9, 0x5b, 0x00, 0x00, 0x06, 0xc5, 'C','y','r','i','l','l','i','c','_','i','e',0,\n0xd9, 0x54, 0x00, 0x00, 0x06, 0xc6, 'C','y','r','i','l','l','i','c','_','e','f',0,\n0xb3, 0x19, 0x00, 0x00, 0x06, 0xc7, 'C','y','r','i','l','l','i','c','_','g','h','e',0,\n0xd9, 0x55, 0x00, 0x00, 0x06, 0xc8, 'C','y','r','i','l','l','i','c','_','h','a',0,\n0x6c, 0x7b, 0x00, 0x00, 0x06, 0xc9, 'C','y','r','i','l','l','i','c','_','i',0,\n0x9d, 0xb1, 0x00, 0x00, 0x06, 0xca, 'C','y','r','i','l','l','i','c','_','s','h','o','r','t','i',0,\n0xd9, 0x5b, 0x00, 0x00, 0x06, 0xcb, 'C','y','r','i','l','l','i','c','_','k','a',0,\n0xd9, 0x5a, 0x00, 0x00, 0x06, 0xcc, 'C','y','r','i','l','l','i','c','_','e','l',0,\n0xd9, 0x5b, 0x00, 0x00, 0x06, 0xcd, 'C','y','r','i','l','l','i','c','_','e','m',0,\n0xd9, 0x5c, 0x00, 0x00, 0x06, 0xce, 'C','y','r','i','l','l','i','c','_','e','n',0,\n0x6c, 0x81, 0x00, 0x00, 0x06, 0xcf, 'C','y','r','i','l','l','i','c','_','o',0,\n0xd9, 0x69, 0x00, 0x00, 0x06, 0xd0, 'C','y','r','i','l','l','i','c','_','p','e',0,\n0xd9, 0x77, 0x00, 0x00, 0x06, 0xd1, 'C','y','r','i','l','l','i','c','_','y','a',0,\n0xd9, 0x60, 0x00, 0x00, 0x06, 0xd2, 'C','y','r','i','l','l','i','c','_','e','r',0,\n0xd9, 0x61, 0x00, 0x00, 0x06, 0xd3, 'C','y','r','i','l','l','i','c','_','e','s',0,\n0xd9, 0x71, 0x00, 0x00, 0x06, 0xd4, 'C','y','r','i','l','l','i','c','_','t','e',0,\n0x6c, 0x87, 0x00, 0x00, 0x06, 0xd5, 'C','y','r','i','l','l','i','c','_','u',0,\n0xb3, 0x65, 0x00, 0x00, 0x06, 0xd6, 'C','y','r','i','l','l','i','c','_','z','h','e',0,\n0xd9, 0x75, 0x00, 0x00, 0x06, 0xd7, 'C','y','r','i','l','l','i','c','_','v','e',0,\n0x78, 0xb8, 0x00, 0x00, 0x06, 0xd8, 'C','y','r','i','l','l','i','c','_','s','o','f','t','s','i','g','n',0,\n0x67, 0x45, 0x00, 0x00, 0x06, 0xd9, 'C','y','r','i','l','l','i','c','_','y','e','r','u',0,\n0xd9, 0x7d, 0x00, 0x00, 0x06, 0xda, 'C','y','r','i','l','l','i','c','_','z','e',0,\n0xb3, 0x45, 0x00, 0x00, 0x06, 0xdb, 'C','y','r','i','l','l','i','c','_','s','h','a',0,\n0x6c, 0x77, 0x00, 0x00, 0x06, 0xdc, 'C','y','r','i','l','l','i','c','_','e',0,\n0xce, 0x4d, 0x00, 0x00, 0x06, 0xdd, 'C','y','r','i','l','l','i','c','_','s','h','c','h','a',0,\n0xb3, 0x09, 0x00, 0x00, 0x06, 0xde, 'C','y','r','i','l','l','i','c','_','c','h','e',0,\n0x70, 0x38, 0x00, 0x00, 0x06, 0xdf, 'C','y','r','i','l','l','i','c','_','h','a','r','d','s','i','g','n',0,\n0xd9, 0x2b, 0x00, 0x00, 0x06, 0xe0, 'C','y','r','i','l','l','i','c','_','Y','U',0,\n0x6c, 0x53, 0x00, 0x00, 0x06, 0xe1, 'C','y','r','i','l','l','i','c','_','A',0,\n0xd8, 0xed, 0x00, 0x00, 0x06, 0xe2, 'C','y','r','i','l','l','i','c','_','B','E',0,\n0xb2, 0x83, 0x00, 0x00, 0x06, 0xe3, 'C','y','r','i','l','l','i','c','_','T','S','E',0,\n0xd8, 0xf1, 0x00, 0x00, 0x06, 0xe4, 'C','y','r','i','l','l','i','c','_','D','E',0,\n0xd8, 0xfb, 0x00, 0x00, 0x06, 0xe5, 'C','y','r','i','l','l','i','c','_','I','E',0,\n0xd8, 0xf4, 0x00, 0x00, 0x06, 0xe6, 'C','y','r','i','l','l','i','c','_','E','F',0,\n0xb2, 0x39, 0x00, 0x00, 0x06, 0xe7, 'C','y','r','i','l','l','i','c','_','G','H','E',0,\n0xd8, 0xf5, 0x00, 0x00, 0x06, 0xe8, 'C','y','r','i','l','l','i','c','_','H','A',0,\n0x6c, 0x5b, 0x00, 0x00, 0x06, 0xe9, 'C','y','r','i','l','l','i','c','_','I',0,\n0x95, 0xd1, 0x00, 0x00, 0x06, 0xea, 'C','y','r','i','l','l','i','c','_','S','H','O','R','T','I',0,\n0xd8, 0xfb, 0x00, 0x00, 0x06, 0xeb, 'C','y','r','i','l','l','i','c','_','K','A',0,\n0xd8, 0xfa, 0x00, 0x00, 0x06, 0xec, 'C','y','r','i','l','l','i','c','_','E','L',0,\n0xd8, 0xfb, 0x00, 0x00, 0x06, 0xed, 'C','y','r','i','l','l','i','c','_','E','M',0,\n0xd8, 0xfc, 0x00, 0x00, 0x06, 0xee, 'C','y','r','i','l','l','i','c','_','E','N',0,\n0x6c, 0x61, 0x00, 0x00, 0x06, 0xef, 'C','y','r','i','l','l','i','c','_','O',0,\n0xd9, 0x09, 0x00, 0x00, 0x06, 0xf0, 'C','y','r','i','l','l','i','c','_','P','E',0,\n0xd9, 0x17, 0x00, 0x00, 0x06, 0xf1, 'C','y','r','i','l','l','i','c','_','Y','A',0,\n0xd9, 0x00, 0x00, 0x00, 0x06, 0xf2, 'C','y','r','i','l','l','i','c','_','E','R',0,\n0xd9, 0x01, 0x00, 0x00, 0x06, 0xf3, 'C','y','r','i','l','l','i','c','_','E','S',0,\n0xd9, 0x11, 0x00, 0x00, 0x06, 0xf4, 'C','y','r','i','l','l','i','c','_','T','E',0,\n0x6c, 0x67, 0x00, 0x00, 0x06, 0xf5, 'C','y','r','i','l','l','i','c','_','U',0,\n0xb2, 0x85, 0x00, 0x00, 0x06, 0xf6, 'C','y','r','i','l','l','i','c','_','Z','H','E',0,\n0xd9, 0x15, 0x00, 0x00, 0x06, 0xf7, 'C','y','r','i','l','l','i','c','_','V','E',0,\n0x58, 0xd8, 0x00, 0x00, 0x06, 0xf8, 'C','y','r','i','l','l','i','c','_','S','O','F','T','S','I','G','N',0,\n0x65, 0x65, 0x00, 0x00, 0x06, 0xf9, 'C','y','r','i','l','l','i','c','_','Y','E','R','U',0,\n0xd9, 0x1d, 0x00, 0x00, 0x06, 0xfa, 'C','y','r','i','l','l','i','c','_','Z','E',0,\n0xb2, 0x65, 0x00, 0x00, 0x06, 0xfb, 'C','y','r','i','l','l','i','c','_','S','H','A',0,\n0x6c, 0x57, 0x00, 0x00, 0x06, 0xfc, 'C','y','r','i','l','l','i','c','_','E',0,\n0xca, 0x6d, 0x00, 0x00, 0x06, 0xfd, 'C','y','r','i','l','l','i','c','_','S','H','C','H','A',0,\n0xb2, 0x29, 0x00, 0x00, 0x06, 0xfe, 'C','y','r','i','l','l','i','c','_','C','H','E',0,\n0x50, 0x58, 0x00, 0x00, 0x06, 0xff, 'C','y','r','i','l','l','i','c','_','H','A','R','D','S','I','G','N',0,\n0xc0, 0x8c, 0x00, 0x00, 0x07, 0xa1, 'G','r','e','e','k','_','A','L','P','H','A','a','c','c','e','n','t',0,\n0x6d, 0x4c, 0x00, 0x00, 0x07, 0xa2, 'G','r','e','e','k','_','E','P','S','I','L','O','N','a','c','c','e','n','t',0,\n0x79, 0x8c, 0x00, 0x00, 0x07, 0xa3, 'G','r','e','e','k','_','E','T','A','a','c','c','e','n','t',0,\n0xf7, 0x8c, 0x00, 0x00, 0x07, 0xa4, 'G','r','e','e','k','_','I','O','T','A','a','c','c','e','n','t',0,\n0xe3, 0x39, 0x00, 0x00, 0x07, 0xa5, 'G','r','e','e','k','_','I','O','T','A','d','i','e','r','e','s','i','s',0,\n0xc4, 0xb9, 0x00, 0x00, 0x07, 0xa5, 'G','r','e','e','k','_','I','O','T','A','d','i','a','e','r','e','s','i','s',0,\n0xc7, 0x4c, 0x00, 0x00, 0x07, 0xa7, 'G','r','e','e','k','_','O','M','I','C','R','O','N','a','c','c','e','n','t',0,\n0x6d, 0x4c, 0x00, 0x00, 0x07, 0xa8, 'G','r','e','e','k','_','U','P','S','I','L','O','N','a','c','c','e','n','t',0,\n0xba, 0x39, 0x00, 0x00, 0x07, 0xa9, 'G','r','e','e','k','_','U','P','S','I','L','O','N','d','i','e','r','e','s','i','s',0,\n0xef, 0x0c, 0x00, 0x00, 0x07, 0xab, 'G','r','e','e','k','_','O','M','E','G','A','a','c','c','e','n','t',0,\n0xf2, 0x39, 0x00, 0x00, 0x07, 0xae, 'G','r','e','e','k','_','a','c','c','e','n','t','d','i','e','r','e','s','i','s',0,\n0x5c, 0x1c, 0x00, 0x00, 0x07, 0xaf, 'G','r','e','e','k','_','h','o','r','i','z','b','a','r',0,\n0xb8, 0x8c, 0x00, 0x00, 0x07, 0xb1, 'G','r','e','e','k','_','a','l','p','h','a','a','c','c','e','n','t',0,\n0x65, 0x4c, 0x00, 0x00, 0x07, 0xb2, 'G','r','e','e','k','_','e','p','s','i','l','o','n','a','c','c','e','n','t',0,\n0xb1, 0x8c, 0x00, 0x00, 0x07, 0xb3, 'G','r','e','e','k','_','e','t','a','a','c','c','e','n','t',0,\n0x6f, 0x8c, 0x00, 0x00, 0x07, 0xb4, 'G','r','e','e','k','_','i','o','t','a','a','c','c','e','n','t',0,\n0xc3, 0x39, 0x00, 0x00, 0x07, 0xb5, 'G','r','e','e','k','_','i','o','t','a','d','i','e','r','e','s','i','s',0,\n0xf2, 0x39, 0x00, 0x00, 0x07, 0xb6, 'G','r','e','e','k','_','i','o','t','a','a','c','c','e','n','t','d','i','e','r','e','s','i','s',0,\n0xbf, 0x4c, 0x00, 0x00, 0x07, 0xb7, 'G','r','e','e','k','_','o','m','i','c','r','o','n','a','c','c','e','n','t',0,\n0x65, 0x4c, 0x00, 0x00, 0x07, 0xb8, 'G','r','e','e','k','_','u','p','s','i','l','o','n','a','c','c','e','n','t',0,\n0x9a, 0x39, 0x00, 0x00, 0x07, 0xb9, 'G','r','e','e','k','_','u','p','s','i','l','o','n','d','i','e','r','e','s','i','s',0,\n0xb2, 0x39, 0x00, 0x00, 0x07, 0xba, 'G','r','e','e','k','_','u','p','s','i','l','o','n','a','c','c','e','n','t','d','i','e','r','e','s','i','s',0,\n0xe7, 0x0c, 0x00, 0x00, 0x07, 0xbb, 'G','r','e','e','k','_','o','m','e','g','a','a','c','c','e','n','t',0,\n0xc6, 0xa1, 0x00, 0x00, 0x07, 0xc1, 'G','r','e','e','k','_','A','L','P','H','A',0,\n0x63, 0x1d, 0x00, 0x00, 0x07, 0xc2, 'G','r','e','e','k','_','B','E','T','A',0,\n0xc6, 0xa7, 0x00, 0x00, 0x07, 0xc3, 'G','r','e','e','k','_','G','A','M','M','A',0,\n0xc6, 0xa1, 0x00, 0x00, 0x07, 0xc4, 'G','r','e','e','k','_','D','E','L','T','A',0,\n0x1d, 0x54, 0x00, 0x00, 0x07, 0xc5, 'G','r','e','e','k','_','E','P','S','I','L','O','N',0,\n0x63, 0xdd, 0x00, 0x00, 0x07, 0xc6, 'G','r','e','e','k','_','Z','E','T','A',0,\n0xb1, 0x85, 0x00, 0x00, 0x07, 0xc7, 'G','r','e','e','k','_','E','T','A',0,\n0xc7, 0x9d, 0x00, 0x00, 0x07, 0xc8, 'G','r','e','e','k','_','T','H','E','T','A',0,\n0x63, 0x7d, 0x00, 0x00, 0x07, 0xc9, 'G','r','e','e','k','_','I','O','T','A',0,\n0xc6, 0xf9, 0x00, 0x00, 0x07, 0xca, 'G','r','e','e','k','_','K','A','P','P','A',0,\n0xc6, 0xe5, 0x00, 0x00, 0x07, 0xcb, 'G','r','e','e','k','_','L','A','M','D','A',0,\n0x8e, 0x09, 0x00, 0x00, 0x07, 0xcb, 'G','r','e','e','k','_','L','A','M','B','D','A',0,\n0x58, 0xb3, 0x00, 0x00, 0x07, 0xcc, 'G','r','e','e','k','_','M','U',0,\n0x58, 0xb5, 0x00, 0x00, 0x07, 0xcd, 'G','r','e','e','k','_','N','U',0,\n0x58, 0xbd, 0x00, 0x00, 0x07, 0xce, 'G','r','e','e','k','_','X','I',0,\n0x1e, 0xbc, 0x00, 0x00, 0x07, 0xcf, 'G','r','e','e','k','_','O','M','I','C','R','O','N',0,\n0x58, 0xad, 0x00, 0x00, 0x07, 0xd0, 'G','r','e','e','k','_','P','I',0,\n0xb1, 0xaf, 0x00, 0x00, 0x07, 0xd1, 'G','r','e','e','k','_','R','H','O',0,\n0xc7, 0x8f, 0x00, 0x00, 0x07, 0xd2, 'G','r','e','e','k','_','S','I','G','M','A',0,\n0xb1, 0xaf, 0x00, 0x00, 0x07, 0xd4, 'G','r','e','e','k','_','T','A','U',0,\n0x21, 0x54, 0x00, 0x00, 0x07, 0xd5, 'G','r','e','e','k','_','U','P','S','I','L','O','N',0,\n0xb1, 0xa1, 0x00, 0x00, 0x07, 0xd6, 'G','r','e','e','k','_','P','H','I',0,\n0xb1, 0x6d, 0x00, 0x00, 0x07, 0xd7, 'G','r','e','e','k','_','C','H','I',0,\n0xb1, 0xb7, 0x00, 0x00, 0x07, 0xd8, 'G','r','e','e','k','_','P','S','I',0,\n0xc7, 0x5b, 0x00, 0x00, 0x07, 0xd9, 'G','r','e','e','k','_','O','M','E','G','A',0,\n0xca, 0x81, 0x00, 0x00, 0x07, 0xe1, 'G','r','e','e','k','_','a','l','p','h','a',0,\n0x64, 0xfd, 0x00, 0x00, 0x07, 0xe2, 'G','r','e','e','k','_','b','e','t','a',0,\n0xca, 0x87, 0x00, 0x00, 0x07, 0xe3, 'G','r','e','e','k','_','g','a','m','m','a',0,\n0xca, 0x81, 0x00, 0x00, 0x07, 0xe4, 'G','r','e','e','k','_','d','e','l','t','a',0,\n0x2d, 0x34, 0x00, 0x00, 0x07, 0xe5, 'G','r','e','e','k','_','e','p','s','i','l','o','n',0,\n0x65, 0xbd, 0x00, 0x00, 0x07, 0xe6, 'G','r','e','e','k','_','z','e','t','a',0,\n0xb2, 0x65, 0x00, 0x00, 0x07, 0xe7, 'G','r','e','e','k','_','e','t','a',0,\n0xcb, 0x7d, 0x00, 0x00, 0x07, 0xe8, 'G','r','e','e','k','_','t','h','e','t','a',0,\n0x65, 0x5d, 0x00, 0x00, 0x07, 0xe9, 'G','r','e','e','k','_','i','o','t','a',0,\n0xca, 0xd9, 0x00, 0x00, 0x07, 0xea, 'G','r','e','e','k','_','k','a','p','p','a',0,\n0xca, 0xc5, 0x00, 0x00, 0x07, 0xeb, 'G','r','e','e','k','_','l','a','m','d','a',0,\n0x95, 0xe9, 0x00, 0x00, 0x07, 0xeb, 'G','r','e','e','k','_','l','a','m','b','d','a',0,\n0x59, 0x13, 0x00, 0x00, 0x07, 0xec, 'G','r','e','e','k','_','m','u',0,\n0x59, 0x15, 0x00, 0x00, 0x07, 0xed, 'G','r','e','e','k','_','n','u',0,\n0x59, 0x1d, 0x00, 0x00, 0x07, 0xee, 'G','r','e','e','k','_','x','i',0,\n0x2e, 0x9c, 0x00, 0x00, 0x07, 0xef, 'G','r','e','e','k','_','o','m','i','c','r','o','n',0,\n0x59, 0x0d, 0x00, 0x00, 0x07, 0xf0, 'G','r','e','e','k','_','p','i',0,\n0xb2, 0x8f, 0x00, 0x00, 0x07, 0xf1, 'G','r','e','e','k','_','r','h','o',0,\n0xcb, 0x6f, 0x00, 0x00, 0x07, 0xf2, 'G','r','e','e','k','_','s','i','g','m','a',0,\n0x71, 0x4f, 0x00, 0x00, 0x07, 0xf3, 'G','r','e','e','k','_','f','i','n','a','l','s','m','a','l','l','s','i','g','m','a',0,\n0xb2, 0x8f, 0x00, 0x00, 0x07, 0xf4, 'G','r','e','e','k','_','t','a','u',0,\n0x31, 0x34, 0x00, 0x00, 0x07, 0xf5, 'G','r','e','e','k','_','u','p','s','i','l','o','n',0,\n0xb2, 0x81, 0x00, 0x00, 0x07, 0xf6, 'G','r','e','e','k','_','p','h','i',0,\n0xb2, 0x4d, 0x00, 0x00, 0x07, 0xf7, 'G','r','e','e','k','_','c','h','i',0,\n0xb2, 0x97, 0x00, 0x00, 0x07, 0xf8, 'G','r','e','e','k','_','p','s','i',0,\n0xcb, 0x3b, 0x00, 0x00, 0x07, 0xf9, 'G','r','e','e','k','_','o','m','e','g','a',0,\n0x98, 0x56, 0x00, 0x00, 0xff, 0x7e, 'G','r','e','e','k','_','s','w','i','t','c','h',0,\n0x4e, 0xe2, 0x00, 0x00, 0x08, 0xa1, 'l','e','f','t','r','a','d','i','c','a','l',0,\n0x3e, 0xe2, 0x00, 0x00, 0x08, 0xa2, 't','o','p','l','e','f','t','r','a','d','i','c','a','l',0,\n0xe8, 0x48, 0x00, 0x00, 0x08, 0xa3, 'h','o','r','i','z','c','o','n','n','e','c','t','o','r',0,\n0x88, 0xfe, 0x00, 0x00, 0x08, 0xa4, 't','o','p','i','n','t','e','g','r','a','l',0,\n0x44, 0xfe, 0x00, 0x00, 0x08, 0xa5, 'b','o','t','i','n','t','e','g','r','a','l',0,\n0x08, 0x48, 0x00, 0x00, 0x08, 0xa6, 'v','e','r','t','c','o','n','n','e','c','t','o','r',0,\n0x06, 0x52, 0x00, 0x00, 0x08, 0xa7, 't','o','p','l','e','f','t','s','q','b','r','a','c','k','e','t',0,\n0x86, 0x52, 0x00, 0x00, 0x08, 0xa8, 'b','o','t','l','e','f','t','s','q','b','r','a','c','k','e','t',0,\n0xee, 0x52, 0x00, 0x00, 0x08, 0xa9, 't','o','p','r','i','g','h','t','s','q','b','r','a','c','k','e','t',0,\n0xee, 0x52, 0x00, 0x00, 0x08, 0xaa, 'b','o','t','r','i','g','h','t','s','q','b','r','a','c','k','e','t',0,\n0x1f, 0x83, 0x00, 0x00, 0x08, 0xab, 't','o','p','l','e','f','t','p','a','r','e','n','s',0,\n0x0f, 0x83, 0x00, 0x00, 0x08, 0xac, 'b','o','t','l','e','f','t','p','a','r','e','n','s',0,\n0x5c, 0x83, 0x00, 0x00, 0x08, 0xad, 't','o','p','r','i','g','h','t','p','a','r','e','n','s',0,\n0x3c, 0x83, 0x00, 0x00, 0x08, 0xae, 'b','o','t','r','i','g','h','t','p','a','r','e','n','s',0,\n0x1e, 0x7f, 0x00, 0x00, 0x08, 0xaf, 'l','e','f','t','m','i','d','d','l','e','c','u','r','l','y','b','r','a','c','e',0,\n0x1e, 0x7f, 0x00, 0x00, 0x08, 0xb0, 'r','i','g','h','t','m','i','d','d','l','e','c','u','r','l','y','b','r','a','c','e',0,\n0x0b, 0x00, 0x00, 0x00, 0x08, 0xb1, 't','o','p','l','e','f','t','s','u','m','m','a','t','i','o','n',0,\n0x8b, 0x00, 0x00, 0x00, 0x08, 0xb2, 'b','o','t','l','e','f','t','s','u','m','m','a','t','i','o','n',0,\n0xd0, 0x48, 0x00, 0x00, 0x08, 0xb3, 't','o','p','v','e','r','t','s','u','m','m','a','t','i','o','n','c','o','n','n','e','c','t','o','r',0,\n0xd0, 0x48, 0x00, 0x00, 0x08, 0xb4, 'b','o','t','v','e','r','t','s','u','m','m','a','t','i','o','n','c','o','n','n','e','c','t','o','r',0,\n0xf3, 0x00, 0x00, 0x00, 0x08, 0xb5, 't','o','p','r','i','g','h','t','s','u','m','m','a','t','i','o','n',0,\n0xf3, 0x00, 0x00, 0x00, 0x08, 0xb6, 'b','o','t','r','i','g','h','t','s','u','m','m','a','t','i','o','n',0,\n0x1d, 0x00, 0x00, 0x00, 0x08, 0xb7, 'r','i','g','h','t','m','i','d','d','l','e','s','u','m','m','a','t','i','o','n',0,\n0x74, 0xda, 0x00, 0x00, 0x08, 0xbc, 'l','e','s','s','t','h','a','n','e','q','u','a','l',0,\n0x6e, 0x1a, 0x00, 0x00, 0x08, 0xbd, 'n','o','t','e','q','u','a','l',0,\n0xa2, 0xda, 0x00, 0x00, 0x08, 0xbe, 'g','r','e','a','t','e','r','t','h','a','n','e','q','u','a','l',0,\n0x6a, 0xfe, 0x00, 0x00, 0x08, 0xbf, 'i','n','t','e','g','r','a','l',0,\n0xdc, 0x05, 0x00, 0x00, 0x08, 0xc0, 't','h','e','r','e','f','o','r','e',0,\n0xdc, 0xc0, 0x00, 0x00, 0x08, 0xc1, 'v','a','r','i','a','t','i','o','n',0,\n0x69, 0xc5, 0x00, 0x00, 0x08, 0xc2, 'i','n','f','i','n','i','t','y',0,\n0x0c, 0xa9, 0x00, 0x00, 0x08, 0xc5, 'n','a','b','l','a',0,\n0x44, 0x89, 0x00, 0x00, 0x08, 0xc8, 'a','p','p','r','o','x','i','m','a','t','e',0,\n0xe8, 0x5a, 0x00, 0x00, 0x08, 0xc9, 's','i','m','i','l','a','r','e','q','u','a','l',0,\n0x69, 0x3c, 0x00, 0x00, 0x08, 0xcd, 'i','f','o','n','l','y','i','f',0,\n0x35, 0x21, 0x00, 0x00, 0x08, 0xce, 'i','m','p','l','i','e','s',0,\n0xcf, 0x42, 0x00, 0x00, 0x08, 0xcf, 'i','d','e','n','t','i','c','a','l',0,\n0x34, 0xe2, 0x00, 0x00, 0x08, 0xd6, 'r','a','d','i','c','a','l',0,\n0xa7, 0x58, 0x00, 0x00, 0x08, 0xda, 'i','n','c','l','u','d','e','d','i','n',0,\n0x69, 0x95, 0x00, 0x00, 0x08, 0xdb, 'i','n','c','l','u','d','e','s',0,\n0xbc, 0x20, 0x00, 0x00, 0x08, 0xdc, 'i','n','t','e','r','s','e','c','t','i','o','n',0,\n0x0d, 0xb0, 0x00, 0x00, 0x08, 0xdd, 'u','n','i','o','n',0,\n0xad, 0x54, 0x00, 0x00, 0x08, 0xde, 'l','o','g','i','c','a','l','a','n','d',0,\n0xd6, 0x98, 0x00, 0x00, 0x08, 0xdf, 'l','o','g','i','c','a','l','o','r',0,\n0x63, 0xa5, 0x00, 0x00, 0x08, 0xef, 'p','a','r','t','i','a','l','d','e','r','i','v','a','t','i','v','e',0,\n0x6a, 0xc0, 0x00, 0x00, 0x08, 0xf6, 'f','u','n','c','t','i','o','n',0,\n0xd3, 0x3d, 0x00, 0x00, 0x08, 0xfb, 'l','e','f','t','a','r','r','o','w',0,\n0x37, 0xfd, 0x00, 0x00, 0x08, 0xfc, 'u','p','a','r','r','o','w',0,\n0xb5, 0xbd, 0x00, 0x00, 0x08, 0xfd, 'r','i','g','h','t','a','r','r','o','w',0,\n0xd3, 0xbd, 0x00, 0x00, 0x08, 0xfe, 'd','o','w','n','a','r','r','o','w',0,\n0x0c, 0x4b, 0x00, 0x00, 0x09, 0xdf, 'b','l','a','n','k',0,\n0xf9, 0x94, 0x00, 0x00, 0x09, 0xe0, 's','o','l','i','d','d','i','a','m','o','n','d',0,\n0x4e, 0x64, 0x00, 0x00, 0x09, 0xe1, 'c','h','e','c','k','e','r','b','o','a','r','d',0,\n0x01, 0x44, 0x00, 0x00, 0x09, 0xe2, 'h','t',0,\n0x01, 0x32, 0x00, 0x00, 0x09, 0xe3, 'f','f',0,\n0x01, 0x38, 0x00, 0x00, 0x09, 0xe4, 'c','r',0,\n0x01, 0x3e, 0x00, 0x00, 0x09, 0xe5, 'l','f',0,\n0x01, 0x48, 0x00, 0x00, 0x09, 0xe8, 'n','l',0,\n0x01, 0x60, 0x00, 0x00, 0x09, 0xe9, 'v','t',0,\n0x93, 0xd4, 0x00, 0x00, 0x09, 0xea, 'l','o','w','r','i','g','h','t','c','o','r','n','e','r',0,\n0x3b, 0xd4, 0x00, 0x00, 0x09, 0xeb, 'u','p','r','i','g','h','t','c','o','r','n','e','r',0,\n0x0e, 0xd4, 0x00, 0x00, 0x09, 0xec, 'u','p','l','e','f','t','c','o','r','n','e','r',0,\n0xba, 0xd4, 0x00, 0x00, 0x09, 0xed, 'l','o','w','l','e','f','t','c','o','r','n','e','r',0,\n0x3e, 0xdd, 0x00, 0x00, 0x09, 0xee, 'c','r','o','s','s','i','n','g','l','i','n','e','s',0,\n0xed, 0x79, 0x00, 0x00, 0x09, 0xef, 'h','o','r','i','z','l','i','n','e','s','c','a','n','1',0,\n0xed, 0x7b, 0x00, 0x00, 0x09, 0xf0, 'h','o','r','i','z','l','i','n','e','s','c','a','n','3',0,\n0xed, 0x7d, 0x00, 0x00, 0x09, 0xf1, 'h','o','r','i','z','l','i','n','e','s','c','a','n','5',0,\n0xed, 0x7f, 0x00, 0x00, 0x09, 0xf2, 'h','o','r','i','z','l','i','n','e','s','c','a','n','7',0,\n0xed, 0x81, 0x00, 0x00, 0x09, 0xf3, 'h','o','r','i','z','l','i','n','e','s','c','a','n','9',0,\n0x0c, 0xdc, 0x00, 0x00, 0x09, 0xf4, 'l','e','f','t','t',0,\n0x1b, 0x04, 0x00, 0x00, 0x09, 0xf5, 'r','i','g','h','t','t',0,\n0x06, 0x28, 0x00, 0x00, 0x09, 0xf6, 'b','o','t','t',0,\n0x06, 0xb0, 0x00, 0x00, 0x09, 0xf7, 't','o','p','t',0,\n0x37, 0x9c, 0x00, 0x00, 0x09, 0xf8, 'v','e','r','t','b','a','r',0,\n0x34, 0x3f, 0x00, 0x00, 0x0a, 0xa1, 'e','m','s','p','a','c','e',0,\n0x34, 0x5f, 0x00, 0x00, 0x0a, 0xa2, 'e','n','s','p','a','c','e',0,\n0x61, 0x7f, 0x00, 0x00, 0x0a, 0xa3, 'e','m','3','s','p','a','c','e',0,\n0x61, 0x9f, 0x00, 0x00, 0x0a, 0xa4, 'e','m','4','s','p','a','c','e',0,\n0x9a, 0x9f, 0x00, 0x00, 0x0a, 0xa5, 'd','i','g','i','t','s','p','a','c','e',0,\n0xc0, 0x9f, 0x00, 0x00, 0x0a, 0xa6, 'p','u','n','c','t','s','p','a','c','e',0,\n0xdd, 0x5f, 0x00, 0x00, 0x0a, 0xa7, 't','h','i','n','s','p','a','c','e',0,\n0xce, 0x5f, 0x00, 0x00, 0x0a, 0xa8, 'h','a','i','r','s','p','a','c','e',0,\n0x19, 0x62, 0x00, 0x00, 0x0a, 0xa9, 'e','m','d','a','s','h',0,\n0x19, 0x72, 0x00, 0x00, 0x0a, 0xaa, 'e','n','d','a','s','h',0,\n0x6f, 0x4b, 0x00, 0x00, 0x0a, 0xac, 's','i','g','n','i','f','b','l','a','n','k',0,\n0x68, 0x21, 0x00, 0x00, 0x0a, 0xae, 'e','l','l','i','p','s','i','s',0,\n0x64, 0x8a, 0x00, 0x00, 0x0a, 0xaf, 'd','o','u','b','b','a','s','e','l','i','n','e','d','o','t',0,\n0x6d, 0x0c, 0x00, 0x00, 0x0a, 0xb0, 'o','n','e','t','h','i','r','d',0,\n0xe6, 0x8b, 0x00, 0x00, 0x0a, 0xb1, 't','w','o','t','h','i','r','d','s',0,\n0x6c, 0x30, 0x00, 0x00, 0x0a, 0xb2, 'o','n','e','f','i','f','t','h',0,\n0xe4, 0xd3, 0x00, 0x00, 0x0a, 0xb3, 't','w','o','f','i','f','t','h','s',0,\n0x77, 0x53, 0x00, 0x00, 0x0a, 0xb4, 't','h','r','e','e','f','i','f','t','h','s',0,\n0xab, 0x93, 0x00, 0x00, 0x0a, 0xb5, 'f','o','u','r','f','i','f','t','h','s',0,\n0x6d, 0x48, 0x00, 0x00, 0x0a, 0xb6, 'o','n','e','s','i','x','t','h',0,\n0xa5, 0x03, 0x00, 0x00, 0x0a, 0xb7, 'f','i','v','e','s','i','x','t','h','s',0,\n0x18, 0xd8, 0x00, 0x00, 0x0a, 0xb8, 'c','a','r','e','o','f',0,\n0x33, 0x02, 0x00, 0x00, 0x0a, 0xbb, 'f','i','g','d','a','s','h',0,\n0x9f, 0x52, 0x00, 0x00, 0x0a, 0xbc, 'l','e','f','t','a','n','g','l','e','b','r','a','c','k','e','t',0,\n0x4c, 0xac, 0x00, 0x00, 0x0a, 0xbd, 'd','e','c','i','m','a','l','p','o','i','n','t',0,\n0xdf, 0x52, 0x00, 0x00, 0x0a, 0xbe, 'r','i','g','h','t','a','n','g','l','e','b','r','a','c','k','e','t',0,\n0x1a, 0x28, 0x00, 0x00, 0x0a, 0xbf, 'm','a','r','k','e','r',0,\n0xd8, 0x98, 0x00, 0x00, 0x0a, 0xc3, 'o','n','e','e','i','g','h','t','h',0,\n0xee, 0xa3, 0x00, 0x00, 0x0a, 0xc4, 't','h','r','e','e','e','i','g','h','t','h','s',0,\n0x45, 0xa3, 0x00, 0x00, 0x0a, 0xc5, 'f','i','v','e','e','i','g','h','t','h','s',0,\n0xe7, 0x23, 0x00, 0x00, 0x0a, 0xc6, 's','e','v','e','n','e','i','g','h','t','h','s',0,\n0xde, 0x4b, 0x00, 0x00, 0x0a, 0xc9, 't','r','a','d','e','m','a','r','k',0,\n0xc3, 0x0b, 0x00, 0x00, 0x0a, 0xca, 's','i','g','n','a','t','u','r','e','m','a','r','k',0,\n0xb4, 0x49, 0x00, 0x00, 0x0a, 0xcb, 't','r','a','d','e','m','a','r','k','i','n','c','i','r','c','l','e',0,\n0x1f, 0xf9, 0x00, 0x00, 0x0a, 0xcc, 'l','e','f','t','o','p','e','n','t','r','i','a','n','g','l','e',0,\n0x5f, 0xf9, 0x00, 0x00, 0x0a, 0xcd, 'r','i','g','h','t','o','p','e','n','t','r','i','a','n','g','l','e',0,\n0x91, 0x49, 0x00, 0x00, 0x0a, 0xce, 'e','m','o','p','e','n','c','i','r','c','l','e',0,\n0x98, 0x19, 0x00, 0x00, 0x0a, 0xcf, 'e','m','o','p','e','n','r','e','c','t','a','n','g','l','e',0,\n0x54, 0x4b, 0x00, 0x00, 0x0a, 0xd0, 'l','e','f','t','s','i','n','g','l','e','q','u','o','t','e','m','a','r','k',0,\n0x54, 0x4b, 0x00, 0x00, 0x0a, 0xd1, 'r','i','g','h','t','s','i','n','g','l','e','q','u','o','t','e','m','a','r','k',0,\n0x9c, 0x4b, 0x00, 0x00, 0x0a, 0xd2, 'l','e','f','t','d','o','u','b','l','e','q','u','o','t','e','m','a','r','k',0,\n0x9c, 0x4b, 0x00, 0x00, 0x0a, 0xd3, 'r','i','g','h','t','d','o','u','b','l','e','q','u','o','t','e','m','a','r','k',0,\n0xed, 0xb0, 0x00, 0x00, 0x0a, 0xd4, 'p','r','e','s','c','r','i','p','t','i','o','n',0,\n0x6c, 0x85, 0x00, 0x00, 0x0a, 0xd5, 'p','e','r','m','i','l','l','e',0,\n0x35, 0xf5, 0x00, 0x00, 0x0a, 0xd6, 'm','i','n','u','t','e','s',0,\n0x35, 0xfb, 0x00, 0x00, 0x0a, 0xd7, 's','e','c','o','n','d','s',0,\n0xa7, 0xd5, 0x00, 0x00, 0x0a, 0xd9, 'l','a','t','i','n','c','r','o','s','s',0,\n0x68, 0x7f, 0x00, 0x00, 0x0a, 0xda, 'h','e','x','a','g','r','a','m',0,\n0xe9, 0x5e, 0x00, 0x00, 0x0a, 0xdb, 'f','i','l','l','e','d','r','e','c','t','b','u','l','l','e','t',0,\n0x09, 0x1e, 0x00, 0x00, 0x0a, 0xdc, 'f','i','l','l','e','d','l','e','f','t','t','r','i','b','u','l','l','e','t',0,\n0xf1, 0x1e, 0x00, 0x00, 0x0a, 0xdd, 'f','i','l','l','e','d','r','i','g','h','t','t','r','i','b','u','l','l','e','t',0,\n0xec, 0xc9, 0x00, 0x00, 0x0a, 0xde, 'e','m','f','i','l','l','e','d','c','i','r','c','l','e',0,\n0x7b, 0x3e, 0x00, 0x00, 0x0a, 0xdf, 'e','m','f','i','l','l','e','d','r','e','c','t',0,\n0x5a, 0x9e, 0x00, 0x00, 0x0a, 0xe0, 'e','n','o','p','e','n','c','i','r','c','b','u','l','l','e','t',0,\n0x13, 0x1e, 0x00, 0x00, 0x0a, 0xe1, 'e','n','o','p','e','n','s','q','u','a','r','e','b','u','l','l','e','t',0,\n0x71, 0x5e, 0x00, 0x00, 0x0a, 0xe2, 'o','p','e','n','r','e','c','t','b','u','l','l','e','t',0,\n0x05, 0xd2, 0x00, 0x00, 0x0a, 0xe3, 'o','p','e','n','t','r','i','b','u','l','l','e','t','u','p',0,\n0x18, 0x18, 0x00, 0x00, 0x0a, 0xe4, 'o','p','e','n','t','r','i','b','u','l','l','e','t','d','o','w','n',0,\n0x6d, 0x9c, 0x00, 0x00, 0x0a, 0xe5, 'o','p','e','n','s','t','a','r',0,\n0xd2, 0x9e, 0x00, 0x00, 0x0a, 0xe6, 'e','n','f','i','l','l','e','d','c','i','r','c','b','u','l','l','e','t',0,\n0xfd, 0x9e, 0x00, 0x00, 0x0a, 0xe7, 'e','n','f','i','l','l','e','d','s','q','b','u','l','l','e','t',0,\n0xf5, 0xd2, 0x00, 0x00, 0x0a, 0xe8, 'f','i','l','l','e','d','t','r','i','b','u','l','l','e','t','u','p',0,\n0xd8, 0x18, 0x00, 0x00, 0x0a, 0xe9, 'f','i','l','l','e','d','t','r','i','b','u','l','l','e','t','d','o','w','n',0,\n0x50, 0xec, 0x00, 0x00, 0x0a, 0xea, 'l','e','f','t','p','o','i','n','t','e','r',0,\n0xda, 0xec, 0x00, 0x00, 0x0a, 0xeb, 'r','i','g','h','t','p','o','i','n','t','e','r',0,\n0x06, 0x14, 0x00, 0x00, 0x0a, 0xec, 'c','l','u','b',0,\n0x32, 0x94, 0x00, 0x00, 0x0a, 0xed, 'd','i','a','m','o','n','d',0,\n0x0c, 0x84, 0x00, 0x00, 0x0a, 0xee, 'h','e','a','r','t',0,\n0xa0, 0xb5, 0x00, 0x00, 0x0a, 0xf0, 'm','a','l','t','e','s','e','c','r','o','s','s',0,\n0x18, 0xa0, 0x00, 0x00, 0x0a, 0xf1, 'd','a','g','g','e','r',0,\n0x8f, 0xe0, 0x00, 0x00, 0x0a, 0xf2, 'd','o','u','b','l','e','d','a','g','g','e','r',0,\n0xc9, 0x8b, 0x00, 0x00, 0x0a, 0xf3, 'c','h','e','c','k','m','a','r','k',0,\n0x23, 0x15, 0x00, 0x00, 0x0a, 0xf4, 'b','a','l','l','o','t','c','r','o','s','s',0,\n0xef, 0x88, 0x00, 0x00, 0x0a, 0xf5, 'm','u','s','i','c','a','l','s','h','a','r','p',0,\n0x77, 0x36, 0x00, 0x00, 0x0a, 0xf6, 'm','u','s','i','c','a','l','f','l','a','t',0,\n0xa6, 0x6a, 0x00, 0x00, 0x0a, 0xf7, 'm','a','l','e','s','y','m','b','o','l',0,\n0x6a, 0x6a, 0x00, 0x00, 0x0a, 0xf8, 'f','e','m','a','l','e','s','y','m','b','o','l',0,\n0xdb, 0x5d, 0x00, 0x00, 0x0a, 0xf9, 't','e','l','e','p','h','o','n','e',0,\n0xc8, 0xec, 0x00, 0x00, 0x0a, 0xfa, 't','e','l','e','p','h','o','n','e','r','e','c','o','r','d','e','r',0,\n0x2a, 0xe8, 0x00, 0x00, 0x0a, 0xfb, 'p','h','o','n','o','g','r','a','p','h','c','o','p','y','r','i','g','h','t',0,\n0x0c, 0x3e, 0x00, 0x00, 0x0a, 0xfc, 'c','a','r','e','t',0,\n0x7c, 0x4b, 0x00, 0x00, 0x0a, 0xfd, 's','i','n','g','l','e','l','o','w','q','u','o','t','e','m','a','r','k',0,\n0xbc, 0x4b, 0x00, 0x00, 0x0a, 0xfe, 'd','o','u','b','l','e','l','o','w','q','u','o','t','e','m','a','r','k',0,\n0x1a, 0x5c, 0x00, 0x00, 0x0a, 0xff, 'c','u','r','s','o','r',0,\n0xd2, 0xbe, 0x00, 0x00, 0x0b, 0xa3, 'l','e','f','t','c','a','r','e','t',0,\n0xb5, 0x3e, 0x00, 0x00, 0x0b, 0xa6, 'r','i','g','h','t','c','a','r','e','t',0,\n0xd3, 0x3e, 0x00, 0x00, 0x0b, 0xa8, 'd','o','w','n','c','a','r','e','t',0,\n0x37, 0x7e, 0x00, 0x00, 0x0b, 0xa9, 'u','p','c','a','r','e','t',0,\n0x37, 0x1c, 0x00, 0x00, 0x0b, 0xc0, 'o','v','e','r','b','a','r',0,\n0x69, 0xd5, 0x00, 0x00, 0x0b, 0xc2, 'd','o','w','n','t','a','c','k',0,\n0x1c, 0x1b, 0x00, 0x00, 0x0b, 0xc3, 'u','p','s','h','o','e',0,\n0xd4, 0xb1, 0x00, 0x00, 0x0b, 0xc4, 'd','o','w','n','s','t','i','l','e',0,\n0x6f, 0x1c, 0x00, 0x00, 0x0b, 0xc6, 'u','n','d','e','r','b','a','r',0,\n0x02, 0xfa, 0x00, 0x00, 0x0b, 0xca, 'j','o','t',0,\n0x06, 0x82, 0x00, 0x00, 0x0b, 0xcc, 'q','u','a','d',0,\n0x1b, 0xf5, 0x00, 0x00, 0x0b, 0xce, 'u','p','t','a','c','k',0,\n0x19, 0x49, 0x00, 0x00, 0x0b, 0xcf, 'c','i','r','c','l','e',0,\n0x38, 0xf1, 0x00, 0x00, 0x0b, 0xd3, 'u','p','s','t','i','l','e',0,\n0x69, 0xfb, 0x00, 0x00, 0x0b, 0xd6, 'd','o','w','n','s','h','o','e',0,\n0xda, 0xfb, 0x00, 0x00, 0x0b, 0xd8, 'r','i','g','h','t','s','h','o','e',0,\n0x69, 0xbb, 0x00, 0x00, 0x0b, 0xda, 'l','e','f','t','s','h','o','e',0,\n0x69, 0x95, 0x00, 0x00, 0x0b, 0xdc, 'l','e','f','t','t','a','c','k',0,\n0xda, 0xd5, 0x00, 0x00, 0x0b, 0xfc, 'r','i','g','h','t','t','a','c','k',0,\n0x45, 0x15, 0x00, 0x00, 0x0c, 0xdf, 'h','e','b','r','e','w','_','d','o','u','b','l','e','l','o','w','l','i','n','e',0,\n0x72, 0x6c, 0x00, 0x00, 0x0c, 0xe0, 'h','e','b','r','e','w','_','a','l','e','p','h',0,\n0x9c, 0x4e, 0x00, 0x00, 0x0c, 0xe1, 'h','e','b','r','e','w','_','b','e','t',0,\n0x39, 0x04, 0x00, 0x00, 0x0c, 0xe1, 'h','e','b','r','e','w','_','b','e','t','h',0,\n0x72, 0xc2, 0x00, 0x00, 0x0c, 0xe2, 'h','e','b','r','e','w','_','g','i','m','e','l',0,\n0xe6, 0x02, 0x00, 0x00, 0x0c, 0xe2, 'h','e','b','r','e','w','_','g','i','m','m','e','l',0,\n0x72, 0x56, 0x00, 0x00, 0x0c, 0xe3, 'h','e','b','r','e','w','_','d','a','l','e','t',0,\n0xe5, 0x14, 0x00, 0x00, 0x0c, 0xe3, 'h','e','b','r','e','w','_','d','a','l','e','t','h',0,\n0xcd, 0xf9, 0x00, 0x00, 0x0c, 0xe4, 'h','e','b','r','e','w','_','h','e',0,\n0x9c, 0x9d, 0x00, 0x00, 0x0c, 0xe5, 'h','e','b','r','e','w','_','w','a','w',0,\n0x39, 0xa4, 0x00, 0x00, 0x0c, 0xe6, 'h','e','b','r','e','w','_','z','a','i','n',0,\n0x73, 0xec, 0x00, 0x00, 0x0c, 0xe6, 'h','e','b','r','e','w','_','z','a','y','i','n',0,\n0x39, 0x06, 0x00, 0x00, 0x0c, 0xe7, 'h','e','b','r','e','w','_','c','h','e','t',0,\n0x9c, 0x66, 0x00, 0x00, 0x0c, 0xe7, 'h','e','b','r','e','w','_','h','e','t',0,\n0x9c, 0x96, 0x00, 0x00, 0x0c, 0xe8, 'h','e','b','r','e','w','_','t','e','t',0,\n0x39, 0x94, 0x00, 0x00, 0x0c, 0xe8, 'h','e','b','r','e','w','_','t','e','t','h',0,\n0x9c, 0xae, 0x00, 0x00, 0x0c, 0xe9, 'h','e','b','r','e','w','_','y','o','d',0,\n0x31, 0x04, 0x00, 0x00, 0x0c, 0xea, 'h','e','b','r','e','w','_','f','i','n','a','l','k','a','p','h',0,\n0x39, 0x34, 0x00, 0x00, 0x0c, 0xeb, 'h','e','b','r','e','w','_','k','a','p','h',0,\n0x72, 0xca, 0x00, 0x00, 0x0c, 0xec, 'h','e','b','r','e','w','_','l','a','m','e','d',0,\n0x98, 0x5b, 0x00, 0x00, 0x0c, 0xed, 'h','e','b','r','e','w','_','f','i','n','a','l','m','e','m',0,\n0x9c, 0x73, 0x00, 0x00, 0x0c, 0xee, 'h','e','b','r','e','w','_','m','e','m',0,\n0x98, 0x80, 0x00, 0x00, 0x0c, 0xef, 'h','e','b','r','e','w','_','f','i','n','a','l','n','u','n',0,\n0x9c, 0x98, 0x00, 0x00, 0x0c, 0xf0, 'h','e','b','r','e','w','_','n','u','n',0,\n0xe6, 0xda, 0x00, 0x00, 0x0c, 0xf1, 'h','e','b','r','e','w','_','s','a','m','e','c','h',0,\n0xe6, 0xea, 0x00, 0x00, 0x0c, 0xf1, 'h','e','b','r','e','w','_','s','a','m','e','k','h',0,\n0x39, 0x3c, 0x00, 0x00, 0x0c, 0xf2, 'h','e','b','r','e','w','_','a','y','i','n',0,\n0xcb, 0xfd, 0x00, 0x00, 0x0c, 0xf3, 'h','e','b','r','e','w','_','f','i','n','a','l','p','e',0,\n0xce, 0x09, 0x00, 0x00, 0x0c, 0xf4, 'h','e','b','r','e','w','_','p','e',0,\n0x31, 0x61, 0x00, 0x00, 0x0c, 0xf5, 'h','e','b','r','e','w','_','f','i','n','a','l','z','a','d','e',0,\n0x31, 0x65, 0x00, 0x00, 0x0c, 0xf5, 'h','e','b','r','e','w','_','f','i','n','a','l','z','a','d','i',0,\n0x39, 0x91, 0x00, 0x00, 0x0c, 0xf6, 'h','e','b','r','e','w','_','z','a','d','e',0,\n0x39, 0x95, 0x00, 0x00, 0x0c, 0xf6, 'h','e','b','r','e','w','_','z','a','d','i',0,\n0x39, 0x9c, 0x00, 0x00, 0x0c, 0xf7, 'h','e','b','r','e','w','_','q','o','p','h',0,\n0x9c, 0x84, 0x00, 0x00, 0x0c, 0xf7, 'h','e','b','r','e','w','_','k','u','f',0,\n0x39, 0x82, 0x00, 0x00, 0x0c, 0xf8, 'h','e','b','r','e','w','_','r','e','s','h',0,\n0x39, 0x88, 0x00, 0x00, 0x0c, 0xf9, 'h','e','b','r','e','w','_','s','h','i','n',0,\n0x9c, 0x91, 0x00, 0x00, 0x0c, 0xfa, 'h','e','b','r','e','w','_','t','a','w',0,\n0x9c, 0x80, 0x00, 0x00, 0x0c, 0xfa, 'h','e','b','r','e','w','_','t','a','f',0,\n0xe8, 0x56, 0x00, 0x00, 0xff, 0x7e, 'H','e','b','r','e','w','_','s','w','i','t','c','h',0,\n0x73, 0x9f, 0x00, 0x00, 0x0d, 0xa1, 'T','h','a','i','_','k','o','k','a','i',0,\n0xcf, 0x53, 0x00, 0x00, 0x0d, 0xa2, 'T','h','a','i','_','k','h','o','k','h','a','i',0,\n0x9f, 0x5a, 0x00, 0x00, 0x0d, 0xa3, 'T','h','a','i','_','k','h','o','k','h','u','a','t',0,\n0x9f, 0x57, 0x00, 0x00, 0x0d, 0xa4, 'T','h','a','i','_','k','h','o','k','h','w','a','i',0,\n0xcf, 0x74, 0x00, 0x00, 0x0d, 0xa5, 'T','h','a','i','_','k','h','o','k','h','o','n',0,\n0x7e, 0xd7, 0x00, 0x00, 0x0d, 0xa6, 'T','h','a','i','_','k','h','o','r','a','k','h','a','n','g',0,\n0xe7, 0xe3, 0x00, 0x00, 0x0d, 0xa7, 'T','h','a','i','_','n','g','o','n','g','u',0,\n0xcd, 0x18, 0x00, 0x00, 0x0d, 0xa8, 'T','h','a','i','_','c','h','o','c','h','a','n',0,\n0x9a, 0xb7, 0x00, 0x00, 0x0d, 0xa9, 'T','h','a','i','_','c','h','o','c','h','i','n','g',0,\n0x9a, 0x97, 0x00, 0x00, 0x0d, 0xaa, 'T','h','a','i','_','c','h','o','c','h','a','n','g',0,\n0xb9, 0xf9, 0x00, 0x00, 0x0d, 0xab, 'T','h','a','i','_','s','o','s','o',0,\n0xcd, 0x2b, 0x00, 0x00, 0x0d, 0xac, 'T','h','a','i','_','c','h','o','c','h','o','e',0,\n0xe9, 0xff, 0x00, 0x00, 0x0d, 0xad, 'T','h','a','i','_','y','o','y','i','n','g',0,\n0xcd, 0x7d, 0x00, 0x00, 0x0d, 0xae, 'T','h','a','i','_','d','o','c','h','a','d','a',0,\n0xd2, 0x65, 0x00, 0x00, 0x0d, 0xaf, 'T','h','a','i','_','t','o','p','a','t','a','k',0,\n0xd1, 0xe0, 0x00, 0x00, 0x0d, 0xb0, 'T','h','a','i','_','t','h','o','t','h','a','n',0,\n0x84, 0xcf, 0x00, 0x00, 0x0d, 0xb1, 'T','h','a','i','_','t','h','o','n','a','n','g','m','o','n','t','h','o',0,\n0x92, 0x41, 0x00, 0x00, 0x0d, 0xb2, 'T','h','a','i','_','t','h','o','p','h','u','t','h','a','o',0,\n0x73, 0xe8, 0x00, 0x00, 0x0d, 0xb3, 'T','h','a','i','_','n','o','n','e','n',0,\n0x73, 0x1d, 0x00, 0x00, 0x0d, 0xb4, 'T','h','a','i','_','d','o','d','e','k',0,\n0x74, 0x59, 0x00, 0x00, 0x0d, 0xb5, 'T','h','a','i','_','t','o','t','a','o',0,\n0xa4, 0x77, 0x00, 0x00, 0x0d, 0xb6, 'T','h','a','i','_','t','h','o','t','h','u','n','g',0,\n0x48, 0x98, 0x00, 0x00, 0x0d, 0xb7, 'T','h','a','i','_','t','h','o','t','h','a','h','a','n',0,\n0xa4, 0x5f, 0x00, 0x00, 0x0d, 0xb8, 'T','h','a','i','_','t','h','o','t','h','o','n','g',0,\n0xb9, 0xcd, 0x00, 0x00, 0x0d, 0xb9, 'T','h','a','i','_','n','o','n','u',0,\n0x9a, 0x37, 0x00, 0x00, 0x0d, 0xba, 'T','h','a','i','_','b','o','b','a','i','m','a','i',0,\n0x74, 0x11, 0x00, 0x00, 0x0d, 0xbb, 'T','h','a','i','_','p','o','p','l','a',0,\n0xa2, 0x37, 0x00, 0x00, 0x0d, 0xbc, 'T','h','a','i','_','p','h','o','p','h','u','n','g',0,\n0xb9, 0x69, 0x00, 0x00, 0x0d, 0xbd, 'T','h','a','i','_','f','o','f','a',0,\n0xd0, 0xc0, 0x00, 0x00, 0x0d, 0xbe, 'T','h','a','i','_','p','h','o','p','h','a','n',0,\n0x73, 0x40, 0x00, 0x00, 0x0d, 0xbf, 'T','h','a','i','_','f','o','f','a','n',0,\n0x89, 0x81, 0x00, 0x00, 0x0d, 0xc0, 'T','h','a','i','_','p','h','o','s','a','m','p','h','a','o',0,\n0xb9, 0xaf, 0x00, 0x00, 0x0d, 0xc1, 'T','h','a','i','_','m','o','m','a',0,\n0x74, 0xb9, 0x00, 0x00, 0x0d, 0xc2, 'T','h','a','i','_','y','o','y','a','k',0,\n0x74, 0x4b, 0x00, 0x00, 0x0d, 0xc3, 'T','h','a','i','_','r','o','r','u','a',0,\n0x2e, 0x2d, 0x00, 0x00, 0x0d, 0xc4, 'T','h','a','i','_','r','u',0,\n0xe7, 0xf7, 0x00, 0x00, 0x0d, 0xc5, 'T','h','a','i','_','l','o','l','i','n','g',0,\n0x2e, 0x21, 0x00, 0x00, 0x0d, 0xc6, 'T','h','a','i','_','l','u',0,\n0xe9, 0x84, 0x00, 0x00, 0x0d, 0xc7, 'T','h','a','i','_','w','o','w','a','e','n',0,\n0xe8, 0xe5, 0x00, 0x00, 0x0d, 0xc8, 'T','h','a','i','_','s','o','s','a','l','a',0,\n0xe9, 0x43, 0x00, 0x00, 0x0d, 0xc9, 'T','h','a','i','_','s','o','r','u','s','i',0,\n0x74, 0x5f, 0x00, 0x00, 0x0d, 0xca, 'T','h','a','i','_','s','o','s','u','a',0,\n0x73, 0x7a, 0x00, 0x00, 0x0d, 0xcb, 'T','h','a','i','_','h','o','h','i','p',0,\n0xcf, 0xdd, 0x00, 0x00, 0x0d, 0xcc, 'T','h','a','i','_','l','o','c','h','u','l','a',0,\n0xb9, 0x8f, 0x00, 0x00, 0x0d, 0xcd, 'T','h','a','i','_','o','a','n','g',0,\n0x9f, 0xbd, 0x00, 0x00, 0x0d, 0xce, 'T','h','a','i','_','h','o','n','o','k','h','u','k',0,\n0x40, 0x5f, 0x00, 0x00, 0x0d, 0xcf, 'T','h','a','i','_','p','a','i','y','a','n','n','o','i',0,\n0x73, 0xc3, 0x00, 0x00, 0x0d, 0xd0, 'T','h','a','i','_','s','a','r','a','a',0,\n0x76, 0x6a, 0x00, 0x00, 0x0d, 0xd1, 'T','h','a','i','_','m','a','i','h','a','n','a','k','a','t',0,\n0xe7, 0xe7, 0x00, 0x00, 0x0d, 0xd2, 'T','h','a','i','_','s','a','r','a','a','a',0,\n0xe7, 0xf3, 0x00, 0x00, 0x0d, 0xd3, 'T','h','a','i','_','s','a','r','a','a','m',0,\n0x73, 0xcb, 0x00, 0x00, 0x0d, 0xd4, 'T','h','a','i','_','s','a','r','a','i',0,\n0xe7, 0xff, 0x00, 0x00, 0x0d, 0xd5, 'T','h','a','i','_','s','a','r','a','i','i',0,\n0xe8, 0x13, 0x00, 0x00, 0x0d, 0xd6, 'T','h','a','i','_','s','a','r','a','u','e',0,\n0xd0, 0x8b, 0x00, 0x00, 0x0d, 0xd7, 'T','h','a','i','_','s','a','r','a','u','e','e',0,\n0x73, 0xd7, 0x00, 0x00, 0x0d, 0xd8, 'T','h','a','i','_','s','a','r','a','u',0,\n0xe8, 0x23, 0x00, 0x00, 0x0d, 0xd9, 'T','h','a','i','_','s','a','r','a','u','u',0,\n0xd0, 0x95, 0x00, 0x00, 0x0d, 0xda, 'T','h','a','i','_','p','h','i','n','t','h','u',0,\n0x66, 0xc7, 0x00, 0x00, 0x0d, 0xde, 'T','h','a','i','_','m','a','i','h','a','n','a','k','a','t','_','m','a','i','t','h','o',0,\n0xb9, 0x28, 0x00, 0x00, 0x0d, 0xdf, 'T','h','a','i','_','b','a','h','t',0,\n0x73, 0xc7, 0x00, 0x00, 0x0d, 0xe0, 'T','h','a','i','_','s','a','r','a','e',0,\n0xe7, 0xeb, 0x00, 0x00, 0x0d, 0xe1, 'T','h','a','i','_','s','a','r','a','a','e',0,\n0x73, 0xd1, 0x00, 0x00, 0x0d, 0xe2, 'T','h','a','i','_','s','a','r','a','o',0,\n0x2b, 0xdc, 0x00, 0x00, 0x0d, 0xe3, 'T','h','a','i','_','s','a','r','a','a','i','m','a','i','m','u','a','n',0,\n0x57, 0x93, 0x00, 0x00, 0x0d, 0xe4, 'T','h','a','i','_','s','a','r','a','a','i','m','a','i','m','a','l','a','i',0,\n0xed, 0xcd, 0x00, 0x00, 0x0d, 0xe5, 'T','h','a','i','_','l','a','k','k','h','a','n','g','y','a','o',0,\n0x9e, 0x75, 0x00, 0x00, 0x0d, 0xe6, 'T','h','a','i','_','m','a','i','y','a','m','o','k',0,\n0x3c, 0x89, 0x00, 0x00, 0x0d, 0xe7, 'T','h','a','i','_','m','a','i','t','a','i','k','h','u',0,\n0x73, 0x51, 0x00, 0x00, 0x0d, 0xe8, 'T','h','a','i','_','m','a','i','e','k',0,\n0xe7, 0x47, 0x00, 0x00, 0x0d, 0xe9, 'T','h','a','i','_','m','a','i','t','h','o',0,\n0xe7, 0x55, 0x00, 0x00, 0x0d, 0xea, 'T','h','a','i','_','m','a','i','t','r','i',0,\n0xec, 0x53, 0x00, 0x00, 0x0d, 0xeb, 'T','h','a','i','_','m','a','i','c','h','a','t','t','a','w','a',0,\n0x16, 0x3e, 0x00, 0x00, 0x0d, 0xec, 'T','h','a','i','_','t','h','a','n','t','h','a','k','h','a','t',0,\n0xa0, 0x0e, 0x00, 0x00, 0x0d, 0xed, 'T','h','a','i','_','n','i','k','h','a','h','i','t',0,\n0xe7, 0x8c, 0x00, 0x00, 0x0d, 0xf0, 'T','h','a','i','_','l','e','k','s','u','n',0,\n0xcf, 0x57, 0x00, 0x00, 0x0d, 0xf1, 'T','h','a','i','_','l','e','k','n','u','n','g',0,\n0xcf, 0x67, 0x00, 0x00, 0x0d, 0xf2, 'T','h','a','i','_','l','e','k','s','o','n','g',0,\n0xe7, 0x63, 0x00, 0x00, 0x0d, 0xf3, 'T','h','a','i','_','l','e','k','s','a','m',0,\n0x73, 0x83, 0x00, 0x00, 0x0d, 0xf4, 'T','h','a','i','_','l','e','k','s','i',0,\n0x73, 0x65, 0x00, 0x00, 0x0d, 0xf5, 'T','h','a','i','_','l','e','k','h','a',0,\n0xe7, 0x51, 0x00, 0x00, 0x0d, 0xf6, 'T','h','a','i','_','l','e','k','h','o','k',0,\n0xce, 0xc6, 0x00, 0x00, 0x0d, 0xf7, 'T','h','a','i','_','l','e','k','c','h','e','t',0,\n0xcf, 0x12, 0x00, 0x00, 0x0d, 0xf8, 'T','h','a','i','_','l','e','k','p','a','e','t',0,\n0xe7, 0x45, 0x00, 0x00, 0x0d, 0xf9, 'T','h','a','i','_','l','e','k','k','a','o',0,\n0x15, 0x72, 0x00, 0x00, 0xff, 0x31, 'H','a','n','g','u','l',0,\n0x74, 0x0c, 0x00, 0x00, 0xff, 0x32, 'H','a','n','g','u','l','_','S','t','a','r','t',0,\n0x5c, 0x6c, 0x00, 0x00, 0xff, 0x33, 'H','a','n','g','u','l','_','E','n','d',0,\n0x72, 0xd5, 0x00, 0x00, 0xff, 0x34, 'H','a','n','g','u','l','_','H','a','n','j','a',0,\n0xb9, 0x4d, 0x00, 0x00, 0xff, 0x35, 'H','a','n','g','u','l','_','J','a','m','o',0,\n0xe8, 0x11, 0x00, 0x00, 0xff, 0x36, 'H','a','n','g','u','l','_','R','o','m','a','j','a',0,\n0x33, 0x3e, 0x00, 0x00, 0xff, 0x37, 'H','a','n','g','u','l','_','C','o','d','e','i','n','p','u','t',0,\n0xe6, 0xb5, 0x00, 0x00, 0xff, 0x38, 'H','a','n','g','u','l','_','J','e','o','n','j','a',0,\n0x72, 0x75, 0x00, 0x00, 0xff, 0x39, 'H','a','n','g','u','l','_','B','a','n','j','a',0,\n0x9e, 0x95, 0x00, 0x00, 0xff, 0x3a, 'H','a','n','g','u','l','_','P','r','e','H','a','n','j','a',0,\n0x43, 0x35, 0x00, 0x00, 0xff, 0x3b, 'H','a','n','g','u','l','_','P','o','s','t','H','a','n','j','a',0,\n0x9a, 0x01, 0x00, 0x00, 0xff, 0x3c, 'H','a','n','g','u','l','_','S','i','n','g','l','e','C','a','n','d','i','d','a','t','e',0,\n0x32, 0x01, 0x00, 0x00, 0xff, 0x3d, 'H','a','n','g','u','l','_','M','u','l','t','i','p','l','e','C','a','n','d','i','d','a','t','e',0,\n0x6a, 0x01, 0x00, 0x00, 0xff, 0x3e, 'H','a','n','g','u','l','_','P','r','e','v','i','o','u','s','C','a','n','d','i','d','a','t','e',0,\n0xd0, 0x7a, 0x00, 0x00, 0xff, 0x3f, 'H','a','n','g','u','l','_','S','p','e','c','i','a','l',0,\n0xec, 0xd6, 0x00, 0x00, 0xff, 0x7e, 'H','a','n','g','u','l','_','s','w','i','t','c','h',0,\n0xe7, 0x51, 0x00, 0x00, 0x0e, 0xa1, 'H','a','n','g','u','l','_','K','i','y','e','o','g',0,\n0x12, 0x51, 0x00, 0x00, 0x0e, 0xa2, 'H','a','n','g','u','l','_','S','s','a','n','g','K','i','y','e','o','g',0,\n0x7a, 0x9d, 0x00, 0x00, 0x0e, 0xa3, 'H','a','n','g','u','l','_','K','i','y','e','o','g','S','i','o','s',0,\n0x73, 0x74, 0x00, 0x00, 0x0e, 0xa4, 'H','a','n','g','u','l','_','N','i','e','u','n',0,\n0x79, 0x50, 0x00, 0x00, 0x0e, 0xa5, 'H','a','n','g','u','l','_','N','i','e','u','n','J','i','e','u','j',0,\n0x79, 0x2e, 0x00, 0x00, 0x0e, 0xa6, 'H','a','n','g','u','l','_','N','i','e','u','n','H','i','e','u','h',0,\n0xe6, 0x0a, 0x00, 0x00, 0x0e, 0xa7, 'H','a','n','g','u','l','_','D','i','k','e','u','d',0,\n0x11, 0x0a, 0x00, 0x00, 0x0e, 0xa8, 'H','a','n','g','u','l','_','S','s','a','n','g','D','i','k','e','u','d',0,\n0x73, 0xb2, 0x00, 0x00, 0x0e, 0xa9, 'H','a','n','g','u','l','_','R','i','e','u','l',0,\n0x03, 0x11, 0x00, 0x00, 0x0e, 0xaa, 'H','a','n','g','u','l','_','R','i','e','u','l','K','i','y','e','o','g',0,\n0x81, 0x43, 0x00, 0x00, 0x0e, 0xab, 'H','a','n','g','u','l','_','R','i','e','u','l','M','i','e','u','m',0,\n0x81, 0x68, 0x00, 0x00, 0x0e, 0xac, 'H','a','n','g','u','l','_','R','i','e','u','l','P','i','e','u','b',0,\n0x40, 0xad, 0x00, 0x00, 0x0e, 0xad, 'H','a','n','g','u','l','_','R','i','e','u','l','S','i','o','s',0,\n0x81, 0xba, 0x00, 0x00, 0x0e, 0xae, 'H','a','n','g','u','l','_','R','i','e','u','l','T','i','e','u','t',0,\n0x03, 0x2c, 0x00, 0x00, 0x0e, 0xaf, 'H','a','n','g','u','l','_','R','i','e','u','l','P','h','i','e','u','f',0,\n0x80, 0xee, 0x00, 0x00, 0x0e, 0xb0, 'H','a','n','g','u','l','_','R','i','e','u','l','H','i','e','u','h',0,\n0x73, 0x63, 0x00, 0x00, 0x0e, 0xb1, 'H','a','n','g','u','l','_','M','i','e','u','m',0,\n0x73, 0x88, 0x00, 0x00, 0x0e, 0xb2, 'H','a','n','g','u','l','_','P','i','e','u','b',0,\n0x89, 0x08, 0x00, 0x00, 0x0e, 0xb3, 'H','a','n','g','u','l','_','S','s','a','n','g','P','i','e','u','b',0,\n0x3e, 0x0d, 0x00, 0x00, 0x0e, 0xb4, 'H','a','n','g','u','l','_','P','i','e','u','b','S','i','o','s',0,\n0xb9, 0xbd, 0x00, 0x00, 0x0e, 0xb5, 'H','a','n','g','u','l','_','S','i','o','s',0,\n0x44, 0x7d, 0x00, 0x00, 0x0e, 0xb6, 'H','a','n','g','u','l','_','S','s','a','n','g','S','i','o','s',0,\n0x73, 0x2f, 0x00, 0x00, 0x0e, 0xb7, 'H','a','n','g','u','l','_','I','e','u','n','g',0,\n0x73, 0x30, 0x00, 0x00, 0x0e, 0xb8, 'H','a','n','g','u','l','_','J','i','e','u','j',0,\n0x88, 0xb0, 0x00, 0x00, 0x0e, 0xb9, 'H','a','n','g','u','l','_','S','s','a','n','g','J','i','e','u','j',0,\n0x72, 0xb9, 0x00, 0x00, 0x0e, 0xba, 'H','a','n','g','u','l','_','C','i','e','u','c',0,\n0xe6, 0xd7, 0x00, 0x00, 0x0e, 0xbb, 'H','a','n','g','u','l','_','K','h','i','e','u','q',0,\n0x73, 0xda, 0x00, 0x00, 0x0e, 0xbc, 'H','a','n','g','u','l','_','T','i','e','u','t',0,\n0xe7, 0x6c, 0x00, 0x00, 0x0e, 0xbd, 'H','a','n','g','u','l','_','P','h','i','e','u','f',0,\n0x73, 0x0e, 0x00, 0x00, 0x0e, 0xbe, 'H','a','n','g','u','l','_','H','i','e','u','h',0,\n0x56, 0xc7, 0x00, 0x00, 0x0e, 0xbf, 'H','a','n','g','u','l','_','A',0,\n0xad, 0xd3, 0x00, 0x00, 0x0e, 0xc0, 'H','a','n','g','u','l','_','A','E',0,\n0xad, 0xff, 0x00, 0x00, 0x0e, 0xc1, 'H','a','n','g','u','l','_','Y','A',0,\n0x5c, 0x43, 0x00, 0x00, 0x0e, 0xc2, 'H','a','n','g','u','l','_','Y','A','E',0,\n0xad, 0xe5, 0x00, 0x00, 0x0e, 0xc3, 'H','a','n','g','u','l','_','E','O',0,\n0x56, 0xcb, 0x00, 0x00, 0x0e, 0xc4, 'H','a','n','g','u','l','_','E',0,\n0x5c, 0x55, 0x00, 0x00, 0x0e, 0xc5, 'H','a','n','g','u','l','_','Y','E','O',0,\n0xae, 0x03, 0x00, 0x00, 0x0e, 0xc6, 'H','a','n','g','u','l','_','Y','E',0,\n0x56, 0xd5, 0x00, 0x00, 0x0e, 0xc7, 'H','a','n','g','u','l','_','O',0,\n0xad, 0xfb, 0x00, 0x00, 0x0e, 0xc8, 'H','a','n','g','u','l','_','W','A',0,\n0x5c, 0x3b, 0x00, 0x00, 0x0e, 0xc9, 'H','a','n','g','u','l','_','W','A','E',0,\n0xad, 0xef, 0x00, 0x00, 0x0e, 0xca, 'H','a','n','g','u','l','_','O','E',0,\n0xae, 0x0d, 0x00, 0x00, 0x0e, 0xcb, 'H','a','n','g','u','l','_','Y','O',0,\n0x56, 0xdb, 0x00, 0x00, 0x0e, 0xcc, 'H','a','n','g','u','l','_','U',0,\n0x5c, 0x4d, 0x00, 0x00, 0x0e, 0xcd, 'H','a','n','g','u','l','_','W','E','O',0,\n0xad, 0xff, 0x00, 0x00, 0x0e, 0xce, 'H','a','n','g','u','l','_','W','E',0,\n0xae, 0x03, 0x00, 0x00, 0x0e, 0xcf, 'H','a','n','g','u','l','_','W','I',0,\n0xae, 0x13, 0x00, 0x00, 0x0e, 0xd0, 'H','a','n','g','u','l','_','Y','U',0,\n0xad, 0xeb, 0x00, 0x00, 0x0e, 0xd1, 'H','a','n','g','u','l','_','E','U',0,\n0xae, 0x07, 0x00, 0x00, 0x0e, 0xd2, 'H','a','n','g','u','l','_','Y','I',0,\n0x56, 0xcf, 0x00, 0x00, 0x0e, 0xd3, 'H','a','n','g','u','l','_','I',0,\n0x96, 0x51, 0x00, 0x00, 0x0e, 0xd4, 'H','a','n','g','u','l','_','J','_','K','i','y','e','o','g',0,\n0xf2, 0x51, 0x00, 0x00, 0x0e, 0xd5, 'H','a','n','g','u','l','_','J','_','S','s','a','n','g','K','i','y','e','o','g',0,\n0x6a, 0x9d, 0x00, 0x00, 0x0e, 0xd6, 'H','a','n','g','u','l','_','J','_','K','i','y','e','o','g','S','i','o','s',0,\n0xca, 0xf4, 0x00, 0x00, 0x0e, 0xd7, 'H','a','n','g','u','l','_','J','_','N','i','e','u','n',0,\n0x69, 0x50, 0x00, 0x00, 0x0e, 0xd8, 'H','a','n','g','u','l','_','J','_','N','i','e','u','n','J','i','e','u','j',0,\n0x69, 0x2e, 0x00, 0x00, 0x0e, 0xd9, 'H','a','n','g','u','l','_','J','_','N','i','e','u','n','H','i','e','u','h',0,\n0x95, 0x0a, 0x00, 0x00, 0x0e, 0xda, 'H','a','n','g','u','l','_','J','_','D','i','k','e','u','d',0,\n0xcb, 0x32, 0x00, 0x00, 0x0e, 0xdb, 'H','a','n','g','u','l','_','J','_','R','i','e','u','l',0,\n0xe3, 0x11, 0x00, 0x00, 0x0e, 0xdc, 'H','a','n','g','u','l','_','J','_','R','i','e','u','l','K','i','y','e','o','g',0,\n0x71, 0x43, 0x00, 0x00, 0x0e, 0xdd, 'H','a','n','g','u','l','_','J','_','R','i','e','u','l','M','i','e','u','m',0,\n0x71, 0x68, 0x00, 0x00, 0x0e, 0xde, 'H','a','n','g','u','l','_','J','_','R','i','e','u','l','P','i','e','u','b',0,\n0xb8, 0xad, 0x00, 0x00, 0x0e, 0xdf, 'H','a','n','g','u','l','_','J','_','R','i','e','u','l','S','i','o','s',0,\n0x71, 0xba, 0x00, 0x00, 0x0e, 0xe0, 'H','a','n','g','u','l','_','J','_','R','i','e','u','l','T','i','e','u','t',0,\n0xe3, 0x2c, 0x00, 0x00, 0x0e, 0xe1, 'H','a','n','g','u','l','_','J','_','R','i','e','u','l','P','h','i','e','u','f',0,\n0x70, 0xee, 0x00, 0x00, 0x0e, 0xe2, 'H','a','n','g','u','l','_','J','_','R','i','e','u','l','H','i','e','u','h',0,\n0xca, 0xe3, 0x00, 0x00, 0x0e, 0xe3, 'H','a','n','g','u','l','_','J','_','M','i','e','u','m',0,\n0xcb, 0x08, 0x00, 0x00, 0x0e, 0xe4, 'H','a','n','g','u','l','_','J','_','P','i','e','u','b',0,\n0xb6, 0x0d, 0x00, 0x00, 0x0e, 0xe5, 'H','a','n','g','u','l','_','J','_','P','i','e','u','b','S','i','o','s',0,\n0xe5, 0x7d, 0x00, 0x00, 0x0e, 0xe6, 'H','a','n','g','u','l','_','J','_','S','i','o','s',0,\n0xbc, 0x7d, 0x00, 0x00, 0x0e, 0xe7, 'H','a','n','g','u','l','_','J','_','S','s','a','n','g','S','i','o','s',0,\n0xca, 0xaf, 0x00, 0x00, 0x0e, 0xe8, 'H','a','n','g','u','l','_','J','_','I','e','u','n','g',0,\n0xca, 0xb0, 0x00, 0x00, 0x0e, 0xe9, 'H','a','n','g','u','l','_','J','_','J','i','e','u','j',0,\n0xca, 0x39, 0x00, 0x00, 0x0e, 0xea, 'H','a','n','g','u','l','_','J','_','C','i','e','u','c',0,\n0x95, 0xd7, 0x00, 0x00, 0x0e, 0xeb, 'H','a','n','g','u','l','_','J','_','K','h','i','e','u','q',0,\n0xcb, 0x5a, 0x00, 0x00, 0x0e, 0xec, 'H','a','n','g','u','l','_','J','_','T','i','e','u','t',0,\n0x96, 0x6c, 0x00, 0x00, 0x0e, 0xed, 'H','a','n','g','u','l','_','J','_','P','h','i','e','u','f',0,\n0xca, 0x8e, 0x00, 0x00, 0x0e, 0xee, 'H','a','n','g','u','l','_','J','_','H','i','e','u','h',0,\n0x98, 0xae, 0x00, 0x00, 0x0e, 0xef, 'H','a','n','g','u','l','_','R','i','e','u','l','Y','e','o','r','i','n','H','i','e','u','h',0,\n0x7f, 0x63, 0x00, 0x00, 0x0e, 0xf0, 'H','a','n','g','u','l','_','S','u','n','k','y','e','o','n','g','e','u','m','M','i','e','u','m',0,\n0x7f, 0x88, 0x00, 0x00, 0x0e, 0xf1, 'H','a','n','g','u','l','_','S','u','n','k','y','e','o','n','g','e','u','m','P','i','e','u','b',0,\n0xce, 0x0d, 0x00, 0x00, 0x0e, 0xf2, 'H','a','n','g','u','l','_','P','a','n','S','i','o','s',0,\n0xb1, 0xcf, 0x00, 0x00, 0x0e, 0xf3, 'H','a','n','g','u','l','_','K','k','o','g','j','i','D','a','l','r','i','n','I','e','u','n','g',0,\n0xff, 0x6c, 0x00, 0x00, 0x0e, 0xf4, 'H','a','n','g','u','l','_','S','u','n','k','y','e','o','n','g','e','u','m','P','h','i','e','u','f',0,\n0x20, 0xae, 0x00, 0x00, 0x0e, 0xf5, 'H','a','n','g','u','l','_','Y','e','o','r','i','n','H','i','e','u','h',0,\n0x72, 0x8f, 0x00, 0x00, 0x0e, 0xf6, 'H','a','n','g','u','l','_','A','r','a','e','A',0,\n0xe5, 0x63, 0x00, 0x00, 0x0e, 0xf7, 'H','a','n','g','u','l','_','A','r','a','e','A','E',0,\n0x2c, 0x0d, 0x00, 0x00, 0x0e, 0xf8, 'H','a','n','g','u','l','_','J','_','P','a','n','S','i','o','s',0,\n0xb1, 0xcf, 0x00, 0x00, 0x0e, 0xf9, 'H','a','n','g','u','l','_','J','_','K','k','o','g','j','i','D','a','l','r','i','n','I','e','u','n','g',0,\n0x00, 0xae, 0x00, 0x00, 0x0e, 0xfa, 'H','a','n','g','u','l','_','J','_','Y','e','o','r','i','n','H','i','e','u','h',0,\n0x6f, 0xe0, 0x00, 0x00, 0x0e, 0xff, 'K','o','r','e','a','n','_','W','o','n',0,\n0x8a, 0x25, 0x01, 0x00, 0x05, 0x87, 'A','r','m','e','n','i','a','n','_','l','i','g','a','t','u','r','e','_','e','w',0,\n0x63, 0xa6, 0x01, 0x00, 0x05, 0x89, 'A','r','m','e','n','i','a','n','_','f','u','l','l','_','s','t','o','p',0,\n0x36, 0x12, 0x01, 0x00, 0x05, 0x89, 'A','r','m','e','n','i','a','n','_','v','e','r','j','a','k','e','t',0,\n0x50, 0x2b, 0x01, 0x00, 0x05, 0x5d, 'A','r','m','e','n','i','a','n','_','s','e','p','a','r','a','t','i','o','n','_','m','a','r','k',0,\n0x79, 0x1e, 0x01, 0x00, 0x05, 0x5d, 'A','r','m','e','n','i','a','n','_','b','u','t',0,\n0xcc, 0xa8, 0x01, 0x00, 0x05, 0x8a, 'A','r','m','e','n','i','a','n','_','h','y','p','h','e','n',0,\n0x37, 0xb9, 0x01, 0x00, 0x05, 0x8a, 'A','r','m','e','n','i','a','n','_','y','e','n','t','a','m','n','a',0,\n0xcb, 0xd7, 0x01, 0x00, 0x05, 0x5c, 'A','r','m','e','n','i','a','n','_','e','x','c','l','a','m',0,\n0xca, 0x9d, 0x01, 0x00, 0x05, 0x5c, 'A','r','m','e','n','i','a','n','_','a','m','a','n','a','k',0,\n0xca, 0x0c, 0x01, 0x00, 0x05, 0x5b, 'A','r','m','e','n','i','a','n','_','a','c','c','e','n','t',0,\n0xcc, 0xd8, 0x01, 0x00, 0x05, 0x5b, 'A','r','m','e','n','i','a','n','_','s','h','e','s','h','t',0,\n0x37, 0x20, 0x01, 0x00, 0x05, 0x5e, 'A','r','m','e','n','i','a','n','_','q','u','e','s','t','i','o','n',0,\n0xcc, 0x91, 0x01, 0x00, 0x05, 0x5e, 'A','r','m','e','n','i','a','n','_','p','a','r','u','y','k',0,\n0x78, 0x30, 0x01, 0x00, 0x05, 0x31, 'A','r','m','e','n','i','a','n','_','A','Y','B',0,\n0x79, 0x10, 0x01, 0x00, 0x05, 0x61, 'A','r','m','e','n','i','a','n','_','a','y','b',0,\n0x78, 0x18, 0x01, 0x00, 0x05, 0x32, 'A','r','m','e','n','i','a','n','_','B','E','N',0,\n0x78, 0xf8, 0x01, 0x00, 0x05, 0x62, 'A','r','m','e','n','i','a','n','_','b','e','n',0,\n0x78, 0x33, 0x01, 0x00, 0x05, 0x33, 'A','r','m','e','n','i','a','n','_','G','I','M',0,\n0x79, 0x13, 0x01, 0x00, 0x05, 0x63, 'A','r','m','e','n','i','a','n','_','g','i','m',0,\n0xbb, 0xe5, 0x01, 0x00, 0x05, 0x34, 'A','r','m','e','n','i','a','n','_','D','A',0,\n0xbc, 0x45, 0x01, 0x00, 0x05, 0x64, 'A','r','m','e','n','i','a','n','_','d','a',0,\n0xf1, 0x1a, 0x01, 0x00, 0x05, 0x35, 'A','r','m','e','n','i','a','n','_','Y','E','C','H',0,\n0xf2, 0xfa, 0x01, 0x00, 0x05, 0x65, 'A','r','m','e','n','i','a','n','_','y','e','c','h',0,\n0xbc, 0x11, 0x01, 0x00, 0x05, 0x36, 'A','r','m','e','n','i','a','n','_','Z','A',0,\n0xbc, 0x71, 0x01, 0x00, 0x05, 0x66, 'A','r','m','e','n','i','a','n','_','z','a',0,\n0x5d, 0xd3, 0x01, 0x00, 0x05, 0x37, 'A','r','m','e','n','i','a','n','_','E',0,\n0x5d, 0xf3, 0x01, 0x00, 0x05, 0x67, 'A','r','m','e','n','i','a','n','_','e',0,\n0xbb, 0xf2, 0x01, 0x00, 0x05, 0x38, 'A','r','m','e','n','i','a','n','_','A','T',0,\n0xbc, 0x52, 0x01, 0x00, 0x05, 0x68, 'A','r','m','e','n','i','a','n','_','a','t',0,\n0xbc, 0x13, 0x01, 0x00, 0x05, 0x39, 'A','r','m','e','n','i','a','n','_','T','O',0,\n0xbc, 0x73, 0x01, 0x00, 0x05, 0x69, 'A','r','m','e','n','i','a','n','_','t','o',0,\n0x78, 0x75, 0x01, 0x00, 0x05, 0x3a, 'A','r','m','e','n','i','a','n','_','Z','H','E',0,\n0x79, 0x55, 0x01, 0x00, 0x05, 0x6a, 'A','r','m','e','n','i','a','n','_','z','h','e',0,\n0x78, 0x41, 0x01, 0x00, 0x05, 0x3b, 'A','r','m','e','n','i','a','n','_','I','N','I',0,\n0x79, 0x21, 0x01, 0x00, 0x05, 0x6b, 'A','r','m','e','n','i','a','n','_','i','n','i',0,\n0xf1, 0x2c, 0x01, 0x00, 0x05, 0x3c, 'A','r','m','e','n','i','a','n','_','L','Y','U','N',0,\n0xf3, 0x0c, 0x01, 0x00, 0x05, 0x6c, 'A','r','m','e','n','i','a','n','_','l','y','u','n',0,\n0x78, 0x39, 0x01, 0x00, 0x05, 0x3d, 'A','r','m','e','n','i','a','n','_','K','H','E',0,\n0x79, 0x19, 0x01, 0x00, 0x05, 0x6d, 'A','r','m','e','n','i','a','n','_','k','h','e',0,\n0x78, 0x6f, 0x01, 0x00, 0x05, 0x3e, 'A','r','m','e','n','i','a','n','_','T','S','A',0,\n0x79, 0x4f, 0x01, 0x00, 0x05, 0x6e, 'A','r','m','e','n','i','a','n','_','t','s','a',0,\n0x78, 0x3c, 0x01, 0x00, 0x05, 0x3f, 'A','r','m','e','n','i','a','n','_','K','E','N',0,\n0x79, 0x1c, 0x01, 0x00, 0x05, 0x6f, 'A','r','m','e','n','i','a','n','_','k','e','n',0,\n0xbb, 0xfb, 0x01, 0x00, 0x05, 0x40, 'A','r','m','e','n','i','a','n','_','H','O',0,\n0xbc, 0x5b, 0x01, 0x00, 0x05, 0x70, 'A','r','m','e','n','i','a','n','_','h','o',0,\n0x78, 0x3d, 0x01, 0x00, 0x05, 0x41, 'A','r','m','e','n','i','a','n','_','D','Z','A',0,\n0x79, 0x1d, 0x01, 0x00, 0x05, 0x71, 'A','r','m','e','n','i','a','n','_','d','z','a',0,\n0xf0, 0x9e, 0x01, 0x00, 0x05, 0x42, 'A','r','m','e','n','i','a','n','_','G','H','A','T',0,\n0xf2, 0x7e, 0x01, 0x00, 0x05, 0x72, 'A','r','m','e','n','i','a','n','_','g','h','a','t',0,\n0xf0, 0xf1, 0x01, 0x00, 0x05, 0x43, 'A','r','m','e','n','i','a','n','_','T','C','H','E',0,\n0xf2, 0xd1, 0x01, 0x00, 0x05, 0x73, 'A','r','m','e','n','i','a','n','_','t','c','h','e',0,\n0x78, 0x44, 0x01, 0x00, 0x05, 0x44, 'A','r','m','e','n','i','a','n','_','M','E','N',0,\n0x79, 0x24, 0x01, 0x00, 0x05, 0x74, 'A','r','m','e','n','i','a','n','_','m','e','n',0,\n0xbb, 0xf5, 0x01, 0x00, 0x05, 0x45, 'A','r','m','e','n','i','a','n','_','H','I',0,\n0xbc, 0x55, 0x01, 0x00, 0x05, 0x75, 'A','r','m','e','n','i','a','n','_','h','i',0,\n0xbc, 0x0d, 0x01, 0x00, 0x05, 0x46, 'A','r','m','e','n','i','a','n','_','N','U',0,\n0xbc, 0x6d, 0x01, 0x00, 0x05, 0x76, 'A','r','m','e','n','i','a','n','_','n','u',0,\n0x78, 0x55, 0x01, 0x00, 0x05, 0x47, 'A','r','m','e','n','i','a','n','_','S','H','A',0,\n0x79, 0x35, 0x01, 0x00, 0x05, 0x77, 'A','r','m','e','n','i','a','n','_','s','h','a',0,\n0xbc, 0x17, 0x01, 0x00, 0x05, 0x48, 'A','r','m','e','n','i','a','n','_','V','O',0,\n0xbc, 0x77, 0x01, 0x00, 0x05, 0x78, 'A','r','m','e','n','i','a','n','_','v','o',0,\n0x78, 0x15, 0x01, 0x00, 0x05, 0x49, 'A','r','m','e','n','i','a','n','_','C','H','A',0,\n0x78, 0xf5, 0x01, 0x00, 0x05, 0x79, 'A','r','m','e','n','i','a','n','_','c','h','a',0,\n0xbc, 0x01, 0x01, 0x00, 0x05, 0x4a, 'A','r','m','e','n','i','a','n','_','P','E',0,\n0xbc, 0x61, 0x01, 0x00, 0x05, 0x7a, 'A','r','m','e','n','i','a','n','_','p','e',0,\n0xbb, 0xf5, 0x01, 0x00, 0x05, 0x4b, 'A','r','m','e','n','i','a','n','_','J','E',0,\n0xbc, 0x55, 0x01, 0x00, 0x05, 0x7b, 'A','r','m','e','n','i','a','n','_','j','e',0,\n0xbc, 0x01, 0x01, 0x00, 0x05, 0x4c, 'A','r','m','e','n','i','a','n','_','R','A',0,\n0xbc, 0x61, 0x01, 0x00, 0x05, 0x7c, 'A','r','m','e','n','i','a','n','_','r','a',0,\n0xbc, 0x07, 0x01, 0x00, 0x05, 0x4d, 'A','r','m','e','n','i','a','n','_','S','E',0,\n0xbc, 0x67, 0x01, 0x00, 0x05, 0x7d, 'A','r','m','e','n','i','a','n','_','s','e',0,\n0x78, 0x70, 0x01, 0x00, 0x05, 0x4e, 'A','r','m','e','n','i','a','n','_','V','E','V',0,\n0x79, 0x50, 0x01, 0x00, 0x05, 0x7e, 'A','r','m','e','n','i','a','n','_','v','e','v',0,\n0xf1, 0x6c, 0x01, 0x00, 0x05, 0x4f, 'A','r','m','e','n','i','a','n','_','T','Y','U','N',0,\n0xf3, 0x4c, 0x01, 0x00, 0x05, 0x7f, 'A','r','m','e','n','i','a','n','_','t','y','u','n',0,\n0xbc, 0x05, 0x01, 0x00, 0x05, 0x50, 'A','r','m','e','n','i','a','n','_','R','E',0,\n0xbc, 0x65, 0x01, 0x00, 0x05, 0x80, 'A','r','m','e','n','i','a','n','_','r','e',0,\n0x78, 0x7d, 0x01, 0x00, 0x05, 0x51, 'A','r','m','e','n','i','a','n','_','T','S','O',0,\n0x79, 0x5d, 0x01, 0x00, 0x05, 0x81, 'A','r','m','e','n','i','a','n','_','t','s','o',0,\n0xf1, 0x7c, 0x01, 0x00, 0x05, 0x52, 'A','r','m','e','n','i','a','n','_','V','Y','U','N',0,\n0xf3, 0x5c, 0x01, 0x00, 0x05, 0x82, 'A','r','m','e','n','i','a','n','_','v','y','u','n',0,\n0xf1, 0x50, 0x01, 0x00, 0x05, 0x53, 'A','r','m','e','n','i','a','n','_','P','Y','U','R',0,\n0xf3, 0x30, 0x01, 0x00, 0x05, 0x83, 'A','r','m','e','n','i','a','n','_','p','y','u','r',0,\n0xbb, 0xf7, 0x01, 0x00, 0x05, 0x54, 'A','r','m','e','n','i','a','n','_','K','E',0,\n0xbc, 0x57, 0x01, 0x00, 0x05, 0x84, 'A','r','m','e','n','i','a','n','_','k','e',0,\n0x5d, 0xdd, 0x01, 0x00, 0x05, 0x55, 'A','r','m','e','n','i','a','n','_','O',0,\n0x5d, 0xfd, 0x01, 0x00, 0x05, 0x85, 'A','r','m','e','n','i','a','n','_','o',0,\n0xbb, 0xed, 0x01, 0x00, 0x05, 0x56, 'A','r','m','e','n','i','a','n','_','F','E',0,\n0xbc, 0x4d, 0x01, 0x00, 0x05, 0x86, 'A','r','m','e','n','i','a','n','_','f','e',0,\n0xbe, 0x4d, 0x01, 0x00, 0x05, 0x5a, 'A','r','m','e','n','i','a','n','_','a','p','o','s','t','r','o','p','h','e',0,\n0xc1, 0x0c, 0x01, 0x00, 0x10, 0xd0, 'G','e','o','r','g','i','a','n','_','a','n',0,\n0x82, 0x70, 0x01, 0x00, 0x10, 0xd1, 'G','e','o','r','g','i','a','n','_','b','a','n',0,\n0x82, 0x84, 0x01, 0x00, 0x10, 0xd2, 'G','e','o','r','g','i','a','n','_','g','a','n',0,\n0x82, 0x94, 0x01, 0x00, 0x10, 0xd3, 'G','e','o','r','g','i','a','n','_','d','o','n',0,\n0xc1, 0x14, 0x01, 0x00, 0x10, 0xd4, 'G','e','o','r','g','i','a','n','_','e','n',0,\n0x82, 0xd0, 0x01, 0x00, 0x10, 0xd5, 'G','e','o','r','g','i','a','n','_','v','i','n',0,\n0x82, 0xd8, 0x01, 0x00, 0x10, 0xd6, 'G','e','o','r','g','i','a','n','_','z','e','n',0,\n0x82, 0xb8, 0x01, 0x00, 0x10, 0xd7, 'G','e','o','r','g','i','a','n','_','t','a','n',0,\n0xc1, 0x1c, 0x01, 0x00, 0x10, 0xd8, 'G','e','o','r','g','i','a','n','_','i','n',0,\n0x82, 0x94, 0x01, 0x00, 0x10, 0xd9, 'G','e','o','r','g','i','a','n','_','k','a','n',0,\n0x82, 0x9d, 0x01, 0x00, 0x10, 0xda, 'G','e','o','r','g','i','a','n','_','l','a','s',0,\n0x82, 0x9c, 0x01, 0x00, 0x10, 0xdb, 'G','e','o','r','g','i','a','n','_','m','a','n',0,\n0x82, 0xa4, 0x01, 0x00, 0x10, 0xdc, 'G','e','o','r','g','i','a','n','_','n','a','r',0,\n0xc1, 0x28, 0x01, 0x00, 0x10, 0xdd, 'G','e','o','r','g','i','a','n','_','o','n',0,\n0x82, 0xac, 0x01, 0x00, 0x10, 0xde, 'G','e','o','r','g','i','a','n','_','p','a','r',0,\n0x06, 0x14, 0x01, 0x00, 0x10, 0xdf, 'G','e','o','r','g','i','a','n','_','z','h','a','r',0,\n0x82, 0xa7, 0x01, 0x00, 0x10, 0xe0, 'G','e','o','r','g','i','a','n','_','r','a','e',0,\n0x82, 0xb4, 0x01, 0x00, 0x10, 0xe1, 'G','e','o','r','g','i','a','n','_','s','a','n',0,\n0x82, 0xbc, 0x01, 0x00, 0x10, 0xe2, 'G','e','o','r','g','i','a','n','_','t','a','r',0,\n0xc1, 0x34, 0x01, 0x00, 0x10, 0xe3, 'G','e','o','r','g','i','a','n','_','u','n',0,\n0x05, 0xc4, 0x01, 0x00, 0x10, 0xe4, 'G','e','o','r','g','i','a','n','_','p','h','a','r',0,\n0x05, 0x9c, 0x01, 0x00, 0x10, 0xe5, 'G','e','o','r','g','i','a','n','_','k','h','a','r',0,\n0x05, 0x78, 0x01, 0x00, 0x10, 0xe6, 'G','e','o','r','g','i','a','n','_','g','h','a','n',0,\n0x82, 0xb0, 0x01, 0x00, 0x10, 0xe7, 'G','e','o','r','g','i','a','n','_','q','a','r',0,\n0x05, 0xe8, 0x01, 0x00, 0x10, 0xe8, 'G','e','o','r','g','i','a','n','_','s','h','i','n',0,\n0x05, 0x68, 0x01, 0x00, 0x10, 0xe9, 'G','e','o','r','g','i','a','n','_','c','h','i','n',0,\n0x82, 0x74, 0x01, 0x00, 0x10, 0xea, 'G','e','o','r','g','i','a','n','_','c','a','n',0,\n0x82, 0x9e, 0x01, 0x00, 0x10, 0xeb, 'G','e','o','r','g','i','a','n','_','j','i','l',0,\n0x82, 0x82, 0x01, 0x00, 0x10, 0xec, 'G','e','o','r','g','i','a','n','_','c','i','l',0,\n0x05, 0x5c, 0x01, 0x00, 0x10, 0xed, 'G','e','o','r','g','i','a','n','_','c','h','a','r',0,\n0x82, 0xc8, 0x01, 0x00, 0x10, 0xee, 'G','e','o','r','g','i','a','n','_','x','a','n',0,\n0x05, 0x90, 0x01, 0x00, 0x10, 0xef, 'G','e','o','r','g','i','a','n','_','j','h','a','n',0,\n0x82, 0x7f, 0x01, 0x00, 0x10, 0xf0, 'G','e','o','r','g','i','a','n','_','h','a','e',0,\n0xc1, 0x11, 0x01, 0x00, 0x10, 0xf1, 'G','e','o','r','g','i','a','n','_','h','e',0,\n0x82, 0x8f, 0x01, 0x00, 0x10, 0xf2, 'G','e','o','r','g','i','a','n','_','h','i','e',0,\n0xc1, 0x2f, 0x01, 0x00, 0x10, 0xf3, 'G','e','o','r','g','i','a','n','_','w','e',0,\n0x82, 0x8c, 0x01, 0x00, 0x10, 0xf4, 'G','e','o','r','g','i','a','n','_','h','a','r',0,\n0x82, 0x9b, 0x01, 0x00, 0x10, 0xf5, 'G','e','o','r','g','i','a','n','_','h','o','e',0,\n0xc1, 0x11, 0x01, 0x00, 0x10, 0xf6, 'G','e','o','r','g','i','a','n','_','f','i',0,\n0xbc, 0x4a, 0x01, 0x00, 0x1e, 0x8a, 'X','a','b','o','v','e','d','o','t',0,\n0x15, 0xb5, 0x01, 0x00, 0x01, 0x2c, 'I','b','r','e','v','e',0,\n0x32, 0xa7, 0x01, 0x00, 0x01, 0xb5, 'Z','s','t','r','o','k','e',0,\n0x15, 0x2c, 0x01, 0x00, 0x01, 0xe6, 'G','c','a','r','o','n',0,\n0x16, 0x2c, 0x01, 0x00, 0x01, 0xd1, 'O','c','a','r','o','n',0,\n0x2c, 0x96, 0x01, 0x00, 0x01, 0x9f, 'O','b','a','r','r','e','d',0,\n0xdc, 0x4a, 0x01, 0x00, 0x1e, 0x8b, 'x','a','b','o','v','e','d','o','t',0,\n0x19, 0xb5, 0x01, 0x00, 0x01, 0x2d, 'i','b','r','e','v','e',0,\n0x3a, 0xa7, 0x01, 0x00, 0x01, 0xb6, 'z','s','t','r','o','k','e',0,\n0x19, 0x2c, 0x01, 0x00, 0x01, 0xe7, 'g','c','a','r','o','n',0,\n0x1a, 0x2c, 0x01, 0x00, 0x01, 0xd2, 'o','c','a','r','o','n',0,\n0x34, 0x96, 0x01, 0x00, 0x02, 0x75, 'o','b','a','r','r','e','d',0,\n0x09, 0x57, 0x01, 0x00, 0x01, 0x8f, 'S','C','H','W','A',0,\n0x0d, 0x37, 0x01, 0x00, 0x02, 0x59, 's','c','h','w','a',0,\n0x02, 0x10, 0x01, 0x00, 0x01, 0xb7, 'E','Z','H',0,\n0x02, 0xf0, 0x01, 0x00, 0x02, 0x92, 'e','z','h',0,\n0xb1, 0x4a, 0x01, 0x00, 0x1e, 0x36, 'L','b','e','l','o','w','d','o','t',0,\n0xd1, 0x4a, 0x01, 0x00, 0x1e, 0x37, 'l','b','e','l','o','w','d','o','t',0,\n0xa6, 0x4a, 0x01, 0x00, 0x1e, 0xa0, 'A','b','e','l','o','w','d','o','t',0,\n0xc6, 0x4a, 0x01, 0x00, 0x1e, 0xa1, 'a','b','e','l','o','w','d','o','t',0,\n0x0a, 0x55, 0x01, 0x00, 0x1e, 0xa2, 'A','h','o','o','k',0,\n0x0c, 0x55, 0x01, 0x00, 0x1e, 0xa3, 'a','h','o','o','k',0,\n0x16, 0x89, 0x01, 0x00, 0x1e, 0xa4, 'A','c','i','r','c','u','m','f','l','e','x','a','c','u','t','e',0,\n0x16, 0x89, 0x01, 0x00, 0x1e, 0xa5, 'a','c','i','r','c','u','m','f','l','e','x','a','c','u','t','e',0,\n0x17, 0x15, 0x01, 0x00, 0x1e, 0xa6, 'A','c','i','r','c','u','m','f','l','e','x','g','r','a','v','e',0,\n0x17, 0x15, 0x01, 0x00, 0x1e, 0xa7, 'a','c','i','r','c','u','m','f','l','e','x','g','r','a','v','e',0,\n0x0b, 0x65, 0x01, 0x00, 0x1e, 0xa8, 'A','c','i','r','c','u','m','f','l','e','x','h','o','o','k',0,\n0x0b, 0x65, 0x01, 0x00, 0x1e, 0xa9, 'a','c','i','r','c','u','m','f','l','e','x','h','o','o','k',0,\n0x17, 0xa5, 0x01, 0x00, 0x1e, 0xaa, 'A','c','i','r','c','u','m','f','l','e','x','t','i','l','d','e',0,\n0x17, 0xa5, 0x01, 0x00, 0x1e, 0xab, 'a','c','i','r','c','u','m','f','l','e','x','t','i','l','d','e',0,\n0xb7, 0x4a, 0x01, 0x00, 0x1e, 0xac, 'A','c','i','r','c','u','m','f','l','e','x','b','e','l','o','w','d','o','t',0,\n0xb7, 0x4a, 0x01, 0x00, 0x1e, 0xad, 'a','c','i','r','c','u','m','f','l','e','x','b','e','l','o','w','d','o','t',0,\n0xa2, 0xe9, 0x01, 0x00, 0x1e, 0xae, 'A','b','r','e','v','e','a','c','u','t','e',0,\n0x22, 0xe9, 0x01, 0x00, 0x1e, 0xaf, 'a','b','r','e','v','e','a','c','u','t','e',0,\n0xa3, 0x75, 0x01, 0x00, 0x1e, 0xb0, 'A','b','r','e','v','e','g','r','a','v','e',0,\n0x23, 0x75, 0x01, 0x00, 0x1e, 0xb1, 'a','b','r','e','v','e','g','r','a','v','e',0,\n0x51, 0x95, 0x01, 0x00, 0x1e, 0xb2, 'A','b','r','e','v','e','h','o','o','k',0,\n0x91, 0x95, 0x01, 0x00, 0x1e, 0xb3, 'a','b','r','e','v','e','h','o','o','k',0,\n0xa4, 0x05, 0x01, 0x00, 0x1e, 0xb4, 'A','b','r','e','v','e','t','i','l','d','e',0,\n0x24, 0x05, 0x01, 0x00, 0x1e, 0xb5, 'a','b','r','e','v','e','t','i','l','d','e',0,\n0x1a, 0x4a, 0x01, 0x00, 0x1e, 0xb6, 'A','b','r','e','v','e','b','e','l','o','w','d','o','t',0,\n0x1a, 0x4a, 0x01, 0x00, 0x1e, 0xb7, 'a','b','r','e','v','e','b','e','l','o','w','d','o','t',0,\n0xaa, 0x4a, 0x01, 0x00, 0x1e, 0xb8, 'E','b','e','l','o','w','d','o','t',0,\n0xca, 0x4a, 0x01, 0x00, 0x1e, 0xb9, 'e','b','e','l','o','w','d','o','t',0,\n0x0a, 0x95, 0x01, 0x00, 0x1e, 0xba, 'E','h','o','o','k',0,\n0x0c, 0x95, 0x01, 0x00, 0x1e, 0xbb, 'e','h','o','o','k',0,\n0x16, 0x05, 0x01, 0x00, 0x1e, 0xbc, 'E','t','i','l','d','e',0,\n0x1a, 0x05, 0x01, 0x00, 0x1e, 0xbd, 'e','t','i','l','d','e',0,\n0x16, 0x89, 0x01, 0x00, 0x1e, 0xbe, 'E','c','i','r','c','u','m','f','l','e','x','a','c','u','t','e',0,\n0x16, 0x89, 0x01, 0x00, 0x1e, 0xbf, 'e','c','i','r','c','u','m','f','l','e','x','a','c','u','t','e',0,\n0x17, 0x15, 0x01, 0x00, 0x1e, 0xc0, 'E','c','i','r','c','u','m','f','l','e','x','g','r','a','v','e',0,\n0x17, 0x15, 0x01, 0x00, 0x1e, 0xc1, 'e','c','i','r','c','u','m','f','l','e','x','g','r','a','v','e',0,\n0x0b, 0x65, 0x01, 0x00, 0x1e, 0xc2, 'E','c','i','r','c','u','m','f','l','e','x','h','o','o','k',0,\n0x0b, 0x65, 0x01, 0x00, 0x1e, 0xc3, 'e','c','i','r','c','u','m','f','l','e','x','h','o','o','k',0,\n0x17, 0xa5, 0x01, 0x00, 0x1e, 0xc4, 'E','c','i','r','c','u','m','f','l','e','x','t','i','l','d','e',0,\n0x17, 0xa5, 0x01, 0x00, 0x1e, 0xc5, 'e','c','i','r','c','u','m','f','l','e','x','t','i','l','d','e',0,\n0xb7, 0x4a, 0x01, 0x00, 0x1e, 0xc6, 'E','c','i','r','c','u','m','f','l','e','x','b','e','l','o','w','d','o','t',0,\n0xb7, 0x4a, 0x01, 0x00, 0x1e, 0xc7, 'e','c','i','r','c','u','m','f','l','e','x','b','e','l','o','w','d','o','t',0,\n0x0a, 0xd5, 0x01, 0x00, 0x1e, 0xc8, 'I','h','o','o','k',0,\n0x0c, 0xd5, 0x01, 0x00, 0x1e, 0xc9, 'i','h','o','o','k',0,\n0xae, 0x4a, 0x01, 0x00, 0x1e, 0xca, 'I','b','e','l','o','w','d','o','t',0,\n0xce, 0x4a, 0x01, 0x00, 0x1e, 0xcb, 'i','b','e','l','o','w','d','o','t',0,\n0xb4, 0x4a, 0x01, 0x00, 0x1e, 0xcc, 'O','b','e','l','o','w','d','o','t',0,\n0xd4, 0x4a, 0x01, 0x00, 0x1e, 0xcd, 'o','b','e','l','o','w','d','o','t',0,\n0x0b, 0x35, 0x01, 0x00, 0x1e, 0xce, 'O','h','o','o','k',0,\n0x0d, 0x35, 0x01, 0x00, 0x1e, 0xcf, 'o','h','o','o','k',0,\n0x16, 0x89, 0x01, 0x00, 0x1e, 0xd0, 'O','c','i','r','c','u','m','f','l','e','x','a','c','u','t','e',0,\n0x16, 0x89, 0x01, 0x00, 0x1e, 0xd1, 'o','c','i','r','c','u','m','f','l','e','x','a','c','u','t','e',0,\n0x17, 0x15, 0x01, 0x00, 0x1e, 0xd2, 'O','c','i','r','c','u','m','f','l','e','x','g','r','a','v','e',0,\n0x17, 0x15, 0x01, 0x00, 0x1e, 0xd3, 'o','c','i','r','c','u','m','f','l','e','x','g','r','a','v','e',0,\n0x8b, 0x65, 0x01, 0x00, 0x1e, 0xd4, 'O','c','i','r','c','u','m','f','l','e','x','h','o','o','k',0,\n0x8b, 0x65, 0x01, 0x00, 0x1e, 0xd5, 'o','c','i','r','c','u','m','f','l','e','x','h','o','o','k',0,\n0x17, 0xa5, 0x01, 0x00, 0x1e, 0xd6, 'O','c','i','r','c','u','m','f','l','e','x','t','i','l','d','e',0,\n0x17, 0xa5, 0x01, 0x00, 0x1e, 0xd7, 'o','c','i','r','c','u','m','f','l','e','x','t','i','l','d','e',0,\n0xb7, 0x4a, 0x01, 0x00, 0x1e, 0xd8, 'O','c','i','r','c','u','m','f','l','e','x','b','e','l','o','w','d','o','t',0,\n0xb7, 0x4a, 0x01, 0x00, 0x1e, 0xd9, 'o','c','i','r','c','u','m','f','l','e','x','b','e','l','o','w','d','o','t',0,\n0x74, 0x09, 0x01, 0x00, 0x1e, 0xda, 'O','h','o','r','n','a','c','u','t','e',0,\n0xb4, 0x09, 0x01, 0x00, 0x1e, 0xdb, 'o','h','o','r','n','a','c','u','t','e',0,\n0x74, 0x95, 0x01, 0x00, 0x1e, 0xdc, 'O','h','o','r','n','g','r','a','v','e',0,\n0xb4, 0x95, 0x01, 0x00, 0x1e, 0xdd, 'o','h','o','r','n','g','r','a','v','e',0,\n0xba, 0x25, 0x01, 0x00, 0x1e, 0xde, 'O','h','o','r','n','h','o','o','k',0,\n0xda, 0x25, 0x01, 0x00, 0x1e, 0xdf, 'o','h','o','r','n','h','o','o','k',0,\n0x75, 0x25, 0x01, 0x00, 0x1e, 0xe0, 'O','h','o','r','n','t','i','l','d','e',0,\n0xb5, 0x25, 0x01, 0x00, 0x1e, 0xe1, 'o','h','o','r','n','t','i','l','d','e',0,\n0xa3, 0x4a, 0x01, 0x00, 0x1e, 0xe2, 'O','h','o','r','n','b','e','l','o','w','d','o','t',0,\n0xa3, 0x4a, 0x01, 0x00, 0x1e, 0xe3, 'o','h','o','r','n','b','e','l','o','w','d','o','t',0,\n0xba, 0x4a, 0x01, 0x00, 0x1e, 0xe4, 'U','b','e','l','o','w','d','o','t',0,\n0xda, 0x4a, 0x01, 0x00, 0x1e, 0xe5, 'u','b','e','l','o','w','d','o','t',0,\n0x0b, 0x95, 0x01, 0x00, 0x1e, 0xe6, 'U','h','o','o','k',0,\n0x0d, 0x95, 0x01, 0x00, 0x1e, 0xe7, 'u','h','o','o','k',0,\n0x80, 0x09, 0x01, 0x00, 0x1e, 0xe8, 'U','h','o','r','n','a','c','u','t','e',0,\n0xc0, 0x09, 0x01, 0x00, 0x1e, 0xe9, 'u','h','o','r','n','a','c','u','t','e',0,\n0x80, 0x95, 0x01, 0x00, 0x1e, 0xea, 'U','h','o','r','n','g','r','a','v','e',0,\n0xc0, 0x95, 0x01, 0x00, 0x1e, 0xeb, 'u','h','o','r','n','g','r','a','v','e',0,\n0xc0, 0x25, 0x01, 0x00, 0x1e, 0xec, 'U','h','o','r','n','h','o','o','k',0,\n0xe0, 0x25, 0x01, 0x00, 0x1e, 0xed, 'u','h','o','r','n','h','o','o','k',0,\n0x81, 0x25, 0x01, 0x00, 0x1e, 0xee, 'U','h','o','r','n','t','i','l','d','e',0,\n0xc1, 0x25, 0x01, 0x00, 0x1e, 0xef, 'u','h','o','r','n','t','i','l','d','e',0,\n0x03, 0x4a, 0x01, 0x00, 0x1e, 0xf0, 'U','h','o','r','n','b','e','l','o','w','d','o','t',0,\n0x03, 0x4a, 0x01, 0x00, 0x1e, 0xf1, 'u','h','o','r','n','b','e','l','o','w','d','o','t',0,\n0xbe, 0x4a, 0x01, 0x00, 0x1e, 0xf4, 'Y','b','e','l','o','w','d','o','t',0,\n0xde, 0x4a, 0x01, 0x00, 0x1e, 0xf5, 'y','b','e','l','o','w','d','o','t',0,\n0x0b, 0xd5, 0x01, 0x00, 0x1e, 0xf6, 'Y','h','o','o','k',0,\n0x0d, 0xd5, 0x01, 0x00, 0x1e, 0xf7, 'y','h','o','o','k',0,\n0x18, 0x85, 0x01, 0x00, 0x1e, 0xf8, 'Y','t','i','l','d','e',0,\n0x1c, 0x85, 0x01, 0x00, 0x1e, 0xf9, 'y','t','i','l','d','e',0,\n0x0b, 0x3e, 0x01, 0x00, 0x01, 0xa0, 'O','h','o','r','n',0,\n0x0d, 0x3e, 0x01, 0x00, 0x01, 0xa1, 'o','h','o','r','n',0,\n0x0b, 0x9e, 0x01, 0x00, 0x01, 0xaf, 'U','h','o','r','n',0,\n0x0d, 0x9e, 0x01, 0x00, 0x01, 0xb0, 'u','h','o','r','n',0,\n0xd3, 0x05, 0x01, 0x00, 0x03, 0x03, 'c','o','m','b','i','n','i','n','g','_','t','i','l','d','e',0,\n0xd2, 0x75, 0x01, 0x00, 0x03, 0x00, 'c','o','m','b','i','n','i','n','g','_','g','r','a','v','e',0,\n0xd1, 0xe9, 0x01, 0x00, 0x03, 0x01, 'c','o','m','b','i','n','i','n','g','_','a','c','u','t','e',0,\n0xe9, 0x15, 0x01, 0x00, 0x03, 0x09, 'c','o','m','b','i','n','i','n','g','_','h','o','o','k',0,\n0x92, 0x4a, 0x01, 0x00, 0x03, 0x23, 'c','o','m','b','i','n','i','n','g','_','b','e','l','o','w','d','o','t',0,\n0x2a, 0x68, 0x01, 0x00, 0x20, 0xa0, 'E','c','u','S','i','g','n',0,\n0xaf, 0xb8, 0x01, 0x00, 0x20, 0xa1, 'C','o','l','o','n','S','i','g','n',0,\n0xab, 0x68, 0x01, 0x00, 0x20, 0xa2, 'C','r','u','z','e','i','r','o','S','i','g','n',0,\n0x3c, 0xa8, 0x01, 0x00, 0x20, 0xa3, 'F','F','r','a','n','c','S','i','g','n',0,\n0x5a, 0x08, 0x01, 0x00, 0x20, 0xa4, 'L','i','r','a','S','i','g','n',0,\n0x5a, 0x78, 0x01, 0x00, 0x20, 0xa5, 'M','i','l','l','S','i','g','n',0,\n0xb2, 0x88, 0x01, 0x00, 0x20, 0xa6, 'N','a','i','r','a','S','i','g','n',0,\n0x71, 0xc8, 0x01, 0x00, 0x20, 0xa7, 'P','e','s','e','t','a','S','i','g','n',0,\n0xc0, 0xe8, 0x01, 0x00, 0x20, 0xa8, 'R','u','p','e','e','S','i','g','n',0,\n0x2f, 0xf8, 0x01, 0x00, 0x20, 0xa9, 'W','o','n','S','i','g','n',0,\n0x59, 0x98, 0x01, 0x00, 0x20, 0xaa, 'N','e','w','S','h','e','q','e','l','S','i','g','n',0,\n0x57, 0x68, 0x01, 0x00, 0x20, 0xab, 'D','o','n','g','S','i','g','n',0,\n0x5a, 0x68, 0x00, 0x00, 0x20, 0xac, 'E','u','r','o','S','i','g','n',0,\n0x28, 0x94, 0x01, 0x00, 0x20, 0x70, 'z','e','r','o','s','u','p','e','r','i','o','r',0,\n0xb9, 0x94, 0x01, 0x00, 0x20, 0x74, 'f','o','u','r','s','u','p','e','r','i','o','r',0,\n0x96, 0x94, 0x01, 0x00, 0x20, 0x75, 'f','i','v','e','s','u','p','e','r','i','o','r',0,\n0x87, 0x94, 0x01, 0x00, 0x20, 0x76, 's','i','x','s','u','p','e','r','i','o','r',0,\n0xd9, 0x94, 0x01, 0x00, 0x20, 0x77, 's','e','v','e','n','s','u','p','e','r','i','o','r',0,\n0xe9, 0x94, 0x01, 0x00, 0x20, 0x78, 'e','i','g','h','t','s','u','p','e','r','i','o','r',0,\n0xc6, 0x94, 0x01, 0x00, 0x20, 0x79, 'n','i','n','e','s','u','p','e','r','i','o','r',0,\n0x4f, 0x18, 0x01, 0x00, 0x20, 0x80, 'z','e','r','o','s','u','b','s','c','r','i','p','t',0,\n0xdb, 0x18, 0x01, 0x00, 0x20, 0x81, 'o','n','e','s','u','b','s','c','r','i','p','t',0,\n0x3b, 0x18, 0x01, 0x00, 0x20, 0x82, 't','w','o','s','u','b','s','c','r','i','p','t',0,\n0xcf, 0x18, 0x01, 0x00, 0x20, 0x83, 't','h','r','e','e','s','u','b','s','c','r','i','p','t',0,\n0x71, 0x18, 0x01, 0x00, 0x20, 0x84, 'f','o','u','r','s','u','b','s','c','r','i','p','t',0,\n0x2b, 0x18, 0x01, 0x00, 0x20, 0x85, 'f','i','v','e','s','u','b','s','c','r','i','p','t',0,\n0x0d, 0x18, 0x01, 0x00, 0x20, 0x86, 's','i','x','s','u','b','s','c','r','i','p','t',0,\n0xb1, 0x18, 0x01, 0x00, 0x20, 0x87, 's','e','v','e','n','s','u','b','s','c','r','i','p','t',0,\n0xd1, 0x18, 0x01, 0x00, 0x20, 0x88, 'e','i','g','h','t','s','u','b','s','c','r','i','p','t',0,\n0x8b, 0x18, 0x01, 0x00, 0x20, 0x89, 'n','i','n','e','s','u','b','s','c','r','i','p','t',0,\n0x1e, 0xf2, 0x01, 0x00, 0x22, 0x02, 'p','a','r','t','d','i','f','f','e','r','e','n','t','i','a','l',0,\n0x69, 0xd2, 0x01, 0x00, 0x22, 0x05, 'e','m','p','t','y','s','e','t',0,\n0xce, 0xb4, 0x01, 0x00, 0x22, 0x08, 'e','l','e','m','e','n','t','o','f',0,\n0xe2, 0xb4, 0x01, 0x00, 0x22, 0x09, 'n','o','t','e','l','e','m','e','n','t','o','f',0,\n0xa2, 0x21, 0x01, 0x00, 0x22, 0x0b, 'c','o','n','t','a','i','n','s','a','s',0,\n0xc4, 0xee, 0x01, 0x00, 0x22, 0x1a, 's','q','u','a','r','e','r','o','o','t',0,\n0x67, 0xee, 0x01, 0x00, 0x22, 0x1b, 'c','u','b','e','r','o','o','t',0,\n0xad, 0x9e, 0x01, 0x00, 0x22, 0x1c, 'f','o','u','r','t','h','r','o','o','t',0,\n0xce, 0xfe, 0x01, 0x00, 0x22, 0x2c, 'd','i','n','t','e','g','r','a','l',0,\n0xde, 0xfe, 0x01, 0x00, 0x22, 0x2d, 't','i','n','t','e','g','r','a','l',0,\n0x31, 0x77, 0x01, 0x00, 0x22, 0x35, 'b','e','c','a','u','s','e',0,\n0x68, 0x33, 0x01, 0x00, 0x22, 0x48, 'a','p','p','r','o','x','e','q',0,\n0x72, 0x33, 0x01, 0x00, 0x22, 0x47, 'n','o','t','a','p','p','r','o','x','e','q',0,\n0xe3, 0x42, 0x01, 0x00, 0x22, 0x62, 'n','o','t','i','d','e','n','t','i','c','a','l',0,\n0x71, 0x73, 0x01, 0x00, 0x22, 0x63, 's','t','r','i','c','t','e','q',0,\n0xd9, 0x97, 0x00, 0x00, 0xff, 0xf1, 'b','r','a','i','l','l','e','_','d','o','t','_','1',0,\n0xd9, 0x98, 0x00, 0x00, 0xff, 0xf2, 'b','r','a','i','l','l','e','_','d','o','t','_','2',0,\n0xd9, 0x99, 0x00, 0x00, 0xff, 0xf3, 'b','r','a','i','l','l','e','_','d','o','t','_','3',0,\n0xd9, 0x9a, 0x00, 0x00, 0xff, 0xf4, 'b','r','a','i','l','l','e','_','d','o','t','_','4',0,\n0xd9, 0x9b, 0x00, 0x00, 0xff, 0xf5, 'b','r','a','i','l','l','e','_','d','o','t','_','5',0,\n0xd9, 0x9c, 0x00, 0x00, 0xff, 0xf6, 'b','r','a','i','l','l','e','_','d','o','t','_','6',0,\n0xd9, 0x9d, 0x00, 0x00, 0xff, 0xf7, 'b','r','a','i','l','l','e','_','d','o','t','_','7',0,\n0xd9, 0x9e, 0x00, 0x00, 0xff, 0xf8, 'b','r','a','i','l','l','e','_','d','o','t','_','8',0,\n0xd9, 0x9f, 0x00, 0x00, 0xff, 0xf9, 'b','r','a','i','l','l','e','_','d','o','t','_','9',0,\n0xb3, 0x5e, 0x00, 0x00, 0xff, 0xfa, 'b','r','a','i','l','l','e','_','d','o','t','_','1','0',0,\n0xd9, 0x6b, 0x01, 0x00, 0x28, 0x00, 'b','r','a','i','l','l','e','_','b','l','a','n','k',0,\n0xb4, 0x0b, 0x01, 0x00, 0x28, 0x01, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1',0,\n0xb4, 0x0c, 0x01, 0x00, 0x28, 0x02, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2',0,\n0x68, 0x48, 0x01, 0x00, 0x28, 0x03, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2',0,\n0xb4, 0x0d, 0x01, 0x00, 0x28, 0x04, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3',0,\n0x68, 0x49, 0x01, 0x00, 0x28, 0x05, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3',0,\n0x68, 0x4b, 0x01, 0x00, 0x28, 0x06, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3',0,\n0xd0, 0xc3, 0x01, 0x00, 0x28, 0x07, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3',0,\n0xb4, 0x0e, 0x01, 0x00, 0x28, 0x08, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4',0,\n0x68, 0x4a, 0x01, 0x00, 0x28, 0x09, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4',0,\n0x68, 0x4c, 0x01, 0x00, 0x28, 0x0a, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4',0,\n0xd0, 0xc4, 0x01, 0x00, 0x28, 0x0b, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4',0,\n0x68, 0x4e, 0x01, 0x00, 0x28, 0x0c, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4',0,\n0xd0, 0xc6, 0x01, 0x00, 0x28, 0x0d, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4',0,\n0xd0, 0xca, 0x01, 0x00, 0x28, 0x0e, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4',0,\n0xa1, 0xba, 0x01, 0x00, 0x28, 0x0f, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4',0,\n0xb4, 0x0f, 0x01, 0x00, 0x28, 0x10, 'b','r','a','i','l','l','e','_','d','o','t','s','_','5',0,\n0x68, 0x4b, 0x01, 0x00, 0x28, 0x11, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','5',0,\n0x68, 0x4d, 0x01, 0x00, 0x28, 0x12, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','5',0,\n0xd0, 0xc5, 0x01, 0x00, 0x28, 0x13, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','5',0,\n0x68, 0x4f, 0x01, 0x00, 0x28, 0x14, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','5',0,\n0xd0, 0xc7, 0x01, 0x00, 0x28, 0x15, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','5',0,\n0xd0, 0xcb, 0x01, 0x00, 0x28, 0x16, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','5',0,\n0xa1, 0xbb, 0x01, 0x00, 0x28, 0x17, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','5',0,\n0x68, 0x51, 0x01, 0x00, 0x28, 0x18, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','5',0,\n0xd0, 0xc9, 0x01, 0x00, 0x28, 0x19, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','5',0,\n0xd0, 0xcd, 0x01, 0x00, 0x28, 0x1a, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','5',0,\n0xa1, 0xbd, 0x01, 0x00, 0x28, 0x1b, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','5',0,\n0xd0, 0xd1, 0x01, 0x00, 0x28, 0x1c, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','5',0,\n0xa1, 0xc1, 0x01, 0x00, 0x28, 0x1d, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','5',0,\n0xa1, 0xc9, 0x01, 0x00, 0x28, 0x1e, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','5',0,\n0x43, 0xa9, 0x01, 0x00, 0x28, 0x1f, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','5',0,\n0xb4, 0x10, 0x01, 0x00, 0x28, 0x20, 'b','r','a','i','l','l','e','_','d','o','t','s','_','6',0,\n0x68, 0x4c, 0x01, 0x00, 0x28, 0x21, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','6',0,\n0x68, 0x4e, 0x01, 0x00, 0x28, 0x22, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','6',0,\n0xd0, 0xc6, 0x01, 0x00, 0x28, 0x23, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','6',0,\n0x68, 0x50, 0x01, 0x00, 0x28, 0x24, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','6',0,\n0xd0, 0xc8, 0x01, 0x00, 0x28, 0x25, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','6',0,\n0xd0, 0xcc, 0x01, 0x00, 0x28, 0x26, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','6',0,\n0xa1, 0xbc, 0x01, 0x00, 0x28, 0x27, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','6',0,\n0x68, 0x52, 0x01, 0x00, 0x28, 0x28, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','6',0,\n0xd0, 0xca, 0x01, 0x00, 0x28, 0x29, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','6',0,\n0xd0, 0xce, 0x01, 0x00, 0x28, 0x2a, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','6',0,\n0xa1, 0xbe, 0x01, 0x00, 0x28, 0x2b, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','6',0,\n0xd0, 0xd2, 0x01, 0x00, 0x28, 0x2c, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','6',0,\n0xa1, 0xc2, 0x01, 0x00, 0x28, 0x2d, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','6',0,\n0xa1, 0xca, 0x01, 0x00, 0x28, 0x2e, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','6',0,\n0x43, 0xaa, 0x01, 0x00, 0x28, 0x2f, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','6',0,\n0x68, 0x54, 0x01, 0x00, 0x28, 0x30, 'b','r','a','i','l','l','e','_','d','o','t','s','_','5','6',0,\n0xd0, 0xcc, 0x01, 0x00, 0x28, 0x31, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','5','6',0,\n0xd0, 0xd0, 0x01, 0x00, 0x28, 0x32, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','5','6',0,\n0xa1, 0xc0, 0x01, 0x00, 0x28, 0x33, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','5','6',0,\n0xd0, 0xd4, 0x01, 0x00, 0x28, 0x34, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','5','6',0,\n0xa1, 0xc4, 0x01, 0x00, 0x28, 0x35, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','5','6',0,\n0xa1, 0xcc, 0x01, 0x00, 0x28, 0x36, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','5','6',0,\n0x43, 0xac, 0x01, 0x00, 0x28, 0x37, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','5','6',0,\n0xd0, 0xd8, 0x01, 0x00, 0x28, 0x38, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','5','6',0,\n0xa1, 0xc8, 0x01, 0x00, 0x28, 0x39, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','5','6',0,\n0xa1, 0xd0, 0x01, 0x00, 0x28, 0x3a, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','5','6',0,\n0x43, 0xb0, 0x01, 0x00, 0x28, 0x3b, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','5','6',0,\n0xa1, 0xd8, 0x01, 0x00, 0x28, 0x3c, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','5','6',0,\n0x43, 0xb8, 0x01, 0x00, 0x28, 0x3d, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','5','6',0,\n0x43, 0xc8, 0x01, 0x00, 0x28, 0x3e, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','5','6',0,\n0x87, 0x88, 0x01, 0x00, 0x28, 0x3f, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','5','6',0,\n0xb4, 0x11, 0x01, 0x00, 0x28, 0x40, 'b','r','a','i','l','l','e','_','d','o','t','s','_','7',0,\n0x68, 0x4d, 0x01, 0x00, 0x28, 0x41, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','7',0,\n0x68, 0x4f, 0x01, 0x00, 0x28, 0x42, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','7',0,\n0xd0, 0xc7, 0x01, 0x00, 0x28, 0x43, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','7',0,\n0x68, 0x51, 0x01, 0x00, 0x28, 0x44, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','7',0,\n0xd0, 0xc9, 0x01, 0x00, 0x28, 0x45, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','7',0,\n0xd0, 0xcd, 0x01, 0x00, 0x28, 0x46, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','7',0,\n0xa1, 0xbd, 0x01, 0x00, 0x28, 0x47, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','7',0,\n0x68, 0x53, 0x01, 0x00, 0x28, 0x48, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','7',0,\n0xd0, 0xcb, 0x01, 0x00, 0x28, 0x49, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','7',0,\n0xd0, 0xcf, 0x01, 0x00, 0x28, 0x4a, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','7',0,\n0xa1, 0xbf, 0x01, 0x00, 0x28, 0x4b, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','7',0,\n0xd0, 0xd3, 0x01, 0x00, 0x28, 0x4c, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','7',0,\n0xa1, 0xc3, 0x01, 0x00, 0x28, 0x4d, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','7',0,\n0xa1, 0xcb, 0x01, 0x00, 0x28, 0x4e, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','7',0,\n0x43, 0xab, 0x01, 0x00, 0x28, 0x4f, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','7',0,\n0x68, 0x55, 0x01, 0x00, 0x28, 0x50, 'b','r','a','i','l','l','e','_','d','o','t','s','_','5','7',0,\n0xd0, 0xcd, 0x01, 0x00, 0x28, 0x51, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','5','7',0,\n0xd0, 0xd1, 0x01, 0x00, 0x28, 0x52, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','5','7',0,\n0xa1, 0xc1, 0x01, 0x00, 0x28, 0x53, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','5','7',0,\n0xd0, 0xd5, 0x01, 0x00, 0x28, 0x54, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','5','7',0,\n0xa1, 0xc5, 0x01, 0x00, 0x28, 0x55, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','5','7',0,\n0xa1, 0xcd, 0x01, 0x00, 0x28, 0x56, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','5','7',0,\n0x43, 0xad, 0x01, 0x00, 0x28, 0x57, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','5','7',0,\n0xd0, 0xd9, 0x01, 0x00, 0x28, 0x58, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','5','7',0,\n0xa1, 0xc9, 0x01, 0x00, 0x28, 0x59, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','5','7',0,\n0xa1, 0xd1, 0x01, 0x00, 0x28, 0x5a, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','5','7',0,\n0x43, 0xb1, 0x01, 0x00, 0x28, 0x5b, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','5','7',0,\n0xa1, 0xd9, 0x01, 0x00, 0x28, 0x5c, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','5','7',0,\n0x43, 0xb9, 0x01, 0x00, 0x28, 0x5d, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','5','7',0,\n0x43, 0xc9, 0x01, 0x00, 0x28, 0x5e, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','5','7',0,\n0x87, 0x89, 0x01, 0x00, 0x28, 0x5f, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','5','7',0,\n0x68, 0x57, 0x01, 0x00, 0x28, 0x60, 'b','r','a','i','l','l','e','_','d','o','t','s','_','6','7',0,\n0xd0, 0xcf, 0x01, 0x00, 0x28, 0x61, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','6','7',0,\n0xd0, 0xd3, 0x01, 0x00, 0x28, 0x62, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','6','7',0,\n0xa1, 0xc3, 0x01, 0x00, 0x28, 0x63, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','6','7',0,\n0xd0, 0xd7, 0x01, 0x00, 0x28, 0x64, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','6','7',0,\n0xa1, 0xc7, 0x01, 0x00, 0x28, 0x65, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','6','7',0,\n0xa1, 0xcf, 0x01, 0x00, 0x28, 0x66, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','6','7',0,\n0x43, 0xaf, 0x01, 0x00, 0x28, 0x67, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','6','7',0,\n0xd0, 0xdb, 0x01, 0x00, 0x28, 0x68, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','6','7',0,\n0xa1, 0xcb, 0x01, 0x00, 0x28, 0x69, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','6','7',0,\n0xa1, 0xd3, 0x01, 0x00, 0x28, 0x6a, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','6','7',0,\n0x43, 0xb3, 0x01, 0x00, 0x28, 0x6b, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','6','7',0,\n0xa1, 0xdb, 0x01, 0x00, 0x28, 0x6c, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','6','7',0,\n0x43, 0xbb, 0x01, 0x00, 0x28, 0x6d, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','6','7',0,\n0x43, 0xcb, 0x01, 0x00, 0x28, 0x6e, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','6','7',0,\n0x87, 0x8b, 0x01, 0x00, 0x28, 0x6f, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','6','7',0,\n0xd0, 0xdf, 0x01, 0x00, 0x28, 0x70, 'b','r','a','i','l','l','e','_','d','o','t','s','_','5','6','7',0,\n0xa1, 0xcf, 0x01, 0x00, 0x28, 0x71, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','5','6','7',0,\n0xa1, 0xd7, 0x01, 0x00, 0x28, 0x72, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','5','6','7',0,\n0x43, 0xb7, 0x01, 0x00, 0x28, 0x73, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','5','6','7',0,\n0xa1, 0xdf, 0x01, 0x00, 0x28, 0x74, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','5','6','7',0,\n0x43, 0xbf, 0x01, 0x00, 0x28, 0x75, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','5','6','7',0,\n0x43, 0xcf, 0x01, 0x00, 0x28, 0x76, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','5','6','7',0,\n0x87, 0x8f, 0x01, 0x00, 0x28, 0x77, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','5','6','7',0,\n0xa1, 0xe7, 0x01, 0x00, 0x28, 0x78, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','5','6','7',0,\n0x43, 0xc7, 0x01, 0x00, 0x28, 0x79, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','5','6','7',0,\n0x43, 0xd7, 0x01, 0x00, 0x28, 0x7a, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','5','6','7',0,\n0x87, 0x97, 0x01, 0x00, 0x28, 0x7b, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','5','6','7',0,\n0x43, 0xe7, 0x01, 0x00, 0x28, 0x7c, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','5','6','7',0,\n0x87, 0xa7, 0x01, 0x00, 0x28, 0x7d, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','5','6','7',0,\n0x87, 0xc7, 0x01, 0x00, 0x28, 0x7e, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','5','6','7',0,\n0x0f, 0x47, 0x01, 0x00, 0x28, 0x7f, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','5','6','7',0,\n0xb4, 0x12, 0x01, 0x00, 0x28, 0x80, 'b','r','a','i','l','l','e','_','d','o','t','s','_','8',0,\n0x68, 0x4e, 0x01, 0x00, 0x28, 0x81, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','8',0,\n0x68, 0x50, 0x01, 0x00, 0x28, 0x82, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','8',0,\n0xd0, 0xc8, 0x01, 0x00, 0x28, 0x83, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','8',0,\n0x68, 0x52, 0x01, 0x00, 0x28, 0x84, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','8',0,\n0xd0, 0xca, 0x01, 0x00, 0x28, 0x85, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','8',0,\n0xd0, 0xce, 0x01, 0x00, 0x28, 0x86, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','8',0,\n0xa1, 0xbe, 0x01, 0x00, 0x28, 0x87, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','8',0,\n0x68, 0x54, 0x01, 0x00, 0x28, 0x88, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','8',0,\n0xd0, 0xcc, 0x01, 0x00, 0x28, 0x89, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','8',0,\n0xd0, 0xd0, 0x01, 0x00, 0x28, 0x8a, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','8',0,\n0xa1, 0xc0, 0x01, 0x00, 0x28, 0x8b, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','8',0,\n0xd0, 0xd4, 0x01, 0x00, 0x28, 0x8c, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','8',0,\n0xa1, 0xc4, 0x01, 0x00, 0x28, 0x8d, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','8',0,\n0xa1, 0xcc, 0x01, 0x00, 0x28, 0x8e, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','8',0,\n0x43, 0xac, 0x01, 0x00, 0x28, 0x8f, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','8',0,\n0x68, 0x56, 0x01, 0x00, 0x28, 0x90, 'b','r','a','i','l','l','e','_','d','o','t','s','_','5','8',0,\n0xd0, 0xce, 0x01, 0x00, 0x28, 0x91, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','5','8',0,\n0xd0, 0xd2, 0x01, 0x00, 0x28, 0x92, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','5','8',0,\n0xa1, 0xc2, 0x01, 0x00, 0x28, 0x93, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','5','8',0,\n0xd0, 0xd6, 0x01, 0x00, 0x28, 0x94, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','5','8',0,\n0xa1, 0xc6, 0x01, 0x00, 0x28, 0x95, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','5','8',0,\n0xa1, 0xce, 0x01, 0x00, 0x28, 0x96, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','5','8',0,\n0x43, 0xae, 0x01, 0x00, 0x28, 0x97, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','5','8',0,\n0xd0, 0xda, 0x01, 0x00, 0x28, 0x98, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','5','8',0,\n0xa1, 0xca, 0x01, 0x00, 0x28, 0x99, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','5','8',0,\n0xa1, 0xd2, 0x01, 0x00, 0x28, 0x9a, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','5','8',0,\n0x43, 0xb2, 0x01, 0x00, 0x28, 0x9b, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','5','8',0,\n0xa1, 0xda, 0x01, 0x00, 0x28, 0x9c, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','5','8',0,\n0x43, 0xba, 0x01, 0x00, 0x28, 0x9d, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','5','8',0,\n0x43, 0xca, 0x01, 0x00, 0x28, 0x9e, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','5','8',0,\n0x87, 0x8a, 0x01, 0x00, 0x28, 0x9f, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','5','8',0,\n0x68, 0x58, 0x01, 0x00, 0x28, 0xa0, 'b','r','a','i','l','l','e','_','d','o','t','s','_','6','8',0,\n0xd0, 0xd0, 0x01, 0x00, 0x28, 0xa1, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','6','8',0,\n0xd0, 0xd4, 0x01, 0x00, 0x28, 0xa2, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','6','8',0,\n0xa1, 0xc4, 0x01, 0x00, 0x28, 0xa3, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','6','8',0,\n0xd0, 0xd8, 0x01, 0x00, 0x28, 0xa4, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','6','8',0,\n0xa1, 0xc8, 0x01, 0x00, 0x28, 0xa5, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','6','8',0,\n0xa1, 0xd0, 0x01, 0x00, 0x28, 0xa6, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','6','8',0,\n0x43, 0xb0, 0x01, 0x00, 0x28, 0xa7, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','6','8',0,\n0xd0, 0xdc, 0x01, 0x00, 0x28, 0xa8, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','6','8',0,\n0xa1, 0xcc, 0x01, 0x00, 0x28, 0xa9, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','6','8',0,\n0xa1, 0xd4, 0x01, 0x00, 0x28, 0xaa, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','6','8',0,\n0x43, 0xb4, 0x01, 0x00, 0x28, 0xab, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','6','8',0,\n0xa1, 0xdc, 0x01, 0x00, 0x28, 0xac, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','6','8',0,\n0x43, 0xbc, 0x01, 0x00, 0x28, 0xad, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','6','8',0,\n0x43, 0xcc, 0x01, 0x00, 0x28, 0xae, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','6','8',0,\n0x87, 0x8c, 0x01, 0x00, 0x28, 0xaf, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','6','8',0,\n0xd0, 0xe0, 0x01, 0x00, 0x28, 0xb0, 'b','r','a','i','l','l','e','_','d','o','t','s','_','5','6','8',0,\n0xa1, 0xd0, 0x01, 0x00, 0x28, 0xb1, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','5','6','8',0,\n0xa1, 0xd8, 0x01, 0x00, 0x28, 0xb2, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','5','6','8',0,\n0x43, 0xb8, 0x01, 0x00, 0x28, 0xb3, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','5','6','8',0,\n0xa1, 0xe0, 0x01, 0x00, 0x28, 0xb4, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','5','6','8',0,\n0x43, 0xc0, 0x01, 0x00, 0x28, 0xb5, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','5','6','8',0,\n0x43, 0xd0, 0x01, 0x00, 0x28, 0xb6, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','5','6','8',0,\n0x87, 0x90, 0x01, 0x00, 0x28, 0xb7, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','5','6','8',0,\n0xa1, 0xe8, 0x01, 0x00, 0x28, 0xb8, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','5','6','8',0,\n0x43, 0xc8, 0x01, 0x00, 0x28, 0xb9, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','5','6','8',0,\n0x43, 0xd8, 0x01, 0x00, 0x28, 0xba, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','5','6','8',0,\n0x87, 0x98, 0x01, 0x00, 0x28, 0xbb, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','5','6','8',0,\n0x43, 0xe8, 0x01, 0x00, 0x28, 0xbc, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','5','6','8',0,\n0x87, 0xa8, 0x01, 0x00, 0x28, 0xbd, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','5','6','8',0,\n0x87, 0xc8, 0x01, 0x00, 0x28, 0xbe, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','5','6','8',0,\n0x0f, 0x48, 0x01, 0x00, 0x28, 0xbf, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','5','6','8',0,\n0x68, 0x5a, 0x01, 0x00, 0x28, 0xc0, 'b','r','a','i','l','l','e','_','d','o','t','s','_','7','8',0,\n0xd0, 0xd2, 0x01, 0x00, 0x28, 0xc1, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','7','8',0,\n0xd0, 0xd6, 0x01, 0x00, 0x28, 0xc2, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','7','8',0,\n0xa1, 0xc6, 0x01, 0x00, 0x28, 0xc3, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','7','8',0,\n0xd0, 0xda, 0x01, 0x00, 0x28, 0xc4, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','7','8',0,\n0xa1, 0xca, 0x01, 0x00, 0x28, 0xc5, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','7','8',0,\n0xa1, 0xd2, 0x01, 0x00, 0x28, 0xc6, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','7','8',0,\n0x43, 0xb2, 0x01, 0x00, 0x28, 0xc7, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','7','8',0,\n0xd0, 0xde, 0x01, 0x00, 0x28, 0xc8, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','7','8',0,\n0xa1, 0xce, 0x01, 0x00, 0x28, 0xc9, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','7','8',0,\n0xa1, 0xd6, 0x01, 0x00, 0x28, 0xca, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','7','8',0,\n0x43, 0xb6, 0x01, 0x00, 0x28, 0xcb, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','7','8',0,\n0xa1, 0xde, 0x01, 0x00, 0x28, 0xcc, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','7','8',0,\n0x43, 0xbe, 0x01, 0x00, 0x28, 0xcd, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','7','8',0,\n0x43, 0xce, 0x01, 0x00, 0x28, 0xce, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','7','8',0,\n0x87, 0x8e, 0x01, 0x00, 0x28, 0xcf, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','7','8',0,\n0xd0, 0xe2, 0x01, 0x00, 0x28, 0xd0, 'b','r','a','i','l','l','e','_','d','o','t','s','_','5','7','8',0,\n0xa1, 0xd2, 0x01, 0x00, 0x28, 0xd1, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','5','7','8',0,\n0xa1, 0xda, 0x01, 0x00, 0x28, 0xd2, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','5','7','8',0,\n0x43, 0xba, 0x01, 0x00, 0x28, 0xd3, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','5','7','8',0,\n0xa1, 0xe2, 0x01, 0x00, 0x28, 0xd4, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','5','7','8',0,\n0x43, 0xc2, 0x01, 0x00, 0x28, 0xd5, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','5','7','8',0,\n0x43, 0xd2, 0x01, 0x00, 0x28, 0xd6, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','5','7','8',0,\n0x87, 0x92, 0x01, 0x00, 0x28, 0xd7, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','5','7','8',0,\n0xa1, 0xea, 0x01, 0x00, 0x28, 0xd8, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','5','7','8',0,\n0x43, 0xca, 0x01, 0x00, 0x28, 0xd9, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','5','7','8',0,\n0x43, 0xda, 0x01, 0x00, 0x28, 0xda, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','5','7','8',0,\n0x87, 0x9a, 0x01, 0x00, 0x28, 0xdb, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','5','7','8',0,\n0x43, 0xea, 0x01, 0x00, 0x28, 0xdc, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','5','7','8',0,\n0x87, 0xaa, 0x01, 0x00, 0x28, 0xdd, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','5','7','8',0,\n0x87, 0xca, 0x01, 0x00, 0x28, 0xde, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','5','7','8',0,\n0x0f, 0x4a, 0x01, 0x00, 0x28, 0xdf, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','5','7','8',0,\n0xd0, 0xe6, 0x01, 0x00, 0x28, 0xe0, 'b','r','a','i','l','l','e','_','d','o','t','s','_','6','7','8',0,\n0xa1, 0xd6, 0x01, 0x00, 0x28, 0xe1, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','6','7','8',0,\n0xa1, 0xde, 0x01, 0x00, 0x28, 0xe2, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','6','7','8',0,\n0x43, 0xbe, 0x01, 0x00, 0x28, 0xe3, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','6','7','8',0,\n0xa1, 0xe6, 0x01, 0x00, 0x28, 0xe4, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','6','7','8',0,\n0x43, 0xc6, 0x01, 0x00, 0x28, 0xe5, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','6','7','8',0,\n0x43, 0xd6, 0x01, 0x00, 0x28, 0xe6, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','6','7','8',0,\n0x87, 0x96, 0x01, 0x00, 0x28, 0xe7, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','6','7','8',0,\n0xa1, 0xee, 0x01, 0x00, 0x28, 0xe8, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','6','7','8',0,\n0x43, 0xce, 0x01, 0x00, 0x28, 0xe9, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','6','7','8',0,\n0x43, 0xde, 0x01, 0x00, 0x28, 0xea, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','6','7','8',0,\n0x87, 0x9e, 0x01, 0x00, 0x28, 0xeb, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','6','7','8',0,\n0x43, 0xee, 0x01, 0x00, 0x28, 0xec, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','6','7','8',0,\n0x87, 0xae, 0x01, 0x00, 0x28, 0xed, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','6','7','8',0,\n0x87, 0xce, 0x01, 0x00, 0x28, 0xee, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','6','7','8',0,\n0x0f, 0x4e, 0x01, 0x00, 0x28, 0xef, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','6','7','8',0,\n0xa1, 0xf6, 0x01, 0x00, 0x28, 0xf0, 'b','r','a','i','l','l','e','_','d','o','t','s','_','5','6','7','8',0,\n0x43, 0xd6, 0x01, 0x00, 0x28, 0xf1, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','5','6','7','8',0,\n0x43, 0xe6, 0x01, 0x00, 0x28, 0xf2, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','5','6','7','8',0,\n0x87, 0xa6, 0x01, 0x00, 0x28, 0xf3, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','5','6','7','8',0,\n0x43, 0xf6, 0x01, 0x00, 0x28, 0xf4, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','5','6','7','8',0,\n0x87, 0xb6, 0x01, 0x00, 0x28, 0xf5, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','5','6','7','8',0,\n0x87, 0xd6, 0x01, 0x00, 0x28, 0xf6, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','5','6','7','8',0,\n0x0f, 0x56, 0x01, 0x00, 0x28, 0xf7, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','5','6','7','8',0,\n0x44, 0x06, 0x01, 0x00, 0x28, 0xf8, 'b','r','a','i','l','l','e','_','d','o','t','s','_','4','5','6','7','8',0,\n0x87, 0xc6, 0x01, 0x00, 0x28, 0xf9, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','4','5','6','7','8',0,\n0x87, 0xe6, 0x01, 0x00, 0x28, 0xfa, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','4','5','6','7','8',0,\n0x0f, 0x66, 0x01, 0x00, 0x28, 0xfb, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','4','5','6','7','8',0,\n0x88, 0x06, 0x01, 0x00, 0x28, 0xfc, 'b','r','a','i','l','l','e','_','d','o','t','s','_','3','4','5','6','7','8',0,\n0x0f, 0x86, 0x01, 0x00, 0x28, 0xfd, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','3','4','5','6','7','8',0,\n0x0f, 0xc6, 0x01, 0x00, 0x28, 0xfe, 'b','r','a','i','l','l','e','_','d','o','t','s','_','2','3','4','5','6','7','8',0,\n0x1e, 0xc6, 0x01, 0x00, 0x28, 0xff, 'b','r','a','i','l','l','e','_','d','o','t','s','_','1','2','3','4','5','6','7','8',0,\n0x2e, 0xbf, 0x01, 0x00, 0x0d, 0x82, 'S','i','n','h','_','n','g',0,\n0x2e, 0x7e, 0x01, 0x00, 0x0d, 0x83, 'S','i','n','h','_','h','2',0,\n0x17, 0x1f, 0x01, 0x00, 0x0d, 0x85, 'S','i','n','h','_','a',0,\n0x2e, 0x9f, 0x01, 0x00, 0x0d, 0x86, 'S','i','n','h','_','a','a',0,\n0x2e, 0xa3, 0x01, 0x00, 0x0d, 0x87, 'S','i','n','h','_','a','e',0,\n0x5d, 0xab, 0x01, 0x00, 0x0d, 0x88, 'S','i','n','h','_','a','e','e',0,\n0x17, 0x27, 0x01, 0x00, 0x0d, 0x89, 'S','i','n','h','_','i',0,\n0x2e, 0xb7, 0x01, 0x00, 0x0d, 0x8a, 'S','i','n','h','_','i','i',0,\n0x17, 0x33, 0x01, 0x00, 0x0d, 0x8b, 'S','i','n','h','_','u',0,\n0x2e, 0xdb, 0x01, 0x00, 0x0d, 0x8c, 'S','i','n','h','_','u','u',0,\n0x2e, 0xc9, 0x01, 0x00, 0x0d, 0x8d, 'S','i','n','h','_','r','i',0,\n0x5d, 0xfb, 0x01, 0x00, 0x0d, 0x8e, 'S','i','n','h','_','r','i','i',0,\n0x2e, 0xc9, 0x01, 0x00, 0x0d, 0x8f, 'S','i','n','h','_','l','u',0,\n0x5e, 0x07, 0x01, 0x00, 0x0d, 0x90, 'S','i','n','h','_','l','u','u',0,\n0x17, 0x23, 0x01, 0x00, 0x0d, 0x91, 'S','i','n','h','_','e',0,\n0x2e, 0xab, 0x01, 0x00, 0x0d, 0x92, 'S','i','n','h','_','e','e',0,\n0x2e, 0xa7, 0x01, 0x00, 0x0d, 0x93, 'S','i','n','h','_','a','i',0,\n0x17, 0x2d, 0x01, 0x00, 0x0d, 0x94, 'S','i','n','h','_','o',0,\n0x2e, 0xc9, 0x01, 0x00, 0x0d, 0x95, 'S','i','n','h','_','o','o',0,\n0x2e, 0xb3, 0x01, 0x00, 0x0d, 0x96, 'S','i','n','h','_','a','u',0,\n0x2e, 0xb3, 0x01, 0x00, 0x0d, 0x9a, 'S','i','n','h','_','k','a',0,\n0x5d, 0xd5, 0x01, 0x00, 0x0d, 0x9b, 'S','i','n','h','_','k','h','a',0,\n0x2e, 0xab, 0x01, 0x00, 0x0d, 0x9c, 'S','i','n','h','_','g','a',0,\n0x5d, 0xc5, 0x01, 0x00, 0x0d, 0x9d, 'S','i','n','h','_','g','h','a',0,\n0x5d, 0xb0, 0x01, 0x00, 0x0d, 0x9e, 'S','i','n','h','_','n','g','2',0,\n0x5d, 0xdf, 0x01, 0x00, 0x0d, 0x9f, 'S','i','n','h','_','n','g','a',0,\n0x2e, 0xa3, 0x01, 0x00, 0x0d, 0xa0, 'S','i','n','h','_','c','a',0,\n0x5d, 0xb5, 0x01, 0x00, 0x0d, 0xa1, 'S','i','n','h','_','c','h','a',0,\n0x2e, 0xb1, 0x01, 0x00, 0x0d, 0xa2, 'S','i','n','h','_','j','a',0,\n0x5d, 0xd1, 0x01, 0x00, 0x0d, 0xa3, 'S','i','n','h','_','j','h','a',0,\n0x5e, 0x03, 0x01, 0x00, 0x0d, 0xa4, 'S','i','n','h','_','n','y','a',0,\n0xbc, 0x4b, 0x01, 0x00, 0x0d, 0xa5, 'S','i','n','h','_','j','n','y','a',0,\n0x5d, 0xe5, 0x01, 0x00, 0x0d, 0xa6, 'S','i','n','h','_','n','j','a',0,\n0x5e, 0x11, 0x01, 0x00, 0x0d, 0xa7, 'S','i','n','h','_','t','t','a',0,\n0xbc, 0x91, 0x01, 0x00, 0x0d, 0xa8, 'S','i','n','h','_','t','t','h','a',0,\n0x5d, 0xb1, 0x01, 0x00, 0x0d, 0xa9, 'S','i','n','h','_','d','d','a',0,\n0xbb, 0xd1, 0x01, 0x00, 0x0d, 0xaa, 'S','i','n','h','_','d','d','h','a',0,\n0x5d, 0xed, 0x01, 0x00, 0x0d, 0xab, 'S','i','n','h','_','n','n','a',0,\n0xbc, 0x19, 0x01, 0x00, 0x0d, 0xac, 'S','i','n','h','_','n','d','d','a',0,\n0x5d, 0xf9, 0x01, 0x00, 0x0d, 0xad, 'S','i','n','h','_','t','h','a',0,\n0xbc, 0x61, 0x01, 0x00, 0x0d, 0xae, 'S','i','n','h','_','t','h','h','a',0,\n0x5d, 0xb9, 0x01, 0x00, 0x0d, 0xaf, 'S','i','n','h','_','d','h','a',0,\n0xbb, 0xe1, 0x01, 0x00, 0x0d, 0xb0, 'S','i','n','h','_','d','h','h','a',0,\n0x2e, 0xb9, 0x01, 0x00, 0x0d, 0xb1, 'S','i','n','h','_','n','a',0,\n0xbc, 0x21, 0x01, 0x00, 0x0d, 0xb3, 'S','i','n','h','_','n','d','h','a',0,\n0x2e, 0xbd, 0x01, 0x00, 0x0d, 0xb4, 'S','i','n','h','_','p','a',0,\n0x5d, 0xe9, 0x01, 0x00, 0x0d, 0xb5, 'S','i','n','h','_','p','h','a',0,\n0x2e, 0xa1, 0x01, 0x00, 0x0d, 0xb6, 'S','i','n','h','_','b','a',0,\n0x5d, 0xb1, 0x01, 0x00, 0x0d, 0xb7, 'S','i','n','h','_','b','h','a',0,\n0x2e, 0xb7, 0x01, 0x00, 0x0d, 0xb8, 'S','i','n','h','_','m','a',0,\n0x5d, 0xd1, 0x01, 0x00, 0x0d, 0xb9, 'S','i','n','h','_','m','b','a',0,\n0x2e, 0xcf, 0x01, 0x00, 0x0d, 0xba, 'S','i','n','h','_','y','a',0,\n0x2e, 0xc1, 0x01, 0x00, 0x0d, 0xbb, 'S','i','n','h','_','r','a',0,\n0x2e, 0xb5, 0x01, 0x00, 0x0d, 0xbd, 'S','i','n','h','_','l','a',0,\n0x2e, 0xc9, 0x01, 0x00, 0x0d, 0xc0, 'S','i','n','h','_','v','a',0,\n0x5d, 0xf5, 0x01, 0x00, 0x0d, 0xc1, 'S','i','n','h','_','s','h','a',0,\n0xbc, 0x85, 0x01, 0x00, 0x0d, 0xc2, 'S','i','n','h','_','s','s','h','a',0,\n0x2e, 0xc3, 0x01, 0x00, 0x0d, 0xc3, 'S','i','n','h','_','s','a',0,\n0x2e, 0xad, 0x01, 0x00, 0x0d, 0xc4, 'S','i','n','h','_','h','a',0,\n0x5d, 0xe1, 0x01, 0x00, 0x0d, 0xc5, 'S','i','n','h','_','l','l','a',0,\n0x2e, 0xa9, 0x01, 0x00, 0x0d, 0xc6, 'S','i','n','h','_','f','a',0,\n0x2e, 0xaa, 0x01, 0x00, 0x0d, 0xca, 'S','i','n','h','_','a','l',0,\n0x5d, 0x70, 0x01, 0x00, 0x0d, 0xcf, 'S','i','n','h','_','a','a','2',0,\n0x5d, 0x78, 0x01, 0x00, 0x0d, 0xd0, 'S','i','n','h','_','a','e','2',0,\n0xbb, 0x88, 0x01, 0x00, 0x0d, 0xd1, 'S','i','n','h','_','a','e','e','2',0,\n0x2e, 0x80, 0x01, 0x00, 0x0d, 0xd2, 'S','i','n','h','_','i','2',0,\n0x5d, 0xa0, 0x01, 0x00, 0x0d, 0xd3, 'S','i','n','h','_','i','i','2',0,\n0x2e, 0x98, 0x01, 0x00, 0x0d, 0xd4, 'S','i','n','h','_','u','2',0,\n0x5d, 0xe8, 0x01, 0x00, 0x0d, 0xd6, 'S','i','n','h','_','u','u','2',0,\n0x5d, 0xdc, 0x01, 0x00, 0x0d, 0xd8, 'S','i','n','h','_','r','u','2',0,\n0x2e, 0x78, 0x01, 0x00, 0x0d, 0xd9, 'S','i','n','h','_','e','2',0,\n0x5d, 0x88, 0x01, 0x00, 0x0d, 0xda, 'S','i','n','h','_','e','e','2',0,\n0x5d, 0x80, 0x01, 0x00, 0x0d, 0xdb, 'S','i','n','h','_','a','i','2',0,\n0x2e, 0x8c, 0x01, 0x00, 0x0d, 0xdc, 'S','i','n','h','_','o','2',0,\n0x5d, 0xc4, 0x01, 0x00, 0x0d, 0xdd, 'S','i','n','h','_','o','o','2',0,\n0x5d, 0x98, 0x01, 0x00, 0x0d, 0xde, 'S','i','n','h','_','a','u','2',0,\n0x5d, 0xc4, 0x01, 0x00, 0x0d, 0xdf, 'S','i','n','h','_','l','u','2',0,\n0xbc, 0x70, 0x01, 0x00, 0x0d, 0xf2, 'S','i','n','h','_','r','u','u','2',0,\n0xbc, 0x40, 0x01, 0x00, 0x0d, 0xf3, 'S','i','n','h','_','l','u','u','2',0,\n0x2f, 0xe7, 0x01, 0x00, 0x0d, 0xf4, 'S','i','n','h','_','k','u','n','d','d','a','l','i','y','a',0,\n0xd8, 0x5d, 0x10, 0x08, 0xff, 0x01, 'X','F','8','6','M','o','d','e','L','o','c','k',0,\n0x7c, 0x8e, 0x10, 0x08, 0xff, 0x02, 'X','F','8','6','M','o','n','B','r','i','g','h','t','n','e','s','s','U','p',0,\n0xf3, 0x08, 0x10, 0x08, 0xff, 0x03, 'X','F','8','6','M','o','n','B','r','i','g','h','t','n','e','s','s','D','o','w','n',0,\n0x77, 0xce, 0x10, 0x08, 0xff, 0x04, 'X','F','8','6','K','b','d','L','i','g','h','t','O','n','O','f','f',0,\n0xbc, 0x8e, 0x10, 0x08, 0xff, 0x05, 'X','F','8','6','K','b','d','B','r','i','g','h','t','n','e','s','s','U','p',0,\n0xf3, 0x08, 0x10, 0x08, 0xff, 0x06, 'X','F','8','6','K','b','d','B','r','i','g','h','t','n','e','s','s','D','o','w','n',0,\n0xe6, 0x61, 0x10, 0x08, 0xff, 0x07, 'X','F','8','6','M','o','n','B','r','i','g','h','t','n','e','s','s','C','y','c','l','e',0,\n0x6e, 0x8d, 0x10, 0x08, 0xff, 0x10, 'X','F','8','6','S','t','a','n','d','b','y',0,\n0x34, 0x23, 0x10, 0x08, 0xff, 0x11, 'X','F','8','6','A','u','d','i','o','L','o','w','e','r','V','o','l','u','m','e',0,\n0xaa, 0x19, 0x10, 0x08, 0xff, 0x12, 'X','F','8','6','A','u','d','i','o','M','u','t','e',0,\n0x25, 0xe3, 0x10, 0x08, 0xff, 0x13, 'X','F','8','6','A','u','d','i','o','R','a','i','s','e','V','o','l','u','m','e',0,\n0xa9, 0xfb, 0x10, 0x08, 0xff, 0x14, 'X','F','8','6','A','u','d','i','o','P','l','a','y',0,\n0xaa, 0x46, 0x10, 0x08, 0xff, 0x15, 'X','F','8','6','A','u','d','i','o','S','t','o','p',0,\n0xaa, 0x18, 0x10, 0x08, 0xff, 0x16, 'X','F','8','6','A','u','d','i','o','P','r','e','v',0,\n0xa9, 0xf8, 0x10, 0x08, 0xff, 0x17, 'X','F','8','6','A','u','d','i','o','N','e','x','t',0,\n0xd6, 0xe7, 0x10, 0x08, 0xff, 0x18, 'X','F','8','6','H','o','m','e','P','a','g','e',0,\n0x4d, 0x0a, 0x10, 0x08, 0xff, 0x19, 'X','F','8','6','M','a','i','l',0,\n0x9b, 0x6c, 0x10, 0x08, 0xff, 0x1a, 'X','F','8','6','S','t','a','r','t',0,\n0x36, 0x2e, 0x10, 0x08, 0xff, 0x1b, 'X','F','8','6','S','e','a','r','c','h',0,\n0xa8, 0xec, 0x10, 0x08, 0xff, 0x1c, 'X','F','8','6','A','u','d','i','o','R','e','c','o','r','d',0,\n0x49, 0x48, 0x10, 0x08, 0xff, 0x1d, 'X','F','8','6','C','a','l','c','u','l','a','t','o','r',0,\n0x4d, 0x25, 0x10, 0x08, 0xff, 0x1e, 'X','F','8','6','M','e','m','o',0,\n0xd8, 0x8e, 0x10, 0x08, 0xff, 0x1f, 'X','F','8','6','T','o','D','o','L','i','s','t',0,\n0xd1, 0xc4, 0x10, 0x08, 0xff, 0x20, 'X','F','8','6','C','a','l','e','n','d','a','r',0,\n0xba, 0x38, 0x10, 0x08, 0xff, 0x21, 'X','F','8','6','P','o','w','e','r','D','o','w','n',0,\n0xc0, 0x5e, 0x10, 0x08, 0xff, 0x22, 'X','F','8','6','C','o','n','t','r','a','s','t','A','d','j','u','s','t',0,\n0xdb, 0xda, 0x10, 0x08, 0xff, 0x23, 'X','F','8','6','R','o','c','k','e','r','U','p',0,\n0x70, 0x38, 0x10, 0x08, 0xff, 0x24, 'X','F','8','6','R','o','c','k','e','r','D','o','w','n',0,\n0xe0, 0xcc, 0x10, 0x08, 0xff, 0x25, 'X','F','8','6','R','o','c','k','e','r','E','n','t','e','r',0,\n0x4c, 0xa5, 0x10, 0x08, 0xff, 0x26, 'X','F','8','6','B','a','c','k',0,\n0x6c, 0x04, 0x10, 0x08, 0xff, 0x27, 'X','F','8','6','F','o','r','w','a','r','d',0,\n0x4d, 0x96, 0x10, 0x08, 0xff, 0x28, 'X','F','8','6','S','t','o','p',0,\n0x6c, 0xf2, 0x10, 0x08, 0xff, 0x29, 'X','F','8','6','R','e','f','r','e','s','h',0,\n0xdc, 0xee, 0x10, 0x08, 0xff, 0x2a, 'X','F','8','6','P','o','w','e','r','O','f','f',0,\n0x36, 0x76, 0x10, 0x08, 0xff, 0x2b, 'X','F','8','6','W','a','k','e','U','p',0,\n0x9a, 0x2e, 0x10, 0x08, 0xff, 0x2c, 'X','F','8','6','E','j','e','c','t',0,\n0xd8, 0xcc, 0x10, 0x08, 0xff, 0x2d, 'X','F','8','6','S','c','r','e','e','n','S','a','v','e','r',0,\n0x26, 0x51, 0x10, 0x08, 0xff, 0x2e, 'X','F','8','6','W','W','W',0,\n0x9b, 0x1e, 0x10, 0x08, 0xff, 0x2f, 'X','F','8','6','S','l','e','e','p',0,\n0xab, 0x55, 0x10, 0x08, 0xff, 0x30, 'X','F','8','6','F','a','v','o','r','i','t','e','s',0,\n0x54, 0x47, 0x10, 0x08, 0xff, 0x31, 'X','F','8','6','A','u','d','i','o','P','a','u','s','e',0,\n0x53, 0xdb, 0x10, 0x08, 0xff, 0x32, 'X','F','8','6','A','u','d','i','o','M','e','d','i','a',0,\n0x63, 0x94, 0x10, 0x08, 0xff, 0x33, 'X','F','8','6','M','y','C','o','m','p','u','t','e','r',0,\n0x73, 0x3b, 0x10, 0x08, 0xff, 0x34, 'X','F','8','6','V','e','n','d','o','r','H','o','m','e',0,\n0xaf, 0x9e, 0x10, 0x08, 0xff, 0x35, 'X','F','8','6','L','i','g','h','t','B','u','l','b',0,\n0x4d, 0x66, 0x10, 0x08, 0xff, 0x36, 'X','F','8','6','S','h','o','p',0,\n0x6c, 0x09, 0x10, 0x08, 0xff, 0x37, 'X','F','8','6','H','i','s','t','o','r','y',0,\n0x6c, 0xc4, 0x10, 0x08, 0xff, 0x38, 'X','F','8','6','O','p','e','n','U','R','L',0,\n0x77, 0x71, 0x10, 0x08, 0xff, 0x39, 'X','F','8','6','A','d','d','F','a','v','o','r','i','t','e',0,\n0xd7, 0x49, 0x10, 0x08, 0xff, 0x3a, 'X','F','8','6','H','o','t','L','i','n','k','s',0,\n0xcc, 0x1e, 0x10, 0x08, 0xff, 0x3b, 'X','F','8','6','B','r','i','g','h','t','n','e','s','s','A','d','j','u','s','t',0,\n0x6a, 0x6b, 0x10, 0x08, 0xff, 0x3c, 'X','F','8','6','F','i','n','a','n','c','e',0,\n0xad, 0x25, 0x10, 0x08, 0xff, 0x3d, 'X','F','8','6','C','o','m','m','u','n','i','t','y',0,\n0xa9, 0x6c, 0x10, 0x08, 0xff, 0x3e, 'X','F','8','6','A','u','d','i','o','R','e','w','i','n','d',0,\n0x7f, 0x84, 0x10, 0x08, 0xff, 0x3f, 'X','F','8','6','B','a','c','k','F','o','r','w','a','r','d',0,\n0x6b, 0x6c, 0x10, 0x08, 0xff, 0x40, 'X','F','8','6','L','a','u','n','c','h','0',0,\n0x6b, 0x6d, 0x10, 0x08, 0xff, 0x41, 'X','F','8','6','L','a','u','n','c','h','1',0,\n0x6b, 0x6e, 0x10, 0x08, 0xff, 0x42, 'X','F','8','6','L','a','u','n','c','h','2',0,\n0x6b, 0x6f, 0x10, 0x08, 0xff, 0x43, 'X','F','8','6','L','a','u','n','c','h','3',0,\n0x6b, 0x70, 0x10, 0x08, 0xff, 0x44, 'X','F','8','6','L','a','u','n','c','h','4',0,\n0x6b, 0x71, 0x10, 0x08, 0xff, 0x45, 'X','F','8','6','L','a','u','n','c','h','5',0,\n0x6b, 0x72, 0x10, 0x08, 0xff, 0x46, 'X','F','8','6','L','a','u','n','c','h','6',0,\n0x6b, 0x73, 0x10, 0x08, 0xff, 0x47, 'X','F','8','6','L','a','u','n','c','h','7',0,\n0x6b, 0x74, 0x10, 0x08, 0xff, 0x48, 'X','F','8','6','L','a','u','n','c','h','8',0,\n0x6b, 0x75, 0x10, 0x08, 0xff, 0x49, 'X','F','8','6','L','a','u','n','c','h','9',0,\n0x6b, 0x7d, 0x10, 0x08, 0xff, 0x4a, 'X','F','8','6','L','a','u','n','c','h','A',0,\n0x6b, 0x7e, 0x10, 0x08, 0xff, 0x4b, 'X','F','8','6','L','a','u','n','c','h','B',0,\n0x6b, 0x7f, 0x10, 0x08, 0xff, 0x4c, 'X','F','8','6','L','a','u','n','c','h','C',0,\n0x6b, 0x80, 0x10, 0x08, 0xff, 0x4d, 'X','F','8','6','L','a','u','n','c','h','D',0,\n0x6b, 0x81, 0x10, 0x08, 0xff, 0x4e, 'X','F','8','6','L','a','u','n','c','h','E',0,\n0x6b, 0x82, 0x10, 0x08, 0xff, 0x4f, 'X','F','8','6','L','a','u','n','c','h','F',0,\n0xd9, 0x34, 0x10, 0x08, 0xff, 0x50, 'X','F','8','6','A','p','p','l','i','c','a','t','i','o','n','L','e','f','t',0,\n0xb3, 0x48, 0x10, 0x08, 0xff, 0x51, 'X','F','8','6','A','p','p','l','i','c','a','t','i','o','n','R','i','g','h','t',0,\n0x4c, 0xf5, 0x10, 0x08, 0xff, 0x52, 'X','F','8','6','B','o','o','k',0,\n0x12, 0xc2, 0x10, 0x08, 0xff, 0x53, 'X','F','8','6','C','D',0,\n0x49, 0x34, 0x10, 0x08, 0xff, 0x54, 'X','F','8','6','C','a','l','c','u','l','a','t','e','r',0,\n0x9a, 0x18, 0x10, 0x08, 0xff, 0x55, 'X','F','8','6','C','l','e','a','r',0,\n0x9a, 0x57, 0x10, 0x08, 0xff, 0x56, 'X','F','8','6','C','l','o','s','e',0,\n0x4d, 0x0d, 0x10, 0x08, 0xff, 0x57, 'X','F','8','6','C','o','p','y',0,\n0x26, 0x5a, 0x10, 0x08, 0xff, 0x58, 'X','F','8','6','C','u','t',0,\n0x6a, 0xbb, 0x10, 0x08, 0xff, 0x59, 'X','F','8','6','D','i','s','p','l','a','y',0,\n0x25, 0xf1, 0x10, 0x08, 0xff, 0x5a, 'X','F','8','6','D','O','S',0,\n0xab, 0xeb, 0x10, 0x08, 0xff, 0x5b, 'X','F','8','6','D','o','c','u','m','e','n','t','s',0,\n0x9a, 0x92, 0x10, 0x08, 0xff, 0x5c, 'X','F','8','6','E','x','c','e','l',0,\n0xd9, 0xbc, 0x10, 0x08, 0xff, 0x5d, 'X','F','8','6','E','x','p','l','o','r','e','r',0,\n0x4c, 0xdb, 0x10, 0x08, 0xff, 0x5e, 'X','F','8','6','G','a','m','e',0,\n0x12, 0xf5, 0x10, 0x08, 0xff, 0x5f, 'X','F','8','6','G','o',0,\n0x38, 0x5a, 0x10, 0x08, 0xff, 0x60, 'X','F','8','6','i','T','o','u','c','h',0,\n0x35, 0x96, 0x10, 0x08, 0xff, 0x61, 'X','F','8','6','L','o','g','O','f','f',0,\n0x35, 0xaa, 0x10, 0x08, 0xff, 0x62, 'X','F','8','6','M','a','r','k','e','t',0,\n0x6b, 0xb7, 0x10, 0x08, 0xff, 0x63, 'X','F','8','6','M','e','e','t','i','n','g',0,\n0x35, 0x8c, 0x10, 0x08, 0xff, 0x65, 'X','F','8','6','M','e','n','u','K','B',0,\n0x35, 0x96, 0x10, 0x08, 0xff, 0x66, 'X','F','8','6','M','e','n','u','P','B',0,\n0x6c, 0xe5, 0x10, 0x08, 0xff, 0x67, 'X','F','8','6','M','y','S','i','t','e','s',0,\n0x26, 0x69, 0x10, 0x08, 0xff, 0x68, 'X','F','8','6','N','e','w',0,\n0x4d, 0x45, 0x10, 0x08, 0xff, 0x69, 'X','F','8','6','N','e','w','s',0,\n0x61, 0x2b, 0x10, 0x08, 0xff, 0x6a, 'X','F','8','6','O','f','f','i','c','e','H','o','m','e',0,\n0x4d, 0x50, 0x10, 0x08, 0xff, 0x6b, 'X','F','8','6','O','p','e','n',0,\n0x36, 0xf0, 0x10, 0x08, 0xff, 0x6c, 'X','F','8','6','O','p','t','i','o','n',0,\n0x9a, 0xe1, 0x10, 0x08, 0xff, 0x6d, 'X','F','8','6','P','a','s','t','e',0,\n0x9a, 0xfd, 0x10, 0x08, 0xff, 0x6e, 'X','F','8','6','P','h','o','n','e',0,\n0x09, 0x4d, 0x10, 0x08, 0xff, 0x70, 'X','F','8','6','Q',0,\n0x9b, 0x19, 0x10, 0x08, 0xff, 0x72, 'X','F','8','6','R','e','p','l','y',0,\n0x36, 0x52, 0x10, 0x08, 0xff, 0x73, 'X','F','8','6','R','e','l','o','a','d',0,\n0xc0, 0x7d, 0x10, 0x08, 0xff, 0x74, 'X','F','8','6','R','o','t','a','t','e','W','i','n','d','o','w','s',0,\n0x78, 0x62, 0x10, 0x08, 0xff, 0x75, 'X','F','8','6','R','o','t','a','t','i','o','n','P','B',0,\n0x78, 0x58, 0x10, 0x08, 0xff, 0x76, 'X','F','8','6','R','o','t','a','t','i','o','n','K','B',0,\n0x4d, 0x4d, 0x10, 0x08, 0xff, 0x77, 'X','F','8','6','S','a','v','e',0,\n0xdb, 0x9a, 0x10, 0x08, 0xff, 0x78, 'X','F','8','6','S','c','r','o','l','l','U','p',0,\n0x6f, 0x38, 0x10, 0x08, 0xff, 0x79, 'X','F','8','6','S','c','r','o','l','l','D','o','w','n',0,\n0xde, 0x65, 0x10, 0x08, 0xff, 0x7a, 'X','F','8','6','S','c','r','o','l','l','C','l','i','c','k',0,\n0x4d, 0x4c, 0x10, 0x08, 0xff, 0x7b, 'X','F','8','6','S','e','n','d',0,\n0x9b, 0x48, 0x10, 0x08, 0xff, 0x7c, 'X','F','8','6','S','p','e','l','l',0,\n0xf0, 0x6c, 0x10, 0x08, 0xff, 0x7d, 'X','F','8','6','S','p','l','i','t','S','c','r','e','e','n',0,\n0x6f, 0xf4, 0x10, 0x08, 0xff, 0x7e, 'X','F','8','6','S','u','p','p','o','r','t',0,\n0xda, 0x95, 0x10, 0x08, 0xff, 0x7f, 'X','F','8','6','T','a','s','k','P','a','n','e',0,\n0xdc, 0x7e, 0x10, 0x08, 0xff, 0x80, 'X','F','8','6','T','e','r','m','i','n','a','l',0,\n0x9b, 0x7f, 0x10, 0x08, 0xff, 0x81, 'X','F','8','6','T','o','o','l','s',0,\n0x37, 0x36, 0x10, 0x08, 0xff, 0x82, 'X','F','8','6','T','r','a','v','e','l',0,\n0x37, 0x22, 0x10, 0x08, 0xff, 0x84, 'X','F','8','6','U','s','e','r','P','B',0,\n0x6e, 0x1c, 0x10, 0x08, 0xff, 0x85, 'X','F','8','6','U','s','e','r','1','K','B',0,\n0x6e, 0x20, 0x10, 0x08, 0xff, 0x86, 'X','F','8','6','U','s','e','r','2','K','B',0,\n0x9b, 0x31, 0x10, 0x08, 0xff, 0x87, 'X','F','8','6','V','i','d','e','o',0,\n0xe4, 0xcc, 0x10, 0x08, 0xff, 0x88, 'X','F','8','6','W','h','e','e','l','B','u','t','t','o','n',0,\n0x4d, 0x9c, 0x10, 0x08, 0xff, 0x89, 'X','F','8','6','W','o','r','d',0,\n0x4d, 0x74, 0x10, 0x08, 0xff, 0x8a, 'X','F','8','6','X','f','e','r',0,\n0x37, 0xdc, 0x10, 0x08, 0xff, 0x8b, 'X','F','8','6','Z','o','o','m','I','n',0,\n0x70, 0x52, 0x10, 0x08, 0xff, 0x8c, 'X','F','8','6','Z','o','o','m','O','u','t',0,\n0x4c, 0xff, 0x10, 0x08, 0xff, 0x8d, 'X','F','8','6','A','w','a','y',0,\n0xb3, 0x38, 0x10, 0x08, 0xff, 0x8e, 'X','F','8','6','M','e','s','s','e','n','g','e','r',0,\n0x35, 0xfb, 0x10, 0x08, 0xff, 0x8f, 'X','F','8','6','W','e','b','C','a','m',0,\n0xb2, 0x04, 0x10, 0x08, 0xff, 0x90, 'X','F','8','6','M','a','i','l','F','o','r','w','a','r','d',0,\n0xda, 0x8d, 0x10, 0x08, 0xff, 0x91, 'X','F','8','6','P','i','c','t','u','r','e','s',0,\n0x9b, 0x39, 0x10, 0x08, 0xff, 0x92, 'X','F','8','6','M','u','s','i','c',0,\n0x69, 0x71, 0x10, 0x08, 0xff, 0x93, 'X','F','8','6','B','a','t','t','e','r','y',0,\n0xab, 0xa4, 0x10, 0x08, 0xff, 0x94, 'X','F','8','6','B','l','u','e','t','o','o','t','h',0,\n0x4c, 0x98, 0x10, 0x08, 0xff, 0x95, 'X','F','8','6','W','L','A','N',0,\n0x26, 0x34, 0x10, 0x08, 0xff, 0x96, 'X','F','8','6','U','W','B',0,\n0x51, 0x84, 0x10, 0x08, 0xff, 0x97, 'X','F','8','6','A','u','d','i','o','F','o','r','w','a','r','d',0,\n0xa9, 0x1a, 0x10, 0x08, 0xff, 0x98, 'X','F','8','6','A','u','d','i','o','R','e','p','e','a','t',0,\n0x93, 0x1b, 0x10, 0x08, 0xff, 0x99, 'X','F','8','6','A','u','d','i','o','R','a','n','d','o','m','P','l','a','y',0,\n0xde, 0x95, 0x10, 0x08, 0xff, 0x9a, 'X','F','8','6','S','u','b','t','i','t','l','e',0,\n0x87, 0xa5, 0x10, 0x08, 0xff, 0x9b, 'X','F','8','6','A','u','d','i','o','C','y','c','l','e','T','r','a','c','k',0,\n0x5a, 0x79, 0x10, 0x08, 0xff, 0x9c, 'X','F','8','6','C','y','c','l','e','A','n','g','l','e',0,\n0xab, 0xf5, 0x10, 0x08, 0xff, 0x9d, 'X','F','8','6','F','r','a','m','e','B','a','c','k',0,\n0x66, 0x84, 0x10, 0x08, 0xff, 0x9e, 'X','F','8','6','F','r','a','m','e','F','o','r','w','a','r','d',0,\n0x4d, 0x63, 0x10, 0x08, 0xff, 0x9f, 'X','F','8','6','T','i','m','e',0,\n0x36, 0x5e, 0x10, 0x08, 0xff, 0xa0, 'X','F','8','6','S','e','l','e','c','t',0,\n0x4d, 0x75, 0x10, 0x08, 0xff, 0xa1, 'X','F','8','6','V','i','e','w',0,\n0x6e, 0x2d, 0x10, 0x08, 0xff, 0xa2, 'X','F','8','6','T','o','p','M','e','n','u',0,\n0x26, 0x66, 0x10, 0x08, 0xff, 0xa3, 'X','F','8','6','R','e','d',0,\n0x9a, 0x8c, 0x10, 0x08, 0xff, 0xa4, 'X','F','8','6','G','r','e','e','n',0,\n0x37, 0x55, 0x10, 0x08, 0xff, 0xa5, 'X','F','8','6','Y','e','l','l','o','w',0,\n0x4c, 0xef, 0x10, 0x08, 0xff, 0xa6, 'X','F','8','6','B','l','u','e',0,\n0x6f, 0xe4, 0x10, 0x08, 0xff, 0xa7, 'X','F','8','6','S','u','s','p','e','n','d',0,\n0xab, 0x01, 0x10, 0x08, 0xff, 0xa8, 'X','F','8','6','H','i','b','e','r','n','a','t','e',0,\n0xc5, 0x01, 0x10, 0x08, 0xff, 0xa9, 'X','F','8','6','T','o','u','c','h','p','a','d','T','o','g','g','l','e',0,\n0x7b, 0xe4, 0x10, 0x08, 0xff, 0xb0, 'X','F','8','6','T','o','u','c','h','p','a','d','O','n',0,\n0xf8, 0x1e, 0x10, 0x08, 0xff, 0xb1, 'X','F','8','6','T','o','u','c','h','p','a','d','O','f','f',0,\n0x50, 0x99, 0x10, 0x08, 0xff, 0xb2, 'X','F','8','6','A','u','d','i','o','M','i','c','M','u','t','e',0,\n0xd8, 0x44, 0x10, 0x08, 0xff, 0xb3, 'X','F','8','6','K','e','y','b','o','a','r','d',0,\n0x4c, 0xc4, 0x10, 0x08, 0xff, 0xb4, 'X','F','8','6','W','W','A','N',0,\n0x33, 0x60, 0x10, 0x08, 0xff, 0xb5, 'X','F','8','6','R','F','K','i','l','l',0,\n0xa9, 0x92, 0x10, 0x08, 0xff, 0xb6, 'X','F','8','6','A','u','d','i','o','P','r','e','s','e','t',0,\n0xea, 0xc1, 0x10, 0x08, 0xff, 0xb7, 'X','F','8','6','R','o','t','a','t','i','o','n','L','o','c','k','T','o','g','g','l','e',0,\n0x60, 0xec, 0x10, 0x08, 0xff, 0xb8, 'X','F','8','6','F','u','l','l','S','c','r','e','e','n',0,\n0xfd, 0x9f, 0x10, 0x08, 0xfe, 0x01, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','1',0,\n0xfd, 0xa0, 0x10, 0x08, 0xfe, 0x02, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','2',0,\n0xfd, 0xa1, 0x10, 0x08, 0xfe, 0x03, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','3',0,\n0xfd, 0xa2, 0x10, 0x08, 0xfe, 0x04, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','4',0,\n0xfd, 0xa3, 0x10, 0x08, 0xfe, 0x05, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','5',0,\n0xfd, 0xa4, 0x10, 0x08, 0xfe, 0x06, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','6',0,\n0xfd, 0xa5, 0x10, 0x08, 0xfe, 0x07, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','7',0,\n0xfd, 0xa6, 0x10, 0x08, 0xfe, 0x08, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','8',0,\n0xfd, 0xa7, 0x10, 0x08, 0xfe, 0x09, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','9',0,\n0xfb, 0x6e, 0x10, 0x08, 0xfe, 0x0a, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','1','0',0,\n0xfb, 0x6f, 0x10, 0x08, 0xfe, 0x0b, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','1','1',0,\n0xfb, 0x70, 0x10, 0x08, 0xfe, 0x0c, 'X','F','8','6','S','w','i','t','c','h','_','V','T','_','1','2',0,\n0x37, 0x24, 0x10, 0x08, 0xfe, 0x20, 'X','F','8','6','U','n','g','r','a','b',0,\n0xa6, 0xa4, 0x10, 0x08, 0xfe, 0x21, 'X','F','8','6','C','l','e','a','r','G','r','a','b',0,\n0x68, 0x91, 0x10, 0x08, 0xfe, 0x22, 'X','F','8','6','N','e','x','t','_','V','M','o','d','e',0,\n0x70, 0x91, 0x10, 0x08, 0xfe, 0x23, 'X','F','8','6','P','r','e','v','_','V','M','o','d','e',0,\n0x15, 0xe7, 0x10, 0x08, 0xfe, 0x24, 'X','F','8','6','L','o','g','W','i','n','d','o','w','T','r','e','e',0,\n0xbc, 0x7b, 0x10, 0x08, 0xfe, 0x25, 'X','F','8','6','L','o','g','G','r','a','b','I','n','f','o',0,\n0x73, 0x03, 0x10, 0x08, 0x10, 0xf4, 'X','F','8','6','B','r','i','g','h','t','n','e','s','s','A','u','t','o',0,\n0x58, 0x46, 0x10, 0x08, 0x10, 0xf5, 'X','F','8','6','D','i','s','p','l','a','y','O','f','f',0,\n0x4d, 0x1b, 0x10, 0x08, 0x11, 0x66, 'X','F','8','6','I','n','f','o',0,\n0xae, 0xf9, 0x10, 0x08, 0x11, 0x77, 'X','F','8','6','A','s','p','e','c','t','R','a','t','i','o',0,\n0x25, 0xf0, 0x10, 0x08, 0x11, 0x85, 'X','F','8','6','D','V','D',0,\n0x9a, 0x49, 0x10, 0x08, 0x11, 0x88, 'X','F','8','6','A','u','d','i','o',0,\n0xa5, 0xd2, 0x10, 0x08, 0x11, 0x92, 'X','F','8','6','C','h','a','n','n','e','l','U','p',0,\n0x98, 0x18, 0x10, 0x08, 0x11, 0x93, 'X','F','8','6','C','h','a','n','n','e','l','D','o','w','n',0,\n0x9a, 0x31, 0x10, 0x08, 0x11, 0x9b, 'X','F','8','6','B','r','e','a','k',0,\n0x71, 0x5d, 0x10, 0x08, 0x11, 0xa0, 'X','F','8','6','V','i','d','e','o','P','h','o','n','e',0,\n0xc2, 0x32, 0x10, 0x08, 0x11, 0xa4, 'X','F','8','6','Z','o','o','m','R','e','s','e','t',0,\n0x34, 0xc8, 0x10, 0x08, 0x11, 0xa6, 'X','F','8','6','E','d','i','t','o','r',0,\n0xe4, 0x88, 0x10, 0x08, 0x11, 0xa8, 'X','F','8','6','G','r','a','p','h','i','c','s','E','d','i','t','o','r',0,\n0xce, 0x20, 0x10, 0x08, 0x11, 0xa9, 'X','F','8','6','P','r','e','s','e','n','t','a','t','i','o','n',0,\n0xd2, 0xaf, 0x10, 0x08, 0x11, 0xaa, 'X','F','8','6','D','a','t','a','b','a','s','e',0,\n0xbc, 0x9a, 0x10, 0x08, 0x11, 0xac, 'X','F','8','6','V','o','i','c','e','m','a','i','l',0,\n0x8d, 0xe5, 0x10, 0x08, 0x11, 0xad, 'X','F','8','6','A','d','d','r','e','s','s','b','o','o','k',0,\n0xc6, 0x41, 0x10, 0x08, 0x11, 0xaf, 'X','F','8','6','D','i','s','p','l','a','y','T','o','g','g','l','e',0,\n0x73, 0x35, 0x10, 0x08, 0x11, 0xb0, 'X','F','8','6','S','p','e','l','l','C','h','e','c','k',0,\n0xb6, 0xcd, 0x10, 0x08, 0x11, 0xb6, 'X','F','8','6','C','o','n','t','e','x','t','M','e','n','u',0,\n0xb5, 0x9a, 0x10, 0x08, 0x11, 0xb7, 'X','F','8','6','M','e','d','i','a','R','e','p','e','a','t',0,\n0x7c, 0x56, 0x10, 0x08, 0x11, 0xb8, 'X','F','8','6','1','0','C','h','a','n','n','e','l','s','U','p',0,\n0xf2, 0x28, 0x10, 0x08, 0x11, 0xb9, 'X','F','8','6','1','0','C','h','a','n','n','e','l','s','D','o','w','n',0,\n0x35, 0x51, 0x10, 0x08, 0x11, 0xba, 'X','F','8','6','I','m','a','g','e','s',0,\n0xe5, 0x2c, 0x10, 0x08, 0x11, 0xbc, 'X','F','8','6','N','o','t','i','f','i','c','a','t','i','o','n','C','e','n','t','e','r',0,\n0xd0, 0xfd, 0x10, 0x08, 0x11, 0xbd, 'X','F','8','6','P','i','c','k','u','p','P','h','o','n','e',0,\n0xa9, 0xfd, 0x10, 0x08, 0x11, 0xbe, 'X','F','8','6','H','a','n','g','u','p','P','h','o','n','e',0,\n0x12, 0xf2, 0x10, 0x08, 0x11, 0xd0, 'X','F','8','6','F','n',0,\n0x34, 0x75, 0x10, 0x08, 0x11, 0xd1, 'X','F','8','6','F','n','_','E','s','c',0,\n0x3c, 0x54, 0x10, 0x08, 0x11, 0xe5, 'X','F','8','6','F','n','R','i','g','h','t','S','h','i','f','t',0,\n0xdc, 0x5a, 0x10, 0x08, 0x12, 0x00, 'X','F','8','6','N','u','m','e','r','i','c','0',0,\n0xdc, 0x5b, 0x10, 0x08, 0x12, 0x01, 'X','F','8','6','N','u','m','e','r','i','c','1',0,\n0xdc, 0x5c, 0x10, 0x08, 0x12, 0x02, 'X','F','8','6','N','u','m','e','r','i','c','2',0,\n0xdc, 0x5d, 0x10, 0x08, 0x12, 0x03, 'X','F','8','6','N','u','m','e','r','i','c','3',0,\n0xdc, 0x5e, 0x10, 0x08, 0x12, 0x04, 'X','F','8','6','N','u','m','e','r','i','c','4',0,\n0xdc, 0x5f, 0x10, 0x08, 0x12, 0x05, 'X','F','8','6','N','u','m','e','r','i','c','5',0,\n0xdc, 0x60, 0x10, 0x08, 0x12, 0x06, 'X','F','8','6','N','u','m','e','r','i','c','6',0,\n0xdc, 0x61, 0x10, 0x08, 0x12, 0x07, 'X','F','8','6','N','u','m','e','r','i','c','7',0,\n0xdc, 0x62, 0x10, 0x08, 0x12, 0x08, 'X','F','8','6','N','u','m','e','r','i','c','8',0,\n0xdc, 0x63, 0x10, 0x08, 0x12, 0x09, 'X','F','8','6','N','u','m','e','r','i','c','9',0,\n0xe6, 0xec, 0x10, 0x08, 0x12, 0x0a, 'X','F','8','6','N','u','m','e','r','i','c','S','t','a','r',0,\n0xce, 0x2c, 0x10, 0x08, 0x12, 0x0b, 'X','F','8','6','N','u','m','e','r','i','c','P','o','u','n','d',0,\n0xdc, 0x6b, 0x10, 0x08, 0x12, 0x0c, 'X','F','8','6','N','u','m','e','r','i','c','A',0,\n0xdc, 0x6c, 0x10, 0x08, 0x12, 0x0d, 'X','F','8','6','N','u','m','e','r','i','c','B',0,\n0xdc, 0x6d, 0x10, 0x08, 0x12, 0x0e, 'X','F','8','6','N','u','m','e','r','i','c','C',0,\n0xdc, 0x6e, 0x10, 0x08, 0x12, 0x0f, 'X','F','8','6','N','u','m','e','r','i','c','D',0,\n0x90, 0xe1, 0x10, 0x08, 0x12, 0x10, 'X','F','8','6','C','a','m','e','r','a','F','o','c','u','s',0,\n0xa6, 0x0c, 0x10, 0x08, 0x12, 0x11, 'X','F','8','6','W','P','S','B','u','t','t','o','n',0,\n0x24, 0x9c, 0x10, 0x08, 0x12, 0x15, 'X','F','8','6','C','a','m','e','r','a','Z','o','o','m','I','n',0,\n0x49, 0xd2, 0x10, 0x08, 0x12, 0x16, 'X','F','8','6','C','a','m','e','r','a','Z','o','o','m','O','u','t',0,\n0xd1, 0xde, 0x10, 0x08, 0x12, 0x17, 'X','F','8','6','C','a','m','e','r','a','U','p',0,\n0x48, 0x48, 0x10, 0x08, 0x12, 0x18, 'X','F','8','6','C','a','m','e','r','a','D','o','w','n',0,\n0x48, 0x44, 0x10, 0x08, 0x12, 0x19, 'X','F','8','6','C','a','m','e','r','a','L','e','f','t',0,\n0x91, 0x68, 0x10, 0x08, 0x12, 0x1a, 'X','F','8','6','C','a','m','e','r','a','R','i','g','h','t',0,\n0xb6, 0xdc, 0x10, 0x08, 0x12, 0x1b, 'X','F','8','6','A','t','t','e','n','d','a','n','t','O','n',0,\n0x6e, 0x0e, 0x10, 0x08, 0x12, 0x1c, 'X','F','8','6','A','t','t','e','n','d','a','n','t','O','f','f',0,\n0x74, 0x81, 0x10, 0x08, 0x12, 0x1d, 'X','F','8','6','A','t','t','e','n','d','a','n','t','T','o','g','g','l','e',0,\n0x88, 0x41, 0x10, 0x08, 0x12, 0x1e, 'X','F','8','6','L','i','g','h','t','s','T','o','g','g','l','e',0,\n0x8f, 0x41, 0x10, 0x08, 0x12, 0x30, 'X','F','8','6','A','L','S','T','o','g','g','l','e',0,\n0x8c, 0x91, 0x10, 0x08, 0x12, 0x40, 'X','F','8','6','B','u','t','t','o','n','c','o','n','f','i','g',0,\n0xde, 0xa0, 0x10, 0x08, 0x12, 0x41, 'X','F','8','6','T','a','s','k','m','a','n','a','g','e','r',0,\n0x6d, 0x26, 0x10, 0x08, 0x12, 0x42, 'X','F','8','6','J','o','u','r','n','a','l',0,\n0x71, 0x36, 0x10, 0x08, 0x12, 0x43, 'X','F','8','6','C','o','n','t','r','o','l','P','a','n','e','l',0,\n0xa7, 0xde, 0x10, 0x08, 0x12, 0x44, 'X','F','8','6','A','p','p','S','e','l','e','c','t',0,\n0xda, 0xcc, 0x10, 0x08, 0x12, 0x45, 'X','F','8','6','S','c','r','e','e','n','s','a','v','e','r',0,\n0xdf, 0x1c, 0x10, 0x08, 0x12, 0x46, 'X','F','8','6','V','o','i','c','e','C','o','m','m','a','n','d',0,\n0xae, 0x04, 0x10, 0x08, 0x12, 0x47, 'X','F','8','6','A','s','s','i','s','t','a','n','t',0,\n0xb2, 0xd0, 0x10, 0x08, 0x12, 0x49, 'X','F','8','6','E','m','o','j','i','P','i','c','k','e','r',0,\n0x69, 0xc1, 0x10, 0x08, 0x12, 0x4a, 'X','F','8','6','D','i','c','t','a','t','e',0,\n0x3a, 0x8d, 0x10, 0x08, 0x12, 0x4b, 'X','F','8','6','C','a','m','e','r','a','A','c','c','e','s','s','E','n','a','b','l','e',0,\n0x75, 0x9d, 0x10, 0x08, 0x12, 0x4c, 'X','F','8','6','C','a','m','e','r','a','A','c','c','e','s','s','D','i','s','a','b','l','e',0,\n0x3c, 0xc1, 0x10, 0x08, 0x12, 0x4d, 'X','F','8','6','C','a','m','e','r','a','A','c','c','e','s','s','T','o','g','g','l','e',0,\n0xb9, 0x5c, 0x10, 0x08, 0x12, 0x50, 'X','F','8','6','B','r','i','g','h','t','n','e','s','s','M','i','n',0,\n0xb9, 0x56, 0x10, 0x08, 0x12, 0x51, 'X','F','8','6','B','r','i','g','h','t','n','e','s','s','M','a','x',0,\n0xdb, 0xe8, 0x10, 0x08, 0x12, 0x60, 'X','F','8','6','K','b','d','I','n','p','u','t','A','s','s','i','s','t','P','r','e','v',0,\n0xdb, 0xc8, 0x10, 0x08, 0x12, 0x61, 'X','F','8','6','K','b','d','I','n','p','u','t','A','s','s','i','s','t','N','e','x','t',0,\n0x8a, 0x16, 0x10, 0x08, 0x12, 0x62, 'X','F','8','6','K','b','d','I','n','p','u','t','A','s','s','i','s','t','P','r','e','v','g','r','o','u','p',0,\n0x86, 0x16, 0x10, 0x08, 0x12, 0x63, 'X','F','8','6','K','b','d','I','n','p','u','t','A','s','s','i','s','t','N','e','x','t','g','r','o','u','p',0,\n0x6d, 0xd0, 0x10, 0x08, 0x12, 0x64, 'X','F','8','6','K','b','d','I','n','p','u','t','A','s','s','i','s','t','A','c','c','e','p','t',0,\n0x6e, 0x22, 0x10, 0x08, 0x12, 0x65, 'X','F','8','6','K','b','d','I','n','p','u','t','A','s','s','i','s','t','C','a','n','c','e','l',0,\n0x6d, 0x3a, 0x10, 0x08, 0x12, 0x66, 'X','F','8','6','R','i','g','h','t','U','p',0,\n0xb5, 0xb8, 0x10, 0x08, 0x12, 0x67, 'X','F','8','6','R','i','g','h','t','D','o','w','n',0,\n0x35, 0x6a, 0x10, 0x08, 0x12, 0x68, 'X','F','8','6','L','e','f','t','U','p',0,\n0xd6, 0x78, 0x10, 0x08, 0x12, 0x69, 'X','F','8','6','L','e','f','t','D','o','w','n',0,\n0xdd, 0x2d, 0x10, 0x08, 0x12, 0x6a, 'X','F','8','6','R','o','o','t','M','e','n','u',0,\n0x6c, 0xad, 0x10, 0x08, 0x12, 0x6b, 'X','F','8','6','M','e','d','i','a','T','o','p','M','e','n','u',0,\n0xb8, 0xe7, 0x10, 0x08, 0x12, 0x6c, 'X','F','8','6','N','u','m','e','r','i','c','1','1',0,\n0xb8, 0xe8, 0x10, 0x08, 0x12, 0x6d, 'X','F','8','6','N','u','m','e','r','i','c','1','2',0,\n0xa9, 0x8d, 0x10, 0x08, 0x12, 0x6e, 'X','F','8','6','A','u','d','i','o','D','e','s','c',0,\n0x2f, 0x71, 0x10, 0x08, 0x12, 0x6f, 'X','F','8','6','3','D','M','o','d','e',0,\n0x9f, 0x71, 0x10, 0x08, 0x12, 0x70, 'X','F','8','6','N','e','x','t','F','a','v','o','r','i','t','e',0,\n0x7c, 0x2c, 0x10, 0x08, 0x12, 0x71, 'X','F','8','6','S','t','o','p','R','e','c','o','r','d',0,\n0xd0, 0x6c, 0x10, 0x08, 0x12, 0x72, 'X','F','8','6','P','a','u','s','e','R','e','c','o','r','d',0,\n0x26, 0x2a, 0x10, 0x08, 0x12, 0x73, 'X','F','8','6','V','O','D',0,\n0x37, 0x89, 0x10, 0x08, 0x12, 0x74, 'X','F','8','6','U','n','m','u','t','e',0,\n0xa5, 0xbb, 0x10, 0x08, 0x12, 0x75, 'X','F','8','6','F','a','s','t','R','e','v','e','r','s','e',0,\n0xed, 0x3b, 0x10, 0x08, 0x12, 0x76, 'X','F','8','6','S','l','o','w','R','e','v','e','r','s','e',0,\n0x4c, 0xcd, 0x10, 0x08, 0x12, 0x77, 'X','F','8','6','D','a','t','a',0,\n0x46, 0x44, 0x10, 0x08, 0x12, 0x78, 'X','F','8','6','O','n','S','c','r','e','e','n','K','e','y','b','o','a','r','d',0,\n0x02, 0x81, 0x10, 0x08, 0x12, 0x79, 'X','F','8','6','P','r','i','v','a','c','y','S','c','r','e','e','n','T','o','g','g','l','e',0,\n0x09, 0x4a, 0x10, 0x08, 0x12, 0x7a, 'X','F','8','6','S','e','l','e','c','t','i','v','e','S','c','r','e','e','n','s','h','o','t',0,\n0xcf, 0x5c, 0x10, 0x08, 0x12, 0x7b, 'X','F','8','6','N','e','x','t','E','l','e','m','e','n','t',0,\n0x9b, 0xdc, 0x10, 0x08, 0x12, 0x7c, 'X','F','8','6','P','r','e','v','i','o','u','s','E','l','e','m','e','n','t',0,\n0x13, 0x41, 0x10, 0x08, 0x12, 0x7d, 'X','F','8','6','A','u','t','o','p','i','l','o','t','E','n','g','a','g','e','T','o','g','g','l','e',0,\n0x7b, 0x4c, 0x10, 0x08, 0x12, 0x7e, 'X','F','8','6','M','a','r','k','W','a','y','p','o','i','n','t',0,\n0x26, 0x8d, 0x10, 0x08, 0x12, 0x7f, 'X','F','8','6','S','o','s',0,\n0xd6, 0x4c, 0x10, 0x08, 0x12, 0x80, 'X','F','8','6','N','a','v','C','h','a','r','t',0,\n0x69, 0x2c, 0x10, 0x08, 0x12, 0x81, 'X','F','8','6','F','i','s','h','i','n','g','C','h','a','r','t',0,\n0x51, 0x4c, 0x10, 0x08, 0x12, 0x82, 'X','F','8','6','S','i','n','g','l','e','R','a','n','g','e','R','a','d','a','r',0,\n0x75, 0x4c, 0x10, 0x08, 0x12, 0x83, 'X','F','8','6','D','u','a','l','R','a','n','g','e','R','a','d','a','r',0,\n0x85, 0x4b, 0x10, 0x08, 0x12, 0x84, 'X','F','8','6','R','a','d','a','r','O','v','e','r','l','a','y',0,\n0xa1, 0x54, 0x10, 0x08, 0x12, 0x85, 'X','F','8','6','T','r','a','d','i','t','i','o','n','a','l','S','o','n','a','r',0,\n0x43, 0xb4, 0x10, 0x08, 0x12, 0x86, 'X','F','8','6','C','l','e','a','r','v','u','S','o','n','a','r',0,\n0xdc, 0x34, 0x10, 0x08, 0x12, 0x87, 'X','F','8','6','S','i','d','e','v','u','S','o','n','a','r',0,\n0x6b, 0x3b, 0x10, 0x08, 0x12, 0x88, 'X','F','8','6','N','a','v','I','n','f','o',0,\n0x35, 0x1f, 0x10, 0x08, 0x12, 0x90, 'X','F','8','6','M','a','c','r','o','1',0,\n0x35, 0x20, 0x10, 0x08, 0x12, 0x91, 'X','F','8','6','M','a','c','r','o','2',0,\n0x35, 0x21, 0x10, 0x08, 0x12, 0x92, 'X','F','8','6','M','a','c','r','o','3',0,\n0x35, 0x22, 0x10, 0x08, 0x12, 0x93, 'X','F','8','6','M','a','c','r','o','4',0,\n0x35, 0x23, 0x10, 0x08, 0x12, 0x94, 'X','F','8','6','M','a','c','r','o','5',0,\n0x35, 0x24, 0x10, 0x08, 0x12, 0x95, 'X','F','8','6','M','a','c','r','o','6',0,\n0x35, 0x25, 0x10, 0x08, 0x12, 0x96, 'X','F','8','6','M','a','c','r','o','7',0,\n0x35, 0x26, 0x10, 0x08, 0x12, 0x97, 'X','F','8','6','M','a','c','r','o','8',0,\n0x35, 0x27, 0x10, 0x08, 0x12, 0x98, 'X','F','8','6','M','a','c','r','o','9',0,\n0x6a, 0x6e, 0x10, 0x08, 0x12, 0x99, 'X','F','8','6','M','a','c','r','o','1','0',0,\n0x6a, 0x6f, 0x10, 0x08, 0x12, 0x9a, 'X','F','8','6','M','a','c','r','o','1','1',0,\n0x6a, 0x70, 0x10, 0x08, 0x12, 0x9b, 'X','F','8','6','M','a','c','r','o','1','2',0,\n0x6a, 0x71, 0x10, 0x08, 0x12, 0x9c, 'X','F','8','6','M','a','c','r','o','1','3',0,\n0x6a, 0x72, 0x10, 0x08, 0x12, 0x9d, 'X','F','8','6','M','a','c','r','o','1','4',0,\n0x6a, 0x73, 0x10, 0x08, 0x12, 0x9e, 'X','F','8','6','M','a','c','r','o','1','5',0,\n0x6a, 0x74, 0x10, 0x08, 0x12, 0x9f, 'X','F','8','6','M','a','c','r','o','1','6',0,\n0x6a, 0x75, 0x10, 0x08, 0x12, 0xa0, 'X','F','8','6','M','a','c','r','o','1','7',0,\n0x6a, 0x76, 0x10, 0x08, 0x12, 0xa1, 'X','F','8','6','M','a','c','r','o','1','8',0,\n0x6a, 0x77, 0x10, 0x08, 0x12, 0xa2, 'X','F','8','6','M','a','c','r','o','1','9',0,\n0x6a, 0x70, 0x10, 0x08, 0x12, 0xa3, 'X','F','8','6','M','a','c','r','o','2','0',0,\n0x6a, 0x71, 0x10, 0x08, 0x12, 0xa4, 'X','F','8','6','M','a','c','r','o','2','1',0,\n0x6a, 0x72, 0x10, 0x08, 0x12, 0xa5, 'X','F','8','6','M','a','c','r','o','2','2',0,\n0x6a, 0x73, 0x10, 0x08, 0x12, 0xa6, 'X','F','8','6','M','a','c','r','o','2','3',0,\n0x6a, 0x74, 0x10, 0x08, 0x12, 0xa7, 'X','F','8','6','M','a','c','r','o','2','4',0,\n0x6a, 0x75, 0x10, 0x08, 0x12, 0xa8, 'X','F','8','6','M','a','c','r','o','2','5',0,\n0x6a, 0x76, 0x10, 0x08, 0x12, 0xa9, 'X','F','8','6','M','a','c','r','o','2','6',0,\n0x6a, 0x77, 0x10, 0x08, 0x12, 0xaa, 'X','F','8','6','M','a','c','r','o','2','7',0,\n0x6a, 0x78, 0x10, 0x08, 0x12, 0xab, 'X','F','8','6','M','a','c','r','o','2','8',0,\n0x6a, 0x79, 0x10, 0x08, 0x12, 0xac, 'X','F','8','6','M','a','c','r','o','2','9',0,\n0x6a, 0x72, 0x10, 0x08, 0x12, 0xad, 'X','F','8','6','M','a','c','r','o','3','0',0,\n0x99, 0x2c, 0x10, 0x08, 0x12, 0xb0, 'X','F','8','6','M','a','c','r','o','R','e','c','o','r','d','S','t','a','r','t',0,\n0x4c, 0x76, 0x10, 0x08, 0x12, 0xb1, 'X','F','8','6','M','a','c','r','o','R','e','c','o','r','d','S','t','o','p',0,\n0xad, 0x01, 0x10, 0x08, 0x12, 0xb2, 'X','F','8','6','M','a','c','r','o','P','r','e','s','e','t','C','y','c','l','e',0,\n0x6a, 0x55, 0x10, 0x08, 0x12, 0xb3, 'X','F','8','6','M','a','c','r','o','P','r','e','s','e','t','1',0,\n0x6a, 0x56, 0x10, 0x08, 0x12, 0xb4, 'X','F','8','6','M','a','c','r','o','P','r','e','s','e','t','2',0,\n0x6a, 0x57, 0x10, 0x08, 0x12, 0xb5, 'X','F','8','6','M','a','c','r','o','P','r','e','s','e','t','3',0,\n0x9a, 0x0b, 0x10, 0x08, 0x12, 0xb8, 'X','F','8','6','K','b','d','L','c','d','M','e','n','u','1',0,\n0x9a, 0x0c, 0x10, 0x08, 0x12, 0xb9, 'X','F','8','6','K','b','d','L','c','d','M','e','n','u','2',0,\n0x9a, 0x0d, 0x10, 0x08, 0x12, 0xba, 'X','F','8','6','K','b','d','L','c','d','M','e','n','u','3',0,\n0x9a, 0x0e, 0x10, 0x08, 0x12, 0xbb, 'X','F','8','6','K','b','d','L','c','d','M','e','n','u','4',0,\n0x9a, 0x0f, 0x10, 0x08, 0x12, 0xbc, 'X','F','8','6','K','b','d','L','c','d','M','e','n','u','5',0\n};\n\n#define KTABLESIZE 3927\n#define KMAXHASH 13\n\nstatic const unsigned short hashString[KTABLESIZE] = {\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2bfb, 0x9ee0, 0x0000,\n0x579e, 0x5885, 0x0dbc, 0x9f46, 0x0000, 0x0000, 0x9db3, 0x0000,\n0xa492, 0xa10d, 0x0d64, 0x0dcc, 0x0000, 0x0860, 0x0000, 0x2ba7,\n0x0165, 0x0000, 0x774f, 0x086e, 0x5690, 0x64a2, 0x5b79, 0x0cc8,\n0x1610, 0x0000, 0x23b6, 0x01eb, 0x0000, 0x0000, 0x0000, 0x0000,\n0x5670, 0x2b6f, 0x0000, 0x357a, 0x0000, 0x0000, 0x0000, 0x2c41,\n0x17a7, 0x17af, 0x17b7, 0x17bf, 0x17c7, 0x17cf, 0x17d7, 0x1010,\n0x17e7, 0x17ef, 0x635d, 0x66ac, 0xa06a, 0x61db, 0x0000, 0x5a19,\n0x0000, 0x1850, 0x1858, 0x1860, 0x1868, 0x0e70, 0x1878, 0x1880,\n0x1888, 0x1890, 0x1898, 0x18a0, 0x18a8, 0x18b0, 0x18b8, 0x18c0,\n0x18c8, 0x18d0, 0x18d8, 0x0fff, 0x18e8, 0x07b5, 0x18f8, 0x1900,\n0x1908, 0x1910, 0x1918, 0x07c3, 0x0000, 0x0000, 0x6345, 0x0c56,\n0x07f1, 0x1994, 0x199c, 0x19a4, 0x19ac, 0x19b4, 0x1021, 0x19c4,\n0x19cc, 0x19d4, 0x19dc, 0x19e4, 0x19ec, 0x19f4, 0x19fc, 0x17df,\n0x1a0c, 0x1a14, 0x1a1c, 0x1a24, 0x1a2c, 0x1a34, 0x1a3c, 0x1a44,\n0x1a4c, 0x1a54, 0x1a5c, 0x944c, 0x53c8, 0x5ef3, 0x0000, 0x0000,\n0x9d8b, 0x6f06, 0x869d, 0x572d, 0x0000, 0x9ae4, 0x6069, 0x61fa,\n0x2803, 0xa08b, 0x291d, 0x1870, 0xa7d3, 0x2609, 0x0000, 0x586c,\n0x0000, 0x1e47, 0x9c4c, 0x9469, 0x57c2, 0x76c1, 0x0000, 0x0000,\n0xaf73, 0x65db, 0x0cd9, 0x0000, 0x9346, 0x9c70, 0x57f8, 0x0000,\n0x0000, 0x28e9, 0x9179, 0x9ba9, 0x2813, 0x9410, 0x916b, 0x18e0,\n0x93e5, 0x0000, 0x8e14, 0x18f0, 0x9225, 0x0000, 0x24a4, 0x96a5,\n0x939c, 0x44a4, 0x90fb, 0x98c6, 0x930b, 0x9b35, 0x0000, 0x0000,\n0x9329, 0x0000, 0x909a, 0x0000, 0x938e, 0x0578, 0x0581, 0x058a,\n0x0593, 0x059c, 0x05a5, 0x05ae, 0x05b7, 0x05c0, 0x5b3c, 0x1d2e,\n0x9806, 0x05dd, 0x05f0, 0x0603, 0x0616, 0x0629, 0x063c, 0x064f,\n0x0662, 0x0675, 0x8ae5, 0x0000, 0x7048, 0x069c, 0x06af, 0x06c2,\n0x06d5, 0x06e8, 0x06fb, 0x070e, 0x0721, 0x0734, 0x0000, 0x1a04,\n0x3e7c, 0x2398, 0x624d, 0x00ba, 0x0000, 0x4a89, 0x3d87, 0x9495,\n0x0000, 0x9e55, 0x0000, 0x0000, 0x0000, 0xa291, 0x1457, 0x088b,\n0x0cb6, 0x9b25, 0xab21, 0x90a8, 0x0000, 0x0000, 0x0000, 0x9922,\n0x3715, 0x0000, 0x0000, 0x6f2a, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x8d4f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0e04,\n0x392c, 0x0000, 0x49c9, 0x0000, 0x0000, 0x4f36, 0x3c52, 0x94c1,\n0x3951, 0x0a6c, 0x0000, 0x036a, 0x5828, 0x7316, 0x7338, 0x266e,\n0x7621, 0x0000, 0x0255, 0x0000, 0x3e43, 0x71a2, 0x0000, 0x0000,\n0x0000, 0x0000, 0x20ba, 0x0000, 0x4cbe, 0x0000, 0x126a, 0x1280,\n0x1296, 0x12ac, 0x12c2, 0x0001, 0x9b86, 0x75fa, 0x144e, 0x08b9,\n0x0000, 0x8911, 0x4876, 0x5cbe, 0x19bc, 0x90c3, 0x1847, 0x4a64,\n0x487f, 0x0000, 0x202a, 0x0000, 0x3de0, 0x90d1, 0x4888, 0x0000,\n0x0000, 0x0000, 0x0000, 0x28ac, 0x22a6, 0xaca3, 0x0000, 0x0000,\n0x4891, 0x5942, 0x0000, 0x0000, 0x0000, 0x91cd, 0x0000, 0x1bf7,\n0xa87d, 0x0000, 0x010c, 0x9762, 0x272f, 0x55f4, 0x0000, 0x00d0,\n0x3ebf, 0x4c41, 0x3a45, 0x0000, 0x0000, 0x3d1c, 0x0000, 0xa4bf,\n0x4030, 0x9ffa, 0x3a8e, 0x0000, 0x0000, 0x9363, 0x941e, 0x0000,\n0x7647, 0x0000, 0x49d8, 0xa36e, 0x6415, 0x9545, 0x1221, 0x0000,\n0x3afd, 0x0000, 0x0000, 0x7569, 0x0000, 0x0000, 0x94b2, 0x0000,\n0x33b4, 0x0000, 0x0000, 0x5709, 0x0000, 0x168d, 0x94a3, 0xa175,\n0x9e96, 0x5260, 0x9e84, 0x0fad, 0x6cce, 0x48f3, 0x0000, 0x5a62,\n0x2823, 0x174b, 0x0000, 0x84f6, 0x0000, 0x2793, 0x94de, 0x45bc,\n0x0000, 0x8552, 0x0000, 0x5604, 0x800e, 0x9380, 0x945a, 0x860e,\n0x0000, 0xaa30, 0x0da8, 0x1b35, 0x0000, 0x1460, 0x0000, 0x4a99,\n0x3540, 0x90df, 0x0000, 0x863d, 0x0000, 0x0000, 0x737a, 0x928f,\n0x0000, 0x87bd, 0x05c9, 0x05d3, 0x05e6, 0x05f9, 0x060c, 0x061f,\n0x0632, 0x0645, 0x0658, 0x066b, 0x0717, 0x072a, 0x0000, 0x0000,\n0x983a, 0x55ab, 0x94cf, 0x91db, 0x1bd7, 0x08a2, 0x82e1, 0x2783,\n0x3c27, 0x3257, 0x0688, 0xabd7, 0x27b3, 0x0000, 0x4d3a, 0x28a3,\n0x0000, 0x0d52, 0xa0fa, 0x5287, 0x0000, 0x8835, 0x10a1, 0x0000,\n0x3a7b, 0x0000, 0x9486, 0x70d6, 0x738b, 0x91f9, 0x4b65, 0x93f3,\n0xa5c6, 0x38c1, 0x0747, 0x075b, 0x076f, 0x0783, 0x0797, 0x07ab,\n0x0000, 0x3289, 0x9d7b, 0x92ae, 0xa652, 0x549e, 0x2889, 0x0d02,\n0x376e, 0x54f9, 0x364d, 0x93b8, 0x0000, 0x0000, 0x9402, 0x92cd,\n0x2653, 0x3fa1, 0x1967, 0x7547, 0x0000, 0x0000, 0x0000, 0x0b89,\n0x0000, 0x3703, 0x0000, 0x0000, 0x3bee, 0x4b2d, 0x0000, 0x0000,\n0x9fa0, 0x48df, 0x0000, 0x1e70, 0x1dc0, 0x63a5, 0x2661, 0x9270,\n0x0000, 0x0000, 0x0000, 0x0000, 0x91a2, 0x0000, 0x0000, 0x0000,\n0x6d8c, 0x7274, 0x147d, 0x75d2, 0x4d09, 0x0000, 0x7697, 0x0000,\n0x1aa0, 0x38f7, 0x3a32, 0x9593, 0x3b8b, 0xaa94, 0x0000, 0x0000,\n0x4ede, 0x0000, 0x017d, 0x6f4c, 0x0000, 0x0000, 0x0000, 0x998f,\n0x0000, 0x0000, 0x99a1, 0x530d, 0x302d, 0x99b3, 0x0000, 0x5324,\n0x0000, 0x0000, 0x1473, 0x99d7, 0x0000, 0x1070, 0x72de, 0x0000,\n0x0000, 0x4be9, 0x0000, 0x4df0, 0x715d, 0x08e6, 0x9700, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9e64, 0x0000, 0x0000,\n0xa01a, 0x55e0, 0x0000, 0x9ccc, 0x4104, 0xa049, 0x9124, 0x1f1b,\n0x2f5f, 0x0000, 0x0000, 0xa11c, 0x02aa, 0x0844, 0xacfe, 0x36dd,\n0xad20, 0x3fbc, 0xad42, 0x0852, 0x0000, 0x9a55, 0x0000, 0x0000,\n0x9a67, 0x0000, 0x95f8, 0x9a79, 0x1dca, 0x0000, 0x9a8b, 0x8f5e,\n0x42d5, 0x9a9d, 0x0000, 0x9d1f, 0x4c00, 0x0000, 0x54e6, 0x141a,\n0x0000, 0xa0b8, 0x0000, 0x0000, 0x0022, 0x3c87, 0x0000, 0x0000,\n0xa88f, 0x3739, 0x0000, 0x9208, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x9116, 0x7174, 0x0072, 0x35b6,\n0x0000, 0x486d, 0x38d3, 0x0000, 0x0000, 0x2475, 0x423a, 0x1434,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa9f9, 0x0000,\n0x6e6a, 0x0000, 0x0000, 0x0000, 0x0000, 0xa74a, 0x1edf, 0x0000,\n0x0000, 0x0000, 0x6f70, 0x97c1, 0x4180, 0x0000, 0x0000, 0xa6b4,\n0x23f3, 0x0000, 0x1469, 0x0000, 0x955f, 0x0000, 0x0000, 0x10d4,\n0x0000, 0x46a5, 0x0000, 0x91b0, 0x1a74, 0x0000, 0x0000, 0x0bf8,\n0x9c0a, 0x489a, 0x01af, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x718b, 0x0000, 0x2f9a, 0x9b15, 0x658f, 0x0000, 0x0000, 0x0c8e,\n0x556e, 0x0467, 0x21cc, 0x3e1d, 0x0000, 0x0000, 0x0000, 0x25e3,\n0x5015, 0x0000, 0x0000, 0x0000, 0x578d, 0x3aeb, 0x9be7, 0x27a3,\n0x0000, 0x0000, 0x0e87, 0x0000, 0x1fad, 0x120b, 0x62e5, 0x96b4,\n0x989d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3fd1, 0x0000,\n0x6d96, 0x2519, 0x0000, 0x712e, 0x72ca, 0x554c, 0x0000, 0x9c90,\n0x0000, 0x8374, 0x505e, 0x93d7, 0x3c12, 0x0000, 0x09fa, 0x0000,\n0x0000, 0x9d6c, 0x0000, 0x5173, 0x0000, 0xa18b, 0x0000, 0x0000,\n0x0000, 0x9873, 0x0000, 0x0000, 0x414d, 0x0000, 0x4b9a, 0x0000,\n0x0000, 0xa7fb, 0x569e, 0x9141, 0x0000, 0x71ce, 0x0000, 0x0000,\n0x5617, 0x0000, 0x0000, 0x6f9a, 0x1aed, 0x0000, 0x164b, 0x0000,\n0x0000, 0x0000, 0x95ad, 0x4989, 0x0000, 0x0000, 0x4c18, 0x0000,\n0x0000, 0x58df, 0x64d9, 0x0000, 0x4d7d, 0xaef9, 0x7327, 0x9ca0,\n0xaf89, 0x447d, 0x5525, 0xafcb, 0x0000, 0xab30, 0x0000, 0x563e,\n0x0000, 0x0221, 0x0000, 0x0ddc, 0x4ebe, 0x1192, 0x0000, 0x1d72,\n0x1384, 0x1398, 0x13ac, 0x13c0, 0x13d4, 0x0000, 0x0000, 0x9b72,\n0x0000, 0x0000, 0x0000, 0x74e7, 0x0000, 0x91ea, 0x1b15, 0x1f4d,\n0x0000, 0x0000, 0x56e5, 0xa53f, 0x0000, 0x087c, 0x11ab, 0x4a7a,\n0x71e5, 0x067e, 0x0000, 0x0692, 0x72b6, 0x06a5, 0x0000, 0x06b8,\n0x44f1, 0x06cb, 0x3ed9, 0x06de, 0x0000, 0x06f1, 0x0000, 0x0704,\n0x0000, 0x0000, 0x0000, 0x881d, 0x4626, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x7780, 0x71fc, 0x943c, 0x94ed, 0x8a0b, 0x0dee,\n0x1e2b, 0x0395, 0x7488, 0x8524, 0x0000, 0x0000, 0x0439, 0x0000,\n0x48a3, 0x0000, 0x0000, 0x2d7d, 0x524d, 0x0000, 0x0c46, 0x0496,\n0x72ee, 0x6da0, 0x8160, 0x0000, 0x0000, 0x0000, 0x0000, 0x8760,\n0x0000, 0x0000, 0xa009, 0x1596, 0x0000, 0x0000, 0x74d4, 0x91be,\n0xa973, 0x8a70, 0x0000, 0x5742, 0x0000, 0x5224, 0x8177, 0x5838,\n0x0000, 0xa143, 0x0000, 0x2945, 0x28c6, 0x0000, 0x0000, 0x77d1,\n0x0000, 0x585b, 0x97f5, 0xa58d, 0x4afb, 0x8626, 0x0000, 0x57d5,\n0x87ed, 0x0d74, 0x0000, 0x424a, 0x0000, 0x485a, 0x8afd, 0x9261,\n0x0000, 0x49bb, 0x7349, 0x504f, 0x1238, 0x929e, 0x0000, 0x2698,\n0x553b, 0x0000, 0x1803, 0x3cd0, 0x49f8, 0x5a76, 0x0000, 0x0000,\n0x5c5e, 0x0000, 0xa51c, 0xa439, 0x1c25, 0x92fb, 0x68a3, 0x4adb,\n0x0000, 0x0000, 0x0000, 0x0000, 0xaf9f, 0x0000, 0xaa6f, 0x0000,\n0x4dc2, 0x9f03, 0x6929, 0x0000, 0x33ee, 0xaa83, 0x0000, 0x24d8,\n0x0000, 0x3793, 0x0000, 0x9132, 0x3f06, 0x0000, 0x0000, 0x0e5b,\n0x0000, 0x465e, 0x0000, 0x0000, 0x0000, 0x0000, 0x6915, 0x25d9,\n0x0000, 0x514c, 0x0000, 0x7146, 0x771e, 0x03fc, 0x0000, 0x3888,\n0x1f8a, 0xa3d1, 0x430c, 0x710e, 0x2cca, 0x0000, 0x6811, 0x0000,\n0x0000, 0xa9e5, 0xab0b, 0x0000, 0xad64, 0x92bd, 0x339d, 0x0000,\n0x3498, 0x0000, 0x8e46, 0x0000, 0x0379, 0x9319, 0x9f8d, 0xa2fd,\n0xae2a, 0x0000, 0x3ab1, 0x50d8, 0xaecc, 0x14fb, 0x6835, 0x267c,\n0x320a, 0xa32b, 0x5c8d, 0x38e4, 0x0000, 0x0000, 0x0000, 0x0000,\n0x1719, 0x0000, 0x6859, 0x565f, 0x9c7f, 0x0000, 0x0000, 0x0000,\n0x0c2e, 0x292e, 0x0000, 0x6469, 0x42b2, 0x0000, 0xa69e, 0x0000,\n0x0000, 0x0419, 0x0000, 0x9dd9, 0x0000, 0x11be, 0x6501, 0x56d4,\n0x0000, 0x50aa, 0x8e5f, 0x3819, 0x9cdd, 0x0000, 0x0000, 0x0000,\n0x0000, 0x4dd8, 0x67a3, 0x6443, 0x9642, 0x4727, 0x648f, 0x0000,\n0x0000, 0x0000, 0x31f7, 0x0000, 0x6603, 0x92dc, 0x4404, 0x664f,\n0x6699, 0x0000, 0x6fc6, 0x0000, 0x65b5, 0x045a, 0x9dfa, 0x36ca,\n0xa280, 0x0000, 0x0000, 0x0000, 0x2ef9, 0x340a, 0x0000, 0x0000,\n0x0000, 0x966a, 0x4e47, 0x0000, 0x0000, 0x5aca, 0x0000, 0x35ca,\n0x677d, 0x0000, 0x9de9, 0x0000, 0x0000, 0x7252, 0x0000, 0x0000,\n0x0000, 0x5597, 0x2ee6, 0xa35e, 0x0000, 0x0388, 0x5073, 0x0000,\n0x2df5, 0x9692, 0x0000, 0x3726, 0x0000, 0x609e, 0x0000, 0x0000,\n0x0000, 0x00aa, 0x3426, 0x687d, 0x3085, 0x52fd, 0x050a, 0x0515,\n0x0520, 0x052b, 0x0536, 0x0541, 0x054c, 0x0557, 0x0562, 0x056d,\n0x68ef, 0x1e82, 0x30b8, 0x0000, 0x9816, 0x0000, 0x0000, 0x0000,\n0x2fe7, 0x0000, 0x0000, 0x4f49, 0x0000, 0x9194, 0x0000, 0x2f2b,\n0x3169, 0x0000, 0x3113, 0x0000, 0x0000, 0x0000, 0x0000, 0xaccb,\n0x32a2, 0xacdc, 0x321d, 0x451f, 0x0000, 0x3124, 0x0000, 0xad0f,\n0x0000, 0x0000, 0x0000, 0x3bc8, 0x0000, 0xa6f7, 0x0000, 0x39d7,\n0x6559, 0x1a64, 0x3102, 0x0000, 0x6df8, 0xaae4, 0x6747, 0x1838,\n0x2dad, 0x0000, 0x6977, 0x0000, 0x4577, 0x0000, 0x0000, 0x9eca,\n0x3096, 0x52ae, 0x6687, 0x0000, 0x0000, 0x0000, 0x0000, 0x97e2,\n0x2fb2, 0x0000, 0x3147, 0x993d, 0x0000, 0x0000, 0x6847, 0xad76,\n0x32b3, 0x52c2, 0x5f58, 0xadbe, 0xadd0, 0xade2, 0x68dd, 0xae06,\n0x30a7, 0xaeba, 0x686b, 0x317a, 0x31a4, 0x0000, 0x2434, 0x0000,\n0x0000, 0x0000, 0x5476, 0x9063, 0x42fb, 0x0000, 0x676b, 0x0000,\n0x2135, 0x0000, 0xab4b, 0xa382, 0x31cb, 0x0000, 0x6513, 0x6036,\n0x765c, 0x5fd6, 0x1b8a, 0x0000, 0x5b51, 0x4b08, 0x0000, 0x40f2,\n0x1541, 0x0000, 0x50e8, 0x6eae, 0x9d56, 0x4115, 0x0000, 0x0000,\n0x67da, 0x0000, 0x303d, 0x2dbe, 0x073d, 0x09c9, 0x0000, 0x0751,\n0x2b7d, 0x0000, 0x0765, 0x34ea, 0x0315, 0x0779, 0x2a46, 0x25af,\n0x078d, 0x0000, 0x2a70, 0x07a1, 0x032d, 0x3061, 0x2a54, 0x01fc,\n0x2b61, 0x9048, 0x2bdf, 0x6456, 0x2a7e, 0x0000, 0x1acf, 0x0000,\n0x2ad3, 0x0000, 0x2a62, 0x0000, 0x2b1b, 0x0000, 0x2bed, 0x6662,\n0x2af0, 0x637c, 0x2c17, 0x0000, 0x024a, 0x0000, 0x2b29, 0x6722,\n0x026a, 0x0000, 0x2aa9, 0x023f, 0x295a, 0x6ef4, 0x5e82, 0x0000,\n0x2c33, 0x331e, 0x4209, 0x41a3, 0x0000, 0x3270, 0x2c25, 0x0000,\n0x6790, 0x3e67, 0x45ef, 0x0320, 0x2c6b, 0x030a, 0x6128, 0x0000,\n0x5eb3, 0xab9d, 0x2210, 0x35de, 0x6de0, 0x221d, 0x5f03, 0x4191,\n0x0000, 0x0000, 0x0000, 0x02ff, 0x32e8, 0x3386, 0x21f6, 0x0000,\n0x0b4f, 0x0000, 0x663c, 0x009a, 0x2c87, 0x0000, 0x0000, 0x16ce,\n0x028f, 0x4eee, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x3230, 0x0000, 0x2903, 0x96d5, 0x5ea3, 0x1cc5, 0x0000, 0x0000,\n0x0000, 0x0000, 0x89a6, 0x9ef3, 0x65c8, 0x0000, 0x8c84, 0x6f3b,\n0x0000, 0x0000, 0x0000, 0x0000, 0x3443, 0x44dd, 0x0000, 0xa5b3,\n0x6d21, 0x0000, 0x0000, 0x6e3d, 0x2c5d, 0x70ee, 0x0ee8, 0x7634,\n0xa5ec, 0x0000, 0x1d53, 0x04a5, 0x5e33, 0x0801, 0xa612, 0x02f4,\n0x70a2, 0x5c76, 0x0000, 0x0000, 0x29e2, 0x0000, 0x1cd8, 0x9337,\n0x01ca, 0xa059, 0x4508, 0xacb9, 0x0000, 0x0000, 0x29b7, 0x0000,\n0x7684, 0x0000, 0x0000, 0x0000, 0xa0e3, 0x375d, 0x0000, 0x0000,\n0x0000, 0xa665, 0x0000, 0x0000, 0x1b9b, 0x0000, 0x0000, 0xa68b,\n0x43e8, 0x428e, 0x008d, 0x446a, 0x0000, 0x3244, 0x6311, 0x6faa,\n0x0000, 0x0000, 0x843f, 0x0000, 0x8a3f, 0x0000, 0x12f4, 0x130c,\n0x1324, 0x133c, 0x1354, 0x3bb0, 0x0000, 0x0000, 0x8f44, 0x9f5d,\n0x8edf, 0x448f, 0x84c8, 0x0000, 0x6fba, 0x6cf9, 0x7f24, 0x99c5,\n0x6e80, 0x99e9, 0x7cf0, 0x9a0d, 0x9a1f, 0x9a31, 0x76d5, 0x0940,\n0x8fab, 0x0000, 0x4907, 0x1f5f, 0x491c, 0x3f53, 0x2644, 0x389b,\n0x4946, 0x2d68, 0x495b, 0x0000, 0x3862, 0x4228, 0x0000, 0x0000,\n0x2309, 0x0000, 0x149c, 0x2053, 0x0000, 0xa760, 0x454f, 0x0000,\n0x0000, 0x6e97, 0x8777, 0x416e, 0x1ac4, 0x0000, 0x46ea, 0x0000,\n0x9013, 0x0000, 0x0a3c, 0x0000, 0x0000, 0x0000, 0x0000, 0x2485,\n0x0000, 0x5753, 0x0000, 0x2cea, 0x0000, 0x1633, 0x0000, 0x3f1f,\n0x4795, 0x0000, 0x1d90, 0x0abf, 0x4e86, 0x0000, 0x0000, 0x26a8,\n0x0000, 0x0000, 0xab69, 0x5a0c, 0x9775, 0x0000, 0x1d46, 0x9bf8,\n0xa1a1, 0x0000, 0x7ef6, 0x0000, 0x7c62, 0x0000, 0x5ee3, 0x099a,\n0x4847, 0x20a0, 0x7b21, 0x69cf, 0x7c91, 0x0000, 0x1d04, 0x0000,\n0x1bc5, 0x1709, 0x0000, 0x0000, 0x41b5, 0x9e3f, 0x2125, 0x0000,\n0x7dad, 0x0000, 0x49ad, 0xa6c8, 0x5e22, 0x0000, 0x821d, 0x0000,\n0x5f42, 0x0000, 0x0000, 0x0000, 0x8b2d, 0x012d, 0x81d5, 0x0000,\n0x87d5, 0x0000, 0x3159, 0xa23b, 0x4b58, 0x1813, 0x8235, 0x0000,\n0x7a0f, 0x1920, 0x7fb1, 0x7d7d, 0x6d59, 0x866d, 0x81ed, 0x7ddd,\n0x80cd, 0x6f5e, 0x0080, 0x6192, 0x8c09, 0x7555, 0x6cde, 0x182a,\n0x80fe, 0x86fe, 0x827e, 0x887e, 0x8d99, 0x8b8e, 0x8342, 0x8942,\n0x0000, 0x8c52, 0xac5a, 0x0486, 0x8c3a, 0x092a, 0x83a6, 0x45a1,\n0x8117, 0x8717, 0x2203, 0x5c01, 0x4376, 0x20c8, 0x835b, 0x895b,\n0x0000, 0x8c6b, 0x0000, 0x59b1, 0x0000, 0x8dfb, 0x83bf, 0x89bf,\n0x5c46, 0x8ccf, 0x5068, 0x7526, 0x8e2e, 0x7241, 0xaf5c, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x39eb, 0x176b, 0x5187, 0x0f17,\n0x0000, 0x6d66, 0x3ea7, 0x0000, 0x9722, 0x8e92, 0x0000, 0x0000,\n0x66fb, 0x0000, 0xaede, 0x0000, 0x2741, 0x4363, 0x1d37, 0x9354,\n0x3638, 0x0000, 0x31b5, 0x0000, 0xa33a, 0xac8c, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x335c, 0x8fc6, 0x6fd2, 0x9216,\n0x4994, 0x789a, 0x2260, 0x0ced, 0x0000, 0x226d, 0x0000, 0x59a0,\n0x0000, 0x0000, 0x0000, 0xa625, 0x0000, 0x0000, 0x0000, 0x08fd,\n0x3524, 0x0000, 0x0000, 0x0000, 0x0000, 0x96c4, 0x1532, 0x0812,\n0x1550, 0x0000, 0x0000, 0x0000, 0x36a4, 0x081f, 0x0000, 0x3e05,\n0x0000, 0x0000, 0x1dee, 0x0000, 0x0000, 0x6d06, 0x4aea, 0x9af3,\n0x0000, 0x4537, 0x0000, 0x0000, 0x37cb, 0x4767, 0x77e5, 0x70fe,\n0x780d, 0x7821, 0x7835, 0x4f97, 0x0fcf, 0x7871, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x04fa, 0x93aa, 0x0000, 0x0000, 0x53dc,\n0x268a, 0x47d5, 0x0000, 0x9627, 0x4a19, 0x54ae, 0x0000, 0x58f0,\n0x0000, 0x0000, 0x0000, 0x74c4, 0x0000, 0x4e18, 0x533b, 0x0d8c,\n0x9bd6, 0x59c2, 0x5a50, 0x0356, 0x0000, 0x5902, 0x0000, 0x0000,\n0x0000, 0x759a, 0x4139, 0x0000, 0x0000, 0x3f89, 0x65ef, 0x30dc,\n0x592b, 0x7263, 0x0000, 0x598e, 0x2878, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x4749, 0x0000, 0x01bd, 0x9233,\n0x0000, 0x0000, 0x2331, 0x7587, 0x0000, 0x0000, 0x0000, 0x0000,\n0xa7bc, 0x0000, 0x942d, 0xa2cf, 0x98e7, 0x02e7, 0x253e, 0x9e2f,\n0x0000, 0x0000, 0x21e9, 0x0000, 0x0000, 0x2065, 0x0000, 0x7b51,\n0x0000, 0x0000, 0x3976, 0x0000, 0x5956, 0x9bb8, 0x0000, 0x0000,\n0x4fb0, 0xa3a8, 0x98f9, 0x73d4, 0x0000, 0x0000, 0x0000, 0x1f24,\n0x04d7, 0x76fb, 0x0000, 0x0000, 0x0000, 0x9c2c, 0x216b, 0xa567,\n0x0000, 0x0000, 0x20d5, 0xa029, 0x0000, 0x20e2, 0x9979, 0x0000,\n0x0000, 0x1dfb, 0x97d0, 0xa5a0, 0x0000, 0x0000, 0x1de1, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x7760, 0x0000, 0x2143, 0xa5d9,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x994f, 0x39bd,\n0x0000, 0x4dff, 0x5d2b, 0x824d, 0x0000, 0x0eb8, 0x0000, 0x0f01,\n0x0000, 0x0000, 0x5cfc, 0x9477, 0xaad6, 0x0000, 0x0000, 0xa412,\n0x60e2, 0x0000, 0x0000, 0x75e6, 0x0000, 0x982c, 0x9f38, 0x02c0,\n0x21d9, 0x4bad, 0x0000, 0x7849, 0xa425, 0x0000, 0xa7e9, 0x0000,\n0x95c9, 0xa4d8, 0x1e63, 0x5451, 0x2ecb, 0x632c, 0x0000, 0x26c5,\n0xa951, 0x0000, 0x5afe, 0x5849, 0x0000, 0x0000, 0x0000, 0x1c68,\n0x4d6a, 0x72a5, 0xa9d3, 0x577b, 0x0000, 0x0000, 0x0000, 0x567e,\n0x0000, 0x0000, 0x0000, 0xa1b7, 0x9b44, 0x0000, 0x3c64, 0x37df,\n0xa1cd, 0x1102, 0x02cd, 0xaa47, 0x0000, 0xaa5b, 0x0000, 0x16fb,\n0x0199, 0x0000, 0x4fe6, 0x9c3e, 0x0000, 0x0000, 0x0000, 0x88ca,\n0x0000, 0x0000, 0x33d1, 0x57b0, 0x6167, 0x0000, 0x0000, 0x0000,\n0x90b6, 0x818e, 0x3d64, 0x0000, 0x5914, 0x1ca3, 0x1dd4, 0x0000,\n0x90ee, 0x5c2d, 0x284d, 0x55cf, 0x779d, 0x4ecb, 0x9187, 0x4757,\n0x0000, 0x8130, 0x0000, 0x52e8, 0x3460, 0x0000, 0x0476, 0x9dc6,\n0x0000, 0x0000, 0x88b0, 0x0000, 0x0000, 0x0000, 0x0000, 0x7b39,\n0x1e1a, 0x0000, 0x355d, 0x1e3a, 0x5ca5, 0x4049, 0x1e0d, 0x0000,\n0x4ccd, 0x6547, 0x0000, 0x0000, 0x3c75, 0x4ce9, 0x4cdb, 0x3608,\n0x2441, 0x0000, 0x0000, 0x3cbe, 0x3ce3, 0x8cb6, 0x42e7, 0x0047,\n0x6dc0, 0x3d2e, 0x013a, 0x3d52, 0x3909, 0x0000, 0x0000, 0x3d99,\n0x3dab, 0xa03b, 0x88e1, 0x1bb5, 0x3876, 0x0000, 0x45d8, 0x915e,\n0x3d75, 0x735a, 0x1e93, 0x772f, 0x86b5, 0x0000, 0x3b7a, 0x0000,\n0x3dbd, 0x0000, 0x0000, 0x1b07, 0x3df3, 0x0000, 0x1e56, 0x0000,\n0x1955, 0x0000, 0x2405, 0x0000, 0x3e31, 0x7230, 0x0000, 0x7bab,\n0x8b45, 0x0000, 0x7e9b, 0x0000, 0x0000, 0x08d0, 0x0000, 0x4715,\n0x7ec8, 0x0000, 0x210b, 0x840b, 0x0000, 0x2118, 0x7a7f, 0x0b6e,\n0x25a0, 0x481a, 0x12d8, 0x0bbe, 0x7770, 0x4f25, 0x0000, 0x85e0,\n0x23a7, 0x0000, 0x7f3b, 0x0000, 0x0000, 0x0ea2, 0x0000, 0x0000,\n0x8eab, 0x48b8, 0x0000, 0x85f7, 0x382d, 0xa853, 0x47fc, 0x2e1e,\n0x2e2d, 0x2e3c, 0x2e4b, 0x2e5a, 0x2e69, 0x2e78, 0x2e87, 0x2e96,\n0x2ea5, 0x950c, 0x0000, 0x3a69, 0x04c4, 0x347c, 0x2833, 0x0000,\n0x8f77, 0x3ad9, 0x3a57, 0x04b7, 0x374b, 0x0000, 0x0000, 0x3b44,\n0x3b56, 0x0000, 0x0000, 0x1c33, 0x36b8, 0x0914, 0x0000, 0x9251,\n0x3b20, 0x0000, 0x7740, 0x0000, 0x0000, 0x57e6, 0xac41, 0x0000,\n0x3b68, 0x0000, 0x0000, 0x0000, 0x3b9e, 0x0000, 0x3b32, 0x0000,\n0x4019, 0x0000, 0x0000, 0x967e, 0x3bdc, 0x0000, 0x0000, 0x8d6a,\n0x1c92, 0x0000, 0x3e8f, 0x2577, 0x0000, 0x172a, 0x0000, 0xa995,\n0x4e2f, 0x2867, 0x39fd, 0x3c9a, 0x0000, 0x56b0, 0x8a25, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2568, 0x9d2e,\n0x3620, 0x0000, 0x3f39, 0x0000, 0x44cb, 0x0000, 0x0000, 0xa83c,\n0x0000, 0x0000, 0x0000, 0x270b, 0x2497, 0x0000, 0x11f6, 0x670f,\n0x426e, 0x3cac, 0x09af, 0x0000, 0xabb7, 0x0000, 0x0000, 0x0000,\n0x0000, 0x2f12, 0x4691, 0x0000, 0x5582, 0x0000, 0x6219, 0x0000,\n0xa3bd, 0x0000, 0x0000, 0xa398, 0x66bf, 0x6152, 0x200e, 0x0000,\n0x415e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9888,\n0x0000, 0x0000, 0x0000, 0x0000, 0x7537, 0x0000, 0x0000, 0x0000,\n0x34cc, 0x985e, 0x0000, 0xa47c, 0x0000, 0x41f5, 0x0000, 0x42a0,\n0x0000, 0xa9b4, 0x0000, 0x93c7, 0x425e, 0x42c3, 0x2627, 0x9371,\n0x0000, 0x0000, 0x71b8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0xa8ac, 0x0000, 0x4218, 0x56c2, 0xae4e, 0x95e6, 0x0000, 0x0000,\n0x7e85, 0x5160, 0x427e, 0x927f, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0xae84, 0x0000, 0x6629, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0xa70a, 0x0000, 0x0000, 0x5103,\n0x0f38, 0x2f89, 0x1ed2, 0x1b6f, 0x0f52, 0x07d1, 0x760d, 0x26fd,\n0x0f6c, 0x300a, 0x37b8, 0x07e1, 0x0000, 0x0000, 0x0f86, 0x4e91,\n0x0000, 0x0000, 0x2150, 0x4351, 0x0fa0, 0x32d7, 0x4f8b, 0x0000,\n0xa57a, 0x10b6, 0x0000, 0x4775, 0x0000, 0x0000, 0x73fc, 0x0000,\n0x0f2b, 0x1af7, 0x0000, 0x35f3, 0x0f45, 0x0000, 0x03e2, 0x433f,\n0x0f5f, 0x0000, 0x040b, 0x0000, 0x7472, 0x03d4, 0x0f79, 0x0000,\n0x483b, 0x0000, 0x6ec8, 0x1056, 0x0f93, 0x6ceb, 0x0000, 0x25bd,\n0x0000, 0x4b88, 0x0000, 0x029a, 0xa1f9, 0x9cb0, 0x0000, 0x0000,\n0xa8ff, 0x0000, 0x22ef, 0x4eab, 0xa20f, 0x22fc, 0x1132, 0x6d74,\n0x0000, 0x2cb4, 0x11e3, 0x0000, 0xa225, 0x0000, 0x22d5, 0x8d1b,\n0x3d40, 0x0000, 0x0000, 0x736a, 0x0000, 0x5139, 0x43a3, 0xad31,\n0x9109, 0x03a4, 0x03b0, 0x03bc, 0x03c8, 0x4bd1, 0xa8e7, 0x9749,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2324, 0x693d, 0x4082,\n0x0000, 0x5007, 0x2dd1, 0x1ab3, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0a53, 0x9f73, 0xabee, 0x2f77, 0x0000, 0x103c, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9eb9,\n0x4438, 0x0000, 0x1f40, 0x0000, 0x0000, 0x2317, 0x0000, 0x499f,\n0xafb5, 0x4458, 0x64b5, 0x4cab, 0x6536, 0x40da, 0x1ec5, 0x0000,\n0x55bb, 0x0000, 0x31e1, 0x0000, 0x0000, 0x601c, 0x0000, 0x3a20,\n0x1ba8, 0x0000, 0x6735, 0x0000, 0x6965, 0x9963, 0x1ea0, 0x54c1,\n0x6675, 0xad88, 0x0000, 0xad9a, 0x0000, 0xadac, 0x67ed, 0x2fd5,\n0x63d3, 0xae60, 0x68cb, 0xae72, 0x3c3a, 0xadf4, 0x2ff8, 0xae96,\n0x25cc, 0xaea8, 0x6759, 0x0000, 0x4428, 0x0000, 0x03f0, 0x0000,\n0x656b, 0x5628, 0x0000, 0x7516, 0x5201, 0x43d6, 0x11d2, 0x3135,\n0x0000, 0x3ac7, 0x43c6, 0x0000, 0x555d, 0x6d4c, 0x0000, 0x0000,\n0x0000, 0x2359, 0x4448, 0x431c, 0x535f, 0x0000, 0x0000, 0x27c3,\n0xa269, 0x9242, 0x0000, 0xa734, 0x0000, 0x0000, 0x3598, 0x98b2,\n0x0000, 0x0000, 0x0000, 0x0000, 0x51a8, 0x0000, 0x0000, 0x0000,\n0x0230, 0x0000, 0x5080, 0x0000, 0x0000, 0x914f, 0x0000, 0x0000,\n0x480c, 0x4d55, 0x64c7, 0x7294, 0x806d, 0x0000, 0x0000, 0x4127,\n0x304f, 0x61a8, 0x69bd, 0x0000, 0x0000, 0x67b5, 0x26f0, 0x23c4,\n0x0000, 0x0000, 0x301b, 0x4a29, 0x2a05, 0x8f12, 0x2fc3, 0x0000,\n0x2a2c, 0x0000, 0x1f7d, 0x730a, 0x2a12, 0x0000, 0x67ff, 0x647c,\n0x5e43, 0x2c95, 0x2a39, 0x4a36, 0x5f33, 0x0000, 0x1f33, 0x1c7d,\n0x2a1f, 0x9e73, 0x5e73, 0x0000, 0x02b4, 0x1ce5, 0x2de3, 0x0000,\n0x5ec3, 0x0a86, 0x6e54, 0x7284, 0x2968, 0x5e02, 0x1ef1, 0x6001,\n0x298f, 0x2b8b, 0x5032, 0xa3e2, 0x2975, 0x2bd1, 0x4b40, 0x9cbc,\n0x4bbd, 0x2b37, 0x299c, 0x0000, 0x0000, 0x2bc3, 0x2d9b, 0x0000,\n0x2982, 0x2b99, 0x8485, 0x9e1d, 0x0000, 0x0aa2, 0x2ca2, 0x9b52,\n0x0000, 0x2b45, 0x082c, 0x0000, 0x4c90, 0x2a8c, 0x0000, 0x0000,\n0x0838, 0x2c09, 0x1a7e, 0x613d, 0x70e2, 0x2ab7, 0x7fca, 0x0000,\n0x003b, 0x2c4f, 0xa316, 0x0000, 0x97af, 0x16ee, 0x6d31, 0x0000,\n0x0000, 0x2b53, 0x8bc0, 0x2ae1, 0x47a8, 0x2c79, 0x0000, 0xaa0a,\n0x711e, 0x2ac5, 0x8a5a, 0x14d4, 0x0000, 0x0000, 0xa7a8, 0x0000,\n0x318b, 0x0338, 0x22e2, 0x7578, 0x83d8, 0x215e, 0x0000, 0x4e61,\n0x0000, 0x2b0d, 0x0000, 0xab87, 0x0000, 0x6083, 0x0000, 0x9735,\n0xa2ba, 0x0000, 0x0000, 0x0000, 0x4b16, 0x0956, 0x60b8, 0x1d22,\n0x0000, 0x6616, 0x3508, 0x0000, 0x1ffd, 0x5e63, 0x4b75, 0x51ba,\n0x849b, 0x6e26, 0x7ac4, 0x5f13, 0x7c34, 0x5f23, 0x1d11, 0x5f8d,\n0x111a, 0x0012, 0x7edf, 0x391b, 0x84df, 0x0000, 0x1f70, 0x0000,\n0x853b, 0x0000, 0x7ff7, 0x2a9a, 0x66d3, 0x0000, 0x24c6, 0x0000,\n0x856a, 0x5197, 0x8026, 0x60cd, 0x0e15, 0x0100, 0x6fdf, 0x0000,\n0x87a6, 0x0000, 0x233f, 0x0000, 0x8ab6, 0x234c, 0x0000, 0x0000,\n0x957b, 0x79e2, 0x7a96, 0x7c06, 0x7af2, 0x2463, 0x7f52, 0x7d1e,\n0x16c1, 0x5e92, 0x7f81, 0x7d4d, 0x803d, 0x399d, 0x81bd, 0x6890,\n0x7003, 0x2afe, 0x7f99, 0x7d65, 0x8055, 0x8655, 0x28d5, 0x7dc5,\n0x80b5, 0x3850, 0x1fd1, 0x5ed2, 0x0000, 0x5fec, 0x6dd0, 0x7df6,\n0x80e6, 0x86e6, 0x8266, 0x5e52, 0x0000, 0x8b76, 0x832a, 0x892a,\n0x8f2b, 0x6902, 0x0000, 0x0000, 0x9b00, 0x5bd5, 0x838e, 0x898e,\n0xaf45, 0x8c9e, 0x0000, 0x2245, 0x508d, 0x1250, 0x7946, 0x0000,\n0xa467, 0x393f, 0x5a2c, 0x0000, 0x0000, 0x8efa, 0x0000, 0x5e12,\n0x0000, 0x3964, 0x0000, 0x4c76, 0x46da, 0x617d, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x9532, 0x4fc9, 0x0000, 0x5bbd,\n0x0000, 0x10ec, 0x0000, 0x1b47, 0x0000, 0x0000, 0x4c2b, 0x0000,\n0x5d7a, 0x0af7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7216,\n0xaf13, 0xa0cd, 0x0000, 0xa8ca, 0xabfc, 0x9bc5, 0x254b, 0x0000,\n0x64ed, 0x0000, 0x0000, 0x0000, 0x0000, 0x29a9, 0x0000, 0x0054,\n0x0000, 0x0000, 0x0000, 0x2238, 0x0000, 0x0000, 0x2593, 0x0000,\n0xa079, 0x0000, 0x22c8, 0x0000, 0x0000, 0x236c, 0x503f, 0x0000,\n0x3eef, 0x0000, 0x0000, 0x0000, 0x0000, 0x984a, 0x7416, 0x1daf,\n0x0000, 0x29c5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x26d3,\n0x025e, 0x0000, 0x0000, 0x0000, 0x8acd, 0x0000, 0x0000, 0x24e8,\n0x0000, 0xa4e9, 0x00e8, 0x4fd6, 0x7031, 0x2184, 0x6951, 0x0000,\n0x0000, 0x0000, 0x0000, 0x5d3d, 0x0000, 0x0344, 0x1fc4, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x970f, 0x0000,\n0x1149, 0x6fec, 0x0000, 0x0000, 0x0000, 0x0000, 0x25ed, 0x178e,\n0x0000, 0x0000, 0x68b7, 0x4f00, 0x0000, 0x21a0, 0x0000, 0x0000,\n0x7919, 0xa4a8, 0x0000, 0x7b7f, 0x0000, 0x1b25, 0x0000, 0x0000,\n0x0000, 0x846f, 0x1984, 0x0000, 0x0275, 0x0000, 0x3e56, 0x1401,\n0x0000, 0x3d06, 0x3cf5, 0xaac0, 0x0000, 0x27d3, 0x1eac, 0x21ba,\n0x2e08, 0x1b7d, 0x2046, 0x6f18, 0x0000, 0x72fe, 0x3dcf, 0x9da1,\n0x0000, 0x0000, 0x0000, 0x0000, 0x814a, 0x0000, 0x742e, 0xa917,\n0x0000, 0x7074, 0x3a0f, 0x0000, 0x8bf1, 0x1661, 0x3c01, 0x0000,\n0x0000, 0x29d3, 0x3aa0, 0x7670, 0x9ea5, 0x497c, 0x0000, 0x0000,\n0x3b0f, 0x3692, 0x0000, 0x0000, 0x0000, 0x65a2, 0x0156, 0x14e7,\n0x0000, 0x0000, 0x74b6, 0x0d17, 0x0000, 0x7fe0, 0x845a, 0x0000,\n0x50c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x229a,\n0x0000, 0x49e7, 0x0000, 0x9a43, 0x0000, 0x4931, 0x1fb7, 0x92ec,\n0x0000, 0x3781, 0x285a, 0x4ff7, 0x2385, 0x73e4, 0x0147, 0x0000,\n0x3372, 0x37a6, 0x0000, 0x9f15, 0x0000, 0x0000, 0x24fa, 0x0000,\n0x0000, 0x2eb4, 0x0000, 0x0000, 0x708b, 0x38ad, 0x0000, 0x0000,\n0x0000, 0x0000, 0x9e0b, 0x201d, 0x0000, 0x0000, 0x1ff0, 0x0000,\n0x66e7, 0x0000, 0x0000, 0x907e, 0x0000, 0x0000, 0x63e9, 0x0000,\n0x0000, 0x3989, 0x01da, 0x0000, 0xa44f, 0x0000, 0x4414, 0xac71,\n0x41c8, 0x5127, 0x41d7, 0x51cd, 0x58ca, 0x0000, 0x0000, 0x0000,\n0x9d0a, 0x0000, 0x41e6, 0x0000, 0x0000, 0x0000, 0x1166, 0x0000,\n0x0000, 0x48cc, 0x2076, 0x0000, 0x5fbc, 0x0000, 0x0000, 0x4a55,\n0x0000, 0x990f, 0x0000, 0x0000, 0xa506, 0x0000, 0x2039, 0x0000,\n0x53a6, 0x0000, 0x0000, 0x0000, 0x0000, 0x77c2, 0x0000, 0x0000,\n0x0000, 0x778e, 0x4d20, 0x0000, 0x0000, 0xa71f, 0x0000, 0x0000,\n0x0000, 0x523b, 0x21ad, 0x0000, 0x4068, 0x1675, 0x5fa2, 0x409c,\n0x0fbe, 0x52d6, 0x0000, 0x6bb0, 0x2cdc, 0x23e6, 0x2cf8, 0x2d06,\n0x2d14, 0x2d22, 0x2d30, 0x2d3e, 0x2d4c, 0x2d5a, 0x0000, 0x0e44,\n0x0000, 0x1beb, 0x0000, 0x1b5b, 0x2178, 0xa1e3, 0x0000, 0xa160,\n0x0000, 0x1eb8, 0x482b, 0x0000, 0x5b92, 0x6dec, 0x0000, 0x550c,\n0x0000, 0x6525, 0x43b7, 0x0000, 0x0000, 0x4e73, 0x2840, 0x0000,\n0x13e8, 0x8581, 0x4385, 0x6989, 0x0000, 0x0000, 0x75c0, 0x0000,\n0x5aa1, 0x8a9e, 0x4394, 0x749d, 0x0000, 0x73c4, 0x255a, 0x1a8f,\n0xa2e7, 0x9fe3, 0x0000, 0x0000, 0x0000, 0x4cfa, 0x011b, 0x580b,\n0x5463, 0x018b, 0x67c7, 0x0000, 0x0000, 0x9fcf, 0x7885, 0x5382,\n0x0000, 0x8599, 0x0000, 0x699a, 0x4e9f, 0x5394, 0x6cbc, 0x1f0f,\n0x0000, 0x0000, 0xa777, 0x175c, 0x15ab, 0x0000, 0x117c, 0x70bc,\n0x0000, 0x28b5, 0x534d, 0x0000, 0x978a, 0x20ae, 0x9c1b, 0x1776,\n0x0000, 0x4d94, 0x0000, 0x108a, 0xa934, 0xa867, 0x2896, 0x0000,\n0x0000, 0x1fde, 0x6d3e, 0x7cc1, 0x17f7, 0x0000, 0x0000, 0x85b1,\n0x0000, 0x4709, 0x59e7, 0x0000, 0x0000, 0x82f9, 0x04e9, 0x0b30,\n0x0000, 0x88f9, 0x0000, 0x86cd, 0x16dd, 0x1cf2, 0x0000, 0x884d,\n0x4646, 0x2523, 0x0000, 0x8b5d, 0x0000, 0x8311, 0x0000, 0x7e0e,\n0x0000, 0x8866, 0x157f, 0x8c21, 0x0add, 0x642d, 0x7e6f, 0x26b6,\n0x7b95, 0x0000, 0x1c58, 0x8db1, 0x7bc2, 0x9c5b, 0x7eb2, 0x0000,\n0x84b2, 0x0000, 0x0000, 0x0000, 0x850e, 0x1978, 0x7e40, 0x4f13,\n0x8730, 0x82b0, 0x181e, 0x8de2, 0x4970, 0x54d3, 0x8974, 0x27e3,\n0x6299, 0x0000, 0x0000, 0x2425, 0x2753, 0x8297, 0x89d8, 0x8897,\n0x8ce8, 0x8dca, 0x0000, 0x8ba7, 0x8e78, 0x0000, 0x792f, 0x7987,\n0x7a3b, 0x79b4, 0x7a68, 0x7bd8, 0x4ab8, 0x79cb, 0x76ac, 0x7bef,\n0x7adb, 0x7c4b, 0x60fb, 0x7d07, 0x7b0a, 0x7c7a, 0x7f6a, 0x7d36,\n0x458c, 0x30c9, 0x81a6, 0x7d96, 0x8086, 0x8686, 0x8206, 0x8806,\n0x0000, 0x8b16, 0x82ca, 0x589f, 0x0000, 0x8bda, 0x0000, 0x0000,\n0xa6df, 0x40b8, 0x0000, 0x0000, 0x8fdf, 0x8425, 0x6c5f, 0x0000,\n0x8d35, 0x78ae, 0x6b29, 0x73b0, 0x8ec5, 0x83f2, 0x0000, 0x89f2,\n0x0000, 0x0000, 0x6f85, 0x8d02, 0x8f91, 0x0000, 0x745c, 0x0000,\n0x9613, 0xa826, 0x0000, 0x0000, 0x0000, 0x1782, 0x7409, 0x0000,\n0x705e, 0x96eb, 0x473a, 0x0000, 0x8ff9, 0x713a, 0x0000, 0x6d80,\n0x6b89, 0x61bd, 0x1efe, 0x4a09, 0x0000, 0x1d83, 0x7422, 0x0000,\n0x4606, 0x0000, 0xaa1d, 0x0000, 0x0000, 0x0000, 0x3f6d, 0x222a,\n0x0000, 0x0000, 0x2507, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0xa678, 0x0000, 0x0000, 0x0000, 0x902e, 0x74f8, 0x0000, 0x0000,\n0x0ece, 0x34b2, 0x0000, 0x0000, 0x0ba5, 0x4003, 0x1d60, 0x16b5,\n0x0000, 0x0000, 0x179b, 0x0000, 0x0000, 0x7446, 0x4aca, 0x0000,\n0x0bd9, 0x0000, 0x0000, 0x0000, 0xa252, 0x0000, 0x2619, 0xac0f,\n0x0000, 0xac26, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x5116, 0x0980, 0x0000, 0x0000, 0x0000, 0x0000, 0x096b, 0xa12d,\n0x6b75, 0x626d, 0x1942, 0x5f73, 0x0000, 0x0000, 0x0000, 0x5bed,\n0xa532, 0x0000, 0x0000, 0x4786, 0x0000, 0x0000, 0x2083, 0x002c,\n0x51df, 0x69ab, 0x0c78, 0x0b12, 0x0000, 0x0c9f, 0x62ad, 0x0000,\n0x0000, 0x701a, 0x2f43, 0x0000, 0x0000, 0x5276, 0x743a, 0x9ac9,\n0x0281, 0xaaab, 0x0000, 0x32c4, 0x0000, 0x36ef, 0x432e, 0x0000,\n0x0000, 0x23d6, 0x53b7, 0x0000, 0x0000, 0x0000, 0x5371, 0x9656,\n0x1487, 0x50ba, 0x77af, 0x0000, 0x0000, 0x564e, 0x0000, 0x4f59,\n0x9b64, 0x0000, 0x0000, 0x46fa, 0x75ad, 0x0000, 0x0000, 0x77f9,\n0x51f0, 0x63bd, 0x529d, 0x0000, 0x0000, 0x7507, 0x0000, 0x2379,\n0x76ec, 0x785d, 0x30f1, 0x5023, 0xa2a5, 0x0000, 0x6c4c, 0x0000,\n0x0000, 0x0000, 0x5d14, 0x0000, 0x0000, 0x73f0, 0xa791, 0x1c10,\n0x5213, 0x0000, 0xaf2e, 0x0000, 0x78ee, 0x0000, 0x58b6, 0x136c,\n0x0000, 0x0000, 0xa550, 0x1f9c, 0x2453, 0x0000, 0x29f0, 0x0000,\n0x6d13, 0x0fe6, 0x367a, 0x59fa, 0x0000, 0x0000, 0x1932, 0x99fb,\n0x610f, 0x509b, 0x0000, 0x271d, 0x0000, 0x0000, 0x770b, 0x3662,\n0x6a91, 0x6286, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x878e,\n0x6c84, 0x0000, 0x0000, 0xaced, 0x0000, 0xa3fb, 0x6ca9, 0x1d9d,\n0x0000, 0x78d8, 0x7903, 0x795b, 0x46b4, 0x7971, 0x7a25, 0x799e,\n0x7a52, 0x4aa8, 0x7aae, 0x7c1e, 0x7f0e, 0x7cda, 0x62c4, 0x85ca,\n0x6aca, 0x874a, 0x0000, 0x02d9, 0x0000, 0xa63b, 0x252f, 0x0000,\n0x0000, 0x0000, 0x809d, 0x5d92, 0x0000, 0x0000, 0x59d4, 0xad53,\n0x0000, 0x7ca9, 0x5414, 0x6c11, 0x69e9, 0x0000, 0x0000, 0x0000,\n0x6b9d, 0x0000, 0x5a8d, 0x0000, 0x0000, 0x1ade, 0x2763, 0x6bc4,\n0x597b, 0x0000, 0x0000, 0x0000, 0x6a34, 0x0000, 0x3fe9, 0x5a3d,\n0x4c5b, 0x0000, 0x3074, 0x0000, 0x5cd6, 0x0000, 0x9cf5, 0x25fb,\n0x6db0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x15f0, 0x0000, 0x5428, 0x0000, 0x5da5, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x8a87, 0x0000, 0x0000, 0x9aaf, 0x0000, 0x6c38,\n0x0000, 0x7e27, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0xaaf5, 0x0000, 0x0000, 0x228d, 0x0000, 0x0000, 0x0000, 0x98d5,\n0x6b02, 0x0000, 0x383f, 0x0000, 0x0000, 0x9fba, 0x543b, 0x0000,\n0x5de0, 0x2252, 0x0000, 0x26e2, 0x6b4f, 0x8d81, 0x0000, 0x0000,\n0x6a59, 0x1c00, 0x0000, 0x69fb, 0x5ab4, 0xa350, 0x0000, 0x6bd8,\n0x4676, 0x15cf, 0xae18, 0x0000, 0x9b96, 0x27f3, 0x0000, 0x14c3,\n0xae3c, 0x0000, 0x638f, 0x6b61, 0x3301, 0x6bfe, 0x0000, 0x6a0e,\n0x78c3, 0x5d54, 0x5d67, 0x79fa, 0x7b6a, 0x7e5a, 0x20ef, 0x6c96,\n0x227a, 0x0000, 0x6c71, 0x0000, 0x0000, 0x739c, 0x0000, 0x6a21,\n0x0000, 0x0000, 0x0000, 0x548a, 0x0000, 0x0000, 0x0428, 0x6ab7,\n0x6aa4, 0x6beb, 0x332e, 0x53ed, 0x0000, 0x0000, 0x47ed, 0x5968,\n0x0000, 0x0000, 0x6b16, 0x0000, 0x0000, 0x0000, 0x0000, 0x6aef,\n0x0c1a, 0x16a4, 0x63ff, 0x5400, 0x4563, 0x0000, 0x4a43, 0x2584,\n0x6300, 0x6823, 0x0000, 0x6a6c, 0x0000, 0x5b1d, 0x5b65, 0x6b3c,\n0x0000, 0x6a7f, 0x622e, 0x0447, 0x156f, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x6c25, 0x3345, 0x6add, 0x5baa, 0xa5ff,\n0x0000, 0x0000, 0x0000, 0x6a46, 0x2773, 0x951c, 0x0000, 0x5df3,\n0x0000, 0x5dcc, 0x0000, 0x20fe, 0x0000, 0x0060, 0x2636, 0x1c45,\n0xa09f, 0x0000, 0x5ce9, 0x0a0f, 0x46cb, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x5ae1, 0x0000, 0x0000, 0x0000, 0x0000, 0x6e0f,\n0x0000, 0x0000, 0x020e, 0x0000, 0x47c5, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x1cb1, 0x6050, 0x0000, 0x4f71, 0x0000, 0x4dad,\n0x0000, 0x1600, 0x0000, 0x0000, 0x15bf, 0x0000, 0x0000, 0xa812,\n0x0000, 0x0000, 0x0000, 0x0000, 0x5c1a, 0x0000, 0x22b9, 0x0000,\n0x0000, 0x0000, 0x9f29, 0x657d, 0x0000, 0x0a29, 0x5719, 0x47b4,\n0x0e33, 0x2191, 0x0c67, 0x0000, 0x0000, 0x0d2e, 0x0000, 0x5769,\n0x0000, 0x0000, 0x0000, 0x94fc, 0x155f, 0x208f, 0x24b6, 0x0000,\n0x15e0, 0x0000, 0x44b9, 0x0000, 0x97a0, 0x56f6, 0x2bb5, 0x1621,\n0x0000, 0x37ff, 0x0000, 0x0000, 0x5db9, 0x0000, 0x0000, 0x1511,\n0x1522, 0x173b, 0x09df, 0x0000, 0x6ee2, 0x0000, 0x0000, 0x2413,\n0x0d3f, 0x0000, 0x0000, 0x0000, 0x0000, 0x14b1, 0x9d41\n};\n#endif /* NEEDKTABLE */\n\n#ifdef NEEDVTABLE\n#define VTABLESIZE 3379\n#define VMAXHASH 11\n\nstatic const unsigned short hashKeysym[VTABLESIZE] = {\n0x0003, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0xa451, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0xa469, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x16b7, 0x16c3, 0x16d0, 0x16df, 0x16f0, 0x16fd, 0x170b, 0x171b,\n0x173d, 0x174d, 0x175e, 0x176d, 0x1778, 0x1784, 0x1790, 0x179d,\n0x17a9, 0x17b1, 0x17b9, 0x17c1, 0x17c9, 0x17d1, 0x17d9, 0x17e1,\n0x17e9, 0x17f1, 0x17f9, 0x1805, 0x1815, 0x1820, 0x182c, 0x183a,\n0x1849, 0x1852, 0x185a, 0x1862, 0x186a, 0x1872, 0x187a, 0x1882,\n0x188a, 0x1892, 0x189a, 0x18a2, 0x18aa, 0x18b2, 0x18ba, 0x18c2,\n0x18ca, 0x18d2, 0x18da, 0x18e2, 0x18ea, 0x18f2, 0x18fa, 0x1902,\n0x190a, 0x1912, 0x191a, 0x1922, 0x1934, 0x1944, 0x1957, 0x1969,\n0x197a, 0x1996, 0x199e, 0x19a6, 0x19ae, 0x19b6, 0x19be, 0x19c6,\n0x19ce, 0x19d6, 0x19de, 0x19e6, 0x19ee, 0x19f6, 0x19fe, 0x1a06,\n0x1a0e, 0x1a16, 0x1a1e, 0x1a26, 0x1a2e, 0x1a36, 0x1a3e, 0x1a46,\n0x1a4e, 0x1a56, 0x1a5e, 0x1a66, 0x1a76, 0x1a80, 0x1a91, 0x5527,\n0x553d, 0x554e, 0x555f, 0x5570, 0x5584, 0x5599, 0x3c03, 0x55bd,\n0x55d1, 0x55e2, 0x55f6, 0x5606, 0x5619, 0x562a, 0x5640, 0x5650,\n0x5661, 0x5672, 0x3c77, 0x5692, 0x56a0, 0x56b2, 0x56c4, 0x56d6,\n0x56e7, 0x56f8, 0x570b, 0x571b, 0x572f, 0x5744, 0x5755, 0x576b,\n0x1aa2, 0x1ab5, 0x1ac6, 0x1ad1, 0x1ae0, 0x1aef, 0x1af9, 0x1b09,\n0x1b17, 0x1b27, 0x1b37, 0x1b49, 0x1b71, 0x1b7f, 0x1b8c, 0x1b9d,\n0x1baa, 0x1bb7, 0x1bc7, 0x1bd9, 0x1bed, 0x1bf9, 0x1c02, 0x1c12,\n0x1c27, 0x1c35, 0x1c47, 0x1c6a, 0x1c94, 0x1ca5, 0x1cb3, 0x1cc7,\n0x1cda, 0x1ce7, 0x1cf4, 0x1d06, 0x1d13, 0x1d24, 0x1d30, 0x1d39,\n0x1d48, 0x1d55, 0x1d62, 0x1d74, 0x1d85, 0x1d92, 0x1d9f, 0x1db1,\n0x1dc2, 0x1dd6, 0x1de3, 0x1df0, 0x1dfd, 0x1e0f, 0x1e1c, 0x1e2d,\n0x1e3c, 0x1e58, 0x1e65, 0x1e72, 0x1e84, 0x1e95, 0x1ea2, 0x1eba,\n0x1ec7, 0x1ed4, 0x1ee1, 0x1ef3, 0x1f00, 0x1f11, 0x1f1d, 0x1f26,\n0x1f35, 0x1f42, 0x1f4f, 0x1f61, 0x1f72, 0x1f7f, 0x1f8c, 0x1f9e,\n0x1faf, 0x1fb9, 0x1fc6, 0x1fd3, 0x1fe0, 0x1ff2, 0x1fff, 0x2010,\n0x201f, 0x203b, 0x2048, 0x2055, 0x2067, 0x2078, 0x2085, 0x2091,\n0x0000, 0x0000, 0xad11, 0x0000, 0x6591, 0xa2bc, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x55ad, 0xa384, 0x0000,\n0x7430, 0x0000, 0x0000, 0x0000, 0x69eb, 0x0000, 0x97f7, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x67c9, 0x0000, 0x0000, 0x5680, 0x983c, 0x0000,\n0x6837, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa39a, 0x0000,\n0x6d8e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x577d, 0x0000, 0x578f, 0x0000, 0x57a0, 0x63eb, 0x57b2,\n0x0000, 0x57c4, 0x0000, 0x57d7, 0x53de, 0x57e8, 0x0000, 0x53ef,\n0x0000, 0xa736, 0x5402, 0x0000, 0x0000, 0x5416, 0x0000, 0x580d,\n0x542a, 0x582a, 0x0000, 0x543d, 0x6515, 0x584b, 0x5453, 0x585d,\n0x0000, 0x5465, 0xa3e4, 0x5887, 0x5478, 0x58a1, 0xa3fd, 0x548c,\n0x65f1, 0x58cc, 0x54a0, 0x58e1, 0x0000, 0x54b0, 0x5b67, 0x5904,\n0x54c3, 0x5916, 0x5bbf, 0x54d5, 0x5bef, 0x5944, 0x54e8, 0x5c2f,\n0x5c48, 0x54fb, 0x5c78, 0x5958, 0x550e, 0x596a, 0x5cd8, 0x597d,\n0x5cfe, 0x5990, 0x5d2d, 0x59a2, 0x5d56, 0x59b3, 0x5d7c, 0x59c4,\n0x5da7, 0x59d6, 0x5dce, 0x59e9, 0x5df5, 0x59fc, 0x5e14, 0x5e24,\n0x5e35, 0x5e45, 0x5e54, 0x5e65, 0x5e75, 0x5e84, 0x5e94, 0x5ea5,\n0x5eb5, 0x5ec5, 0x5ed4, 0x5ee5, 0x5ef5, 0x5f05, 0x5f15, 0x5f25,\n0x5f35, 0x20a2, 0x20b0, 0x20bc, 0x5f8f, 0x20ca, 0x20d7, 0x5fd8,\n0x5fee, 0x20e4, 0x20f1, 0x2100, 0x210d, 0x606b, 0x211a, 0x2127,\n0x60ba, 0x2137, 0x2145, 0x2152, 0x6111, 0x2160, 0x216d, 0x217a,\n0x6169, 0x2186, 0x2193, 0x21a2, 0x21af, 0x21bc, 0x21ce, 0x21db,\n0x21eb, 0x624f, 0x626f, 0x21f8, 0x629b, 0x2205, 0x2212, 0x62e7,\n0x221f, 0x0000, 0x222c, 0x0000, 0x223a, 0x0000, 0x0000, 0x2247,\n0x2254, 0x2262, 0x226f, 0x0000, 0x0000, 0x227c, 0x0000, 0x0000,\n0x228f, 0x229c, 0x0000, 0x22a8, 0x0000, 0x0000, 0x22bb, 0x0000,\n0x22ca, 0x0000, 0x0000, 0x22d7, 0x0000, 0x22e4, 0x22f1, 0x0000,\n0x22fe, 0x0000, 0x230b, 0x0000, 0x2319, 0x0000, 0x0000, 0x2326,\n0x2333, 0x2341, 0x234e, 0x0000, 0x0000, 0x235b, 0x0000, 0x57fa,\n0x236e, 0x237b, 0x0000, 0x2387, 0x0000, 0x0000, 0x239a, 0x23a9,\n0x0000, 0x0000, 0xa534, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x583a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0xa953, 0x0000, 0x586e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0xa997, 0x58b8, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x58f2, 0x0000, 0x0000, 0x0000,\n0x0000, 0xa9e7, 0x0000, 0x0000, 0x0000, 0x592d, 0x0000, 0x0000,\n0x909c, 0x90aa, 0x0000, 0x90b8, 0x4005, 0x90d3, 0x90e1, 0x90f0,\n0x1489, 0x149e, 0x14b3, 0x14c5, 0x14d6, 0x14e9, 0x14fd, 0x1513,\n0x1524, 0x1534, 0x1543, 0x1552, 0x1561, 0x1571, 0x1581, 0x1598,\n0x15ad, 0x15c1, 0x15d1, 0x15e2, 0x15f2, 0x1602, 0x1612, 0x1623,\n0x1635, 0x164d, 0x1663, 0x1677, 0x168f, 0x16a6, 0x79cd, 0x79e4,\n0x79fc, 0x7a11, 0x414f, 0x7a3d, 0x7a54, 0x7a6a, 0x7a81, 0x7a98,\n0x7ab0, 0x7751, 0x7add, 0x7af4, 0x7b0c, 0x7b23, 0x7b3b, 0x7b53,\n0x7b6c, 0x7b81, 0x7b97, 0x7bad, 0x7bc4, 0x7bda, 0x7bf1, 0x7c08,\n0x7c20, 0x7c36, 0x7c4d, 0x7c64, 0x7c7c, 0x7c93, 0x7cab, 0x7cc3,\n0x7cdc, 0x7cf2, 0x7d09, 0x7d20, 0x7d38, 0x7d4f, 0x7d67, 0x7d7f,\n0x7d98, 0x7daf, 0x7dc7, 0x7ddf, 0x7df8, 0x7e10, 0x7e29, 0x7e42,\n0x7e5c, 0x7e71, 0x7e87, 0x7e9d, 0x7eb4, 0x7eca, 0x7ee1, 0x7ef8,\n0x7f10, 0x7762, 0x7f3d, 0x7f54, 0x7f6c, 0x7f83, 0x7f9b, 0x7fb3,\n0x7fcc, 0x7fe2, 0x7ff9, 0x8010, 0x8028, 0x803f, 0x8057, 0x806f,\n0x8088, 0x23b8, 0x80b7, 0x80cf, 0x7589, 0x8100, 0x23c6, 0x8132,\n0x814c, 0x23d8, 0x8179, 0x23e8, 0x23f5, 0x81bf, 0x75af, 0x81ef,\n0x75c2, 0x2407, 0x75d4, 0x824f, 0x75e8, 0x8280, 0x2415, 0x82b2,\n0x82cc, 0x2427, 0x82fb, 0x2436, 0x2443, 0x8344, 0x835d, 0x8376,\n0x8390, 0x83a8, 0x83c1, 0x83da, 0x83f4, 0x2455, 0x2465, 0x8441,\n0x845c, 0x65a4, 0x8487, 0x849d, 0x84b4, 0x84ca, 0x84e1, 0x84f8,\n0x8510, 0x8526, 0x853d, 0x8554, 0x856c, 0x2477, 0x859b, 0x85b3,\n0x2487, 0x85e2, 0x85f9, 0x8610, 0x8628, 0x2499, 0x24a6, 0x5b7b,\n0x8688, 0x5b94, 0x86b7, 0x5bac, 0x86e8, 0x24b8, 0x24c8, 0x5bd7,\n0x874c, 0x8762, 0x8779, 0x5c03, 0x87a8, 0x5c1c, 0x87d7, 0x87ef,\n0x8808, 0x6724, 0x8837, 0x5c60, 0x8868, 0x24da, 0x8899, 0x5c8f,\n0x24ea, 0x5ca7, 0x88fb, 0x5cc0, 0x892c, 0x24fc, 0x2509, 0x5ceb,\n0x8990, 0x67b7, 0x89c1, 0x5d16, 0x89f4, 0x8a0d, 0x8a27, 0x5d3f,\n0x8a5c, 0x8a72, 0x8a89, 0x5d69, 0x8ab8, 0x6ce0, 0x6d33, 0x5d94,\n0x8b18, 0x8b2f, 0x8b47, 0x5dbb, 0x8b78, 0x8b90, 0x8ba9, 0x5de2,\n0x8bdc, 0x8bf3, 0x8c0b, 0x5e04, 0x8c3c, 0x8c54, 0x8c6d, 0x8c86,\n0x8ca0, 0x8cb8, 0x8cd1, 0x8cea, 0x8d04, 0x8d1d, 0x8d37, 0x8d51,\n0x8d6c, 0x8d83, 0x8d9b, 0x8db3, 0x8dcc, 0x8de4, 0x8dfd, 0x8e16,\n0x8e30, 0x8e48, 0x8e61, 0x8e7a, 0x8e94, 0x8ead, 0x8ec7, 0x8ee1,\n0x087e, 0x088d, 0x08a4, 0x08bb, 0x08d2, 0x0942, 0x0958, 0x096d,\n0x0982, 0x099c, 0x09b1, 0x09cb, 0x09e1, 0x09fc, 0x0a11, 0x5f75,\n0x08e8, 0x08ff, 0x0916, 0x5fa4, 0x0000, 0x5fbe, 0x0000, 0x0000,\n0x92cf, 0x0000, 0x0000, 0x6003, 0x0000, 0x270d, 0x271f, 0x0a2b,\n0x0a3e, 0x0a55, 0x0a6e, 0x0a88, 0x0aa4, 0x0ac1, 0x0adf, 0x0af9,\n0x0b14, 0x0b32, 0x0b51, 0x0b70, 0x0b8b, 0x0ba7, 0x0bc0, 0x0bdb,\n0x0bfa, 0x0c1c, 0x0c30, 0x0c48, 0x0000, 0x613f, 0x0000, 0x6154,\n0x6d76, 0x0000, 0x0000, 0x617f, 0x0000, 0x6194, 0x0000, 0x61aa,\n0x0000, 0x61bf, 0x0000, 0x61dd, 0x0000, 0x61fc, 0x0000, 0x621b,\n0x6d15, 0x6230, 0x7424, 0x0000, 0x0000, 0x0000, 0x0000, 0x0c58,\n0x0c69, 0x0c7a, 0x0c90, 0x0cb8, 0x0cca, 0x0cdb, 0x0cef, 0x0d04,\n0x0d19, 0x0d30, 0x0d41, 0x0d54, 0x0d66, 0x0d76, 0x0d8e, 0x0daa,\n0x0dbe, 0x0dce, 0x0dde, 0x0df0, 0x0e17, 0x0e46, 0x0e5d, 0x0e72,\n0x0e89, 0x0ea4, 0x0eba, 0x0ed0, 0x0eea, 0x0f03, 0x0f19, 0x10a3,\n0x10b8, 0x10d6, 0x10ee, 0x1104, 0x111c, 0x1134, 0x114b, 0x1168,\n0x117e, 0x1194, 0x6d08, 0x2586, 0x0000, 0x2595, 0x25a2, 0x0f2d,\n0x0f3a, 0x0f47, 0x0f54, 0x0f61, 0x0f6e, 0x0f7b, 0x0f88, 0x0f95,\n0x0fa2, 0x0faf, 0x0fc0, 0x1001, 0x1012, 0x0000, 0xa7d5, 0x25fd,\n0x6d4e, 0x0000, 0x0000, 0x0000, 0x260b, 0x0000, 0x0000, 0x261b,\n0x0000, 0x2629, 0x2638, 0x2646, 0x0000, 0x0000, 0x0000, 0x1450,\n0x1459, 0x1462, 0x146b, 0x1475, 0x147f, 0x2663, 0x2670, 0x0000,\n0x267e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa869, 0x268c,\n0x0000, 0x0000, 0x0000, 0x0000, 0x269a, 0xa352, 0xa891, 0x26aa,\n0x0000, 0x26b8, 0x26c7, 0x26d5, 0x0000, 0x0000, 0xa360, 0x0000,\n0x0000, 0x26e4, 0x0000, 0x0000, 0x0000, 0x26f2, 0x26ff, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1023,\n0x103e, 0x1058, 0x0000, 0x1072, 0x108c, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x4491, 0x0000, 0xa370, 0x0000, 0x0000, 0x11ad,\n0x11c0, 0x11d4, 0x11e5, 0x11f8, 0x120d, 0x1223, 0x123a, 0x1252,\n0x126c, 0x1282, 0x1298, 0x12ae, 0x12c4, 0x12da, 0x12f6, 0x130e,\n0x1326, 0x133e, 0x1356, 0x136e, 0x1386, 0x139a, 0x13ae, 0x13c2,\n0x13ea, 0x1403, 0x141c, 0x1436, 0x13d6, 0x0000, 0x0000, 0x0000,\n0x4648, 0x0000, 0x6d82, 0x0000, 0x0000, 0x0000, 0xa3aa, 0x0014,\n0x0024, 0x002e, 0x003d, 0x0000, 0x0049, 0x0000, 0xa936, 0x0000,\n0x0000, 0x0000, 0x0056, 0x0062, 0x0074, 0x0000, 0xa975, 0x0000,\n0xa3d3, 0x0000, 0x0082, 0x0000, 0x0000, 0x0000, 0x6d68, 0x009c,\n0x0102, 0x010e, 0x011d, 0x013c, 0x0149, 0x0158, 0x0167, 0x017f,\n0x018d, 0x019b, 0x01b1, 0x01bf, 0x01cc, 0x01dc, 0x01ed, 0x01fe,\n0x5a0e, 0x5a1b, 0x5a2e, 0x5a3f, 0x5a52, 0x5a64, 0x00ac, 0x5a8f,\n0x5aa3, 0x5ab6, 0x5acc, 0x00bc, 0x00d2, 0x00ea, 0x5b3e, 0x9126,\n0x0000, 0x9134, 0x4769, 0x9143, 0x0000, 0x9151, 0x28c8, 0x9160,\n0xa47e, 0x916d, 0x4777, 0x917b, 0x884f, 0x9189, 0xa4aa, 0x0241,\n0x024c, 0x0257, 0x0260, 0x026c, 0x0277, 0x0291, 0x02ac, 0x02b6,\n0x0000, 0x789c, 0x0000, 0x78b0, 0x0000, 0x78c5, 0x0000, 0x02c2,\n0x02cf, 0x02db, 0x02e9, 0x7905, 0x02f6, 0x0301, 0x030c, 0x0317,\n0x0322, 0x032f, 0x033a, 0x2905, 0x291f, 0x2930, 0x295c, 0x296a,\n0x2977, 0x2984, 0x2991, 0x299e, 0x29ab, 0x29b9, 0x29c7, 0x29d5,\n0x29f2, 0x2a07, 0x2a14, 0x2a21, 0x2a2e, 0x0346, 0x036c, 0x037b,\n0x2a64, 0x2a72, 0x2a80, 0x2a8e, 0x2a9c, 0x2aab, 0x2ab9, 0x2ac7,\n0x038a, 0x2ae3, 0x2b00, 0x2b1d, 0x0397, 0x2b39, 0x2b47, 0x2b55,\n0x03a6, 0x03b2, 0x03be, 0x03ca, 0x03d6, 0x03e4, 0x03f2, 0x03fe,\n0x040d, 0x041b, 0x043b, 0x045c, 0x0469, 0x0478, 0x0488, 0x2c43,\n0x2c51, 0x2c5f, 0x2c6d, 0x2c7b, 0x2c89, 0x2c97, 0x2ca4, 0x2cb6,\n0x0000, 0x04a7, 0x04b9, 0x04c6, 0x04d9, 0x04eb, 0x04fc, 0x050c,\n0x0517, 0x0522, 0x052d, 0x0538, 0x0543, 0x054e, 0x0559, 0x0564,\n0x056f, 0x9412, 0x0000, 0x0000, 0x0498, 0x057a, 0x0583, 0x058c,\n0x0595, 0x059e, 0x05a7, 0x05b0, 0x05b9, 0x05c2, 0x05cb, 0x05d5,\n0x05e8, 0x05fb, 0x060e, 0x0621, 0x0634, 0x0647, 0x065a, 0x066d,\n0x0680, 0x0694, 0x06a7, 0x06ba, 0x06cd, 0x06e0, 0x06f3, 0x0706,\n0x0719, 0x072c, 0x073f, 0x0753, 0x0767, 0x077b, 0x078f, 0x07a3,\n0x07b7, 0x07c5, 0x07d3, 0x07e3, 0x07f3, 0x0803, 0x0814, 0x0821,\n0x082e, 0x083a, 0x0846, 0x0854, 0x0862, 0x0870, 0xad66, 0x0000,\n0x77d3, 0x77e7, 0x77fb, 0x780f, 0x7823, 0x7837, 0x784b, 0x785f,\n0x7873, 0x7887, 0x0000, 0x0000, 0x0000, 0x0000, 0x008f, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x94fe, 0x0000, 0x809f, 0x0000, 0x951e, 0x0000, 0x0000,\n0x0000, 0x80e8, 0x0000, 0x6288, 0x9218, 0x8119, 0x0000, 0x0000,\n0x0000, 0x62af, 0x0000, 0x8162, 0x62c6, 0x0000, 0x0000, 0x8190,\n0x0000, 0x81a8, 0x0000, 0x0000, 0x0000, 0x81d7, 0x0000, 0x0000,\n0x0000, 0x8208, 0x0000, 0x821f, 0xa58f, 0x8237, 0x6302, 0xa5a2,\n0x0000, 0x8268, 0xa5b5, 0x0000, 0x9253, 0x8299, 0x0000, 0x0000,\n0xa5db, 0x0000, 0x0000, 0x82e3, 0x9263, 0x0000, 0x0000, 0x8313,\n0x0000, 0x832c, 0x0000, 0x0000, 0x0000, 0x2755, 0x2765, 0x69fd,\n0x6a10, 0x6a23, 0x6a36, 0x6a48, 0x6a5b, 0x2775, 0x2785, 0x6a93,\n0x6aa6, 0x6ab9, 0x6acc, 0x6adf, 0x6af1, 0x6b04, 0x6b18, 0x6b2b,\n0x6b3e, 0x6b51, 0x6b63, 0x6b77, 0x6b8b, 0x6b9f, 0x6bb2, 0x6bc6,\n0x6bda, 0x2795, 0x27a5, 0x6c13, 0x6c27, 0x6c3a, 0x6c4e, 0x6c61,\n0x6c73, 0x6c86, 0x6c98, 0x6cab, 0x6cbe, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x8583, 0x2df7, 0xa5c8, 0x0000, 0xa74c,\n0x0000, 0x6da2, 0x6db2, 0x0000, 0x0000, 0xa0fc, 0x0000, 0x0000,\n0xa10f, 0x0000, 0x0000, 0x27b5, 0x27c5, 0x8657, 0x0000, 0x2ecd,\n0x0000, 0x2ee8, 0x2efb, 0x2f14, 0x2f2d, 0x2f45, 0x2f61, 0x2f79,\n0x2f8b, 0x2f9c, 0x2fb4, 0x2fc5, 0x2fd7, 0x2fe9, 0x2ffa, 0x300c,\n0x301d, 0x27d5, 0x27e5, 0x3051, 0x3063, 0x3076, 0x3087, 0x3098,\n0x30a9, 0x30ba, 0x30cb, 0x27f5, 0x2805, 0x0000, 0x0000, 0x0000,\n0x30de, 0x30f3, 0x3104, 0x3115, 0x3126, 0x2815, 0x2825, 0x315b,\n0x317c, 0x318d, 0x31a6, 0x31b7, 0x31cd, 0x31e3, 0x31f9, 0x320c,\n0x321f, 0x3232, 0x3246, 0x88e3, 0x0000, 0x0000, 0x0000, 0x8913,\n0x7731, 0x0000, 0x0000, 0x2835, 0x2842, 0x284f, 0x285c, 0x2869,\n0x287a, 0x0000, 0x0000, 0x89a8, 0x0000, 0x6cd0, 0x6d23, 0x89da,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8a41,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8aa0,\n0x0000, 0x0000, 0x0000, 0x6dc2, 0x6dd2, 0x6de2, 0x6dee, 0x6dfa,\n0x6e11, 0x6e28, 0x6e3f, 0x6e56, 0x6e6c, 0x6e82, 0x6e99, 0x6eb0,\n0x6eca, 0x6ee4, 0x6ef6, 0x6f08, 0x6f1a, 0x6f2c, 0x6f3d, 0x6f4e,\n0x6f60, 0x6f72, 0x6f87, 0x6f9c, 0x6fac, 0x6fbc, 0x6fc8, 0x6fd4,\n0x6fe1, 0x6fee, 0x7005, 0x701c, 0x7033, 0x704a, 0x7060, 0x7076,\n0x708d, 0x70a4, 0x70be, 0x70d8, 0x70e4, 0x70f0, 0x7100, 0x7110,\n0x7120, 0x7130, 0x713c, 0x7148, 0x715f, 0x7176, 0x718d, 0x71a4,\n0x71ba, 0x71d0, 0x71e7, 0x71fe, 0x7218, 0x7232, 0x7243, 0x7254,\n0x7265, 0x7276, 0x7286, 0x7296, 0x72a7, 0x72b8, 0x72cc, 0x72e0,\n0x72f0, 0x7300, 0x730c, 0x7318, 0x7329, 0x733a, 0x734b, 0x735c,\n0x736c, 0x737c, 0x738d, 0x739e, 0x73b2, 0x288b, 0x2898, 0x73c6,\n0x73d6, 0x73e6, 0x73f2, 0x3388, 0x339f, 0x8f2d, 0x0000, 0x33b6,\n0x33d3, 0x8f60, 0x0000, 0x33f0, 0x340c, 0x3428, 0x3445, 0x8fad,\n0x0000, 0x8fc8, 0x0000, 0x3462, 0x347e, 0x8ffb, 0x0000, 0x5f44,\n0x0000, 0x28a5, 0x28ae, 0x28b7, 0x0000, 0x9065, 0x0000, 0x349a,\n0x34b4, 0x34ce, 0x34ec, 0x350a, 0x3526, 0x0000, 0x0000, 0x3542,\n0x355f, 0x357c, 0x359a, 0x35b8, 0x35cc, 0x0000, 0x90c5, 0x0000,\n0x0000, 0x3694, 0x36a6, 0x36ba, 0x36cc, 0x36f1, 0x3705, 0x3728,\n0x374d, 0x3770, 0x3795, 0x37ba, 0x37cd, 0x37e1, 0x3801, 0x2731,\n0x3841, 0x2743, 0x3864, 0x3878, 0x388a, 0x38af, 0x38c3, 0x38e6,\n0x390b, 0x35e0, 0x35f5, 0x3978, 0x398b, 0x399f, 0x39bf, 0x39d9,\n0x39ff, 0x3a11, 0x3a22, 0x360a, 0x3622, 0x3a59, 0x3a6b, 0x3a7d,\n0x3a90, 0x363a, 0x364f, 0x3ac9, 0x3adb, 0x3aed, 0x3aff, 0x3664,\n0x367c, 0x3b34, 0x3b46, 0x3b58, 0x3b6a, 0x3b7c, 0x3b8d, 0x3ba0,\n0x3bb2, 0x3bca, 0x3bde, 0x3bf0, 0x381b, 0x3c14, 0x3c29, 0x3c3c,\n0x3c54, 0x3c66, 0x3852, 0x3c89, 0x3c9c, 0x3cae, 0x3cc0, 0x3cd2,\n0x3ce5, 0x3cf7, 0x3d08, 0x3d1e, 0x3d30, 0x3d42, 0x3d54, 0x3d66,\n0x3d77, 0x3d89, 0x3d9b, 0x3dad, 0x3dbf, 0x3dd1, 0x3de2, 0x3df5,\n0x3e07, 0x3e1f, 0x392e, 0x3e45, 0x3e58, 0x3953, 0x3e7e, 0x3e91,\n0x0000, 0x79b6, 0x0000, 0x7418, 0x9281, 0x0000, 0x0000, 0x9291,\n0x0000, 0x0000, 0x92a0, 0x0000, 0x0000, 0x92b0, 0x0000, 0x0000,\n0x7a27, 0x0000, 0x6445, 0x646b, 0x6491, 0x64b7, 0x64db, 0x6503,\n0x3a34, 0x6549, 0x656d, 0x3a47, 0x65b7, 0x65dd, 0x6605, 0x662b,\n0x6651, 0x6677, 0x669b, 0x66c1, 0x66e9, 0x6711, 0x6737, 0x675b,\n0x677f, 0x67a5, 0x3aa2, 0x67ef, 0x6813, 0x3ab3, 0x685b, 0x687f,\n0x68a5, 0x68cd, 0x68f1, 0x6917, 0x693f, 0x6967, 0x698b, 0x69ad,\n0x0000, 0x0000, 0x9382, 0x69d1, 0x3b11, 0x63bf, 0x635f, 0x3b22,\n0x0000, 0x0000, 0x6458, 0x647e, 0x64a4, 0x251b, 0x64ef, 0x2531,\n0x6538, 0x655b, 0x657f, 0x2540, 0x65ca, 0x254d, 0x6618, 0x663e,\n0x6664, 0x6689, 0x66ae, 0x66d5, 0x66fd, 0x255c, 0x6749, 0x256a,\n0x6792, 0x2579, 0x67dc, 0x6801, 0x6825, 0x6849, 0x686d, 0x6892,\n0x68b9, 0x68df, 0x6904, 0x692b, 0x6953, 0x6979, 0x699c, 0x69bf,\n0x6313, 0x0000, 0x632e, 0x6391, 0xa4c1, 0x0000, 0xa4da, 0x0000,\n0x9acb, 0x0000, 0xa4eb, 0x0000, 0xa508, 0x25b1, 0xa51e, 0x25bf,\n0x0000, 0x25ce, 0x0000, 0x25db, 0x942f, 0x0000, 0x0000, 0x25e5,\n0x0000, 0x25ef, 0x944e, 0x0000, 0x0000, 0x945c, 0x0000, 0x0000,\n0x946b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9479, 0x6cfb,\n0x0000, 0x0000, 0x0000, 0x0000, 0x9488, 0x0000, 0xac73, 0x9497,\n0x0000, 0x0000, 0x94a5, 0x0000, 0xa541, 0x94b4, 0x0000, 0x0000,\n0x94c3, 0x3ea9, 0x3ec1, 0x3edb, 0x3ef1, 0x3f08, 0x94e0, 0x3f3b,\n0x3f55, 0x3f6f, 0x0000, 0x3f8b, 0x0000, 0x0000, 0x3fa3, 0x3fbe,\n0x0000, 0x3fd3, 0x3feb, 0x2655, 0x401b, 0x4032, 0x404b, 0x406a,\n0x4084, 0x409e, 0x40ba, 0x40dc, 0x0000, 0x3e33, 0x0000, 0x0000,\n0x0000, 0x40f4, 0x4106, 0x4117, 0x4129, 0x413b, 0x3e69, 0x4160,\n0x4170, 0x4182, 0x4193, 0x41a5, 0x41ca, 0x41d9, 0x41e8, 0x41f7,\n0x420b, 0x421a, 0x422a, 0x0000, 0x423c, 0x424c, 0x4260, 0x4270,\n0x4280, 0x4290, 0x0000, 0x0000, 0x9e31, 0x0000, 0x0000, 0x0000,\n0x0000, 0x42a2, 0x42b4, 0x42c5, 0x42d7, 0x42e9, 0x42fd, 0x430e,\n0x431e, 0x4330, 0x4341, 0x4353, 0x4378, 0x4387, 0x4396, 0x43a5,\n0x43b9, 0x43c8, 0x43d8, 0x43ea, 0x4406, 0x4416, 0x442a, 0x443a,\n0x444a, 0x445a, 0xa569, 0x760f, 0x7623, 0x7636, 0x7649, 0x765e,\n0x7672, 0x7686, 0x7699, 0x76ae, 0x76c3, 0x0000, 0x9fbc, 0x0000,\n0xa5ee, 0x0000, 0xa601, 0x0000, 0xa614, 0x0000, 0xa627, 0x0000,\n0xa01c, 0x0000, 0xa02b, 0x0000, 0xa03d, 0x0000, 0xa04b, 0x6527,\n0xa05b, 0x0000, 0xa06c, 0x74b8, 0x74c6, 0x74d6, 0x74e9, 0x74fa,\n0x7509, 0x7518, 0x7528, 0x7539, 0x7549, 0x7557, 0x756b, 0x0000,\n0xa57c, 0x0000, 0xa70c, 0x0000, 0xa721, 0x0000, 0x5f5a, 0x0000,\n0xa0cf, 0x0000, 0xa0e5, 0x0000, 0x3259, 0x3272, 0x328b, 0x0000,\n0x743c, 0x0000, 0xa12f, 0x0000, 0xa145, 0x0000, 0xa162, 0x0000,\n0x0000, 0x2e20, 0x2e2f, 0x2e3e, 0x2e4d, 0x2e5c, 0x2e6b, 0x2e7a,\n0x2e89, 0x2e98, 0x2ea7, 0x2d6a, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x2d7f, 0x0000, 0x0000, 0x8427, 0x0000, 0x601e, 0x0000,\n0x0000, 0x0000, 0x2d9d, 0x6038, 0x0000, 0x8471, 0x0000, 0x2daf,\n0x6052, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2dc0,\n0x0000, 0x2dd3, 0x6085, 0x0000, 0x9644, 0x0000, 0xa63d, 0x60a0,\n0x0000, 0x0000, 0x2de5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x32a4, 0xa7be, 0x0000, 0xa667, 0x0000, 0x60e4, 0x0000,\n0xa7fd, 0x0000, 0xa814, 0x60fd, 0xa828, 0x32b5, 0xa83e, 0x0000,\n0xa855, 0x0000, 0x32c6, 0x0000, 0x6417, 0x612a, 0xa87f, 0x0000,\n0x32d9, 0x0000, 0xa8ae, 0x0000, 0xa8cc, 0x0000, 0x0000, 0x0000,\n0xa6b6, 0x863f, 0xa8e9, 0x32ea, 0xa901, 0x0000, 0x64c9, 0x3303,\n0x0000, 0x447f, 0x335e, 0x44a6, 0x44bb, 0x44cd, 0x44df, 0x44f3,\n0x450a, 0x4521, 0x4539, 0x4551, 0x4565, 0x3320, 0x458e, 0x45a3,\n0x45be, 0x45da, 0x45f1, 0x3347, 0x4628, 0x2e0a, 0x4660, 0x4678,\n0x0000, 0x0000, 0xa919, 0x0000, 0x4693, 0x46a7, 0x46b6, 0x46cd,\n0x46dc, 0x46ec, 0x46fc, 0x8790, 0xa9b6, 0x470b, 0xa9d5, 0x0000,\n0x4717, 0x4729, 0xa9fb, 0x0000, 0xaa0c, 0x473c, 0x474b, 0x4759,\n0x0000, 0x2cde, 0x2cec, 0x2cfa, 0x2d08, 0x2d16, 0x2d24, 0x2d32,\n0x2d40, 0x2d4e, 0x2d5c, 0x4788, 0x4797, 0x47aa, 0x47b6, 0x47c7,\n0x0000, 0x8880, 0x0000, 0x90fd, 0xaaf7, 0x0000, 0x0000, 0x6d98,\n0xab23, 0x0000, 0x88cc, 0x9118, 0x0000, 0x0000, 0x0000, 0x47d7,\n0xab89, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x47ef, 0x0000,\n0x0000, 0x8944, 0xa11e, 0x47fe, 0x480e, 0x481c, 0x482d, 0x8976,\n0x0000, 0xa177, 0xa18d, 0xa1a3, 0xa1b9, 0xa1cf, 0xa1e5, 0xa1fb,\n0xa211, 0xa227, 0xa23d, 0xa254, 0xa26b, 0x0000, 0x0000, 0x9196,\n0x0000, 0x0000, 0x0000, 0x91a4, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0xa282, 0xa293, 0xa2a7, 0x91b2, 0xa2d1, 0xa2e9, 0x0000, 0x91c0,\n0x0000, 0x8acf, 0x0000, 0x91cf, 0x8ae7, 0x0000, 0x0000, 0x78da,\n0x0000, 0x0000, 0x0000, 0x78f0, 0xadae, 0x0000, 0x0000, 0x91fb,\n0xadd2, 0x0000, 0x0000, 0x791b, 0x0000, 0x0000, 0x0000, 0x7931,\n0x0000, 0x0000, 0x0000, 0x28d7, 0xae3e, 0x28eb, 0x0000, 0x795d,\n0x0000, 0x0000, 0x0000, 0x7973, 0x0000, 0x0000, 0x0000, 0x7989,\n0xaeaa, 0x0000, 0x0000, 0x79a0, 0x0000, 0x0000, 0x0000, 0x9272,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x8f14, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x2a3b, 0x0000, 0x2a48, 0x0000, 0x2a56,\n0x0000, 0x0000, 0x0000, 0x92de, 0x0000, 0x0000, 0x0000, 0x92ee,\n0x0000, 0x0000, 0x0000, 0x92fd, 0x0000, 0x76d7, 0x0000, 0x930d,\n0x76ee, 0x2ad5, 0x0000, 0x76fd, 0x770d, 0x0000, 0x7720, 0x7ac6,\n0x0000, 0x2b2b, 0xa2ff, 0x932b, 0x0000, 0xac11, 0x0000, 0x9339,\n0x0000, 0x2b63, 0x0000, 0x2b71, 0x0000, 0x2b7f, 0x7742, 0x2b8d,\n0x0000, 0x2b9b, 0x0000, 0x2bb7, 0x0000, 0x2bc5, 0x0000, 0x2bd3,\n0x0000, 0x2be1, 0x0000, 0x2bef, 0x0000, 0x2bfd, 0x0000, 0x2c0b,\n0x7772, 0x2c19, 0x8efc, 0x2c27, 0x0000, 0x2c35, 0x0000, 0x939e,\n0x7782, 0x0000, 0x0000, 0x8f46, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x8f79, 0x0000, 0x93ac, 0x8f93, 0x0000, 0x0000, 0x93ba,\n0x0000, 0x0000, 0x779f, 0x745e, 0x0000, 0x7474, 0x0000, 0x93d9,\n0x0000, 0x7448, 0x0000, 0x9015, 0x0000, 0x0000, 0x9030, 0x93f5,\n0x0000, 0x904a, 0x0000, 0x9404, 0x0000, 0x748a, 0x0000, 0x9080,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x77b1, 0x77c4, 0x483d,\n0x4849, 0x485c, 0x486f, 0x4878, 0x4881, 0x488a, 0x0000, 0x0000,\n0x4893, 0x489c, 0x48a5, 0x48ba, 0x48ce, 0x48e1, 0x48f5, 0x4909,\n0x491e, 0x4933, 0x4948, 0x495d, 0x4972, 0x497e, 0x498b, 0x4996,\n0x49a1, 0x0000, 0x0000, 0x0000, 0xa32d, 0x0000, 0x0000, 0x943e,\n0x0000, 0x9534, 0x9547, 0x9561, 0x957d, 0x9595, 0x95af, 0x95cb,\n0x0000, 0x749f, 0x0000, 0x0000, 0x0000, 0xa33c, 0x0000, 0x0000,\n0x95e8, 0x95fa, 0x9615, 0x9629, 0x4fd8, 0x9658, 0x966c, 0x9680,\n0x9694, 0x96a7, 0x96b6, 0x96c6, 0x96d7, 0x96ed, 0x9702, 0x9711,\n0x9724, 0x9737, 0x974b, 0x9764, 0x9777, 0x978c, 0x97a2, 0x97b1,\n0x97c3, 0x97d2, 0x97e4, 0x60cf, 0x9808, 0x9818, 0x982e, 0x94d1,\n0x984c, 0x9860, 0x9875, 0x988a, 0x989f, 0x98b4, 0x98c8, 0x94ef,\n0x98e9, 0x98fb, 0x9911, 0x9924, 0x993f, 0x9951, 0x9965, 0x997b,\n0x9991, 0x99a3, 0x99b5, 0x99c7, 0x99d9, 0x99eb, 0x99fd, 0x7f26,\n0x9a21, 0x9a33, 0x9a45, 0x9a57, 0x9a69, 0x9a7b, 0x9a8d, 0x9a9f,\n0x9ab1, 0x676d, 0x9ae6, 0x9af5, 0x9b02, 0x9b17, 0x9b27, 0x9b37,\n0x9b46, 0x9b54, 0x92bf, 0x9b74, 0x9b88, 0x9b98, 0x9bab, 0x9bba,\n0x9bc7, 0x9bd8, 0x9be9, 0x9bfa, 0x0000, 0x9c0c, 0x9c1d, 0x9c2e,\n0x9c40, 0x9c4e, 0x9a0f, 0x9c72, 0x9c81, 0x9c92, 0x9ca2, 0x0000,\n0x9cb2, 0x0000, 0x9cbe, 0x9cce, 0x9cdf, 0x9cf7, 0x9d0c, 0x9d21,\n0x9d30, 0x9d43, 0x9d58, 0x9d6e, 0x9d7d, 0x9d8d, 0x9da3, 0x9db5,\n0x9dc8, 0x9ddb, 0x9deb, 0x0000, 0x9dfc, 0x9e0d, 0x9e1f, 0x950e,\n0x9e41, 0x9e57, 0x9e66, 0x9e75, 0x9e86, 0x9e98, 0x9ea7, 0x9ebb,\n0x9ecc, 0x9ee2, 0x9ef5, 0x9f05, 0x9f17, 0x9f2b, 0x9f3a, 0x9f48,\n0x9f5f, 0x9f75, 0x9f8f, 0x9fa2, 0x759c, 0x9fd1, 0x9fe5, 0x9ffc,\n0xa00b, 0x49af, 0x49bd, 0x49cb, 0x49da, 0x49e9, 0x49fa, 0x4a0b,\n0x4a1b, 0x4a2b, 0x4a38, 0x75fc, 0x4a45, 0xa6f9, 0x4a57, 0x4a66,\n0x4a7c, 0x4a8b, 0x4a9b, 0x4aaa, 0x4aba, 0x4acc, 0x4add, 0x4aec,\n0x4afd, 0x0000, 0x0000, 0x4b0a, 0x4b18, 0x4b2f, 0x4b42, 0x4b5a,\n0x0000, 0x0000, 0x0000, 0x4b67, 0x4b77, 0x4b8a, 0x4b9c, 0x6d40,\n0x0000, 0x4baf, 0x4bbf, 0x4bd3, 0x4beb, 0x4c02, 0x4c1a, 0x4c2d,\n0x4c43, 0x4c5d, 0x4c78, 0x4c92, 0x4cad, 0x4cc0, 0x4ccf, 0x4cdd,\n0xa7eb, 0x4ceb, 0x4cfc, 0x4d0b, 0x4d22, 0x4d3c, 0x4d57, 0x4d6c,\n0x4d7f, 0x4d96, 0x4daf, 0x4dc4, 0x4dda, 0x4df2, 0x4e01, 0x4e1a,\n0x4e31, 0x4e49, 0x4e63, 0x4e75, 0x4e88, 0x4e93, 0x4ea1, 0x0000,\n0x4ead, 0x4ec0, 0x4ecd, 0x4ee0, 0x4ef0, 0x4f02, 0x4f15, 0x4f27,\n0x4f38, 0x4f4b, 0x4f5b, 0x4f73, 0x4f8d, 0x4f99, 0x4fb2, 0x4fcb,\n0xaa1f, 0xaa32, 0xaa49, 0xaa5d, 0xaa71, 0xa654, 0xaa96, 0xaaad,\n0xaac2, 0xaad8, 0xaae6, 0x6a6e, 0xab0d, 0x6a81, 0xab32, 0xab4d,\n0xab6b, 0xa67a, 0xab9f, 0xabb9, 0xabd9, 0xabf0, 0xabfe, 0x840d,\n0xac28, 0xac43, 0xac5c, 0x6d5b, 0xac8e, 0xa6a0, 0xacbb, 0x0000,\n0x0000, 0x910b, 0x0000, 0xa07b, 0x0000, 0x0000, 0xaccd, 0xacde,\n0xacef, 0xa08d, 0xaa85, 0xad22, 0xad33, 0xad44, 0xad55, 0xa0a1,\n0xad78, 0xad8a, 0xad9c, 0x6bed, 0xadc0, 0x6c00, 0xade4, 0xadf6,\n0xae08, 0xae1a, 0xae2c, 0xa6ca, 0xae50, 0xae62, 0xae74, 0xae86,\n0xae98, 0xa6e1, 0xaebc, 0xaece, 0x0000, 0x0000, 0xaee0, 0xaefb,\n0xaf15, 0xaf30, 0xaf47, 0xaf5e, 0x0000, 0x0000, 0xaf75, 0xaf8b,\n0xafa1, 0xafb7, 0xafcd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0xa0ba, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x85cc, 0x0000, 0xa762, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0xa779, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0xa793, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2eb6,\n0x0000, 0x0000, 0x0000, 0x91dd, 0x0000, 0x0000, 0x98d7, 0x866f,\n0x91ec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x869f,\n0x0000, 0xa68d, 0x920a, 0x0000, 0x0000, 0xa3bf, 0x0000, 0x86cf,\n0x0000, 0x0000, 0x0000, 0x0000, 0x7948, 0x0000, 0x0000, 0x8700,\n0x0000, 0x9235, 0x0000, 0x8719, 0x0000, 0x0000, 0x9244, 0x8732,\n0x0000, 0x0000, 0x0000, 0x302f, 0x0000, 0x303f, 0x4fe8, 0x0000,\n0x4ff9, 0x5009, 0x0000, 0xa414, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa427, 0x0000, 0x87bf,\n0x0000, 0x0000, 0xa43b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x5017, 0x0000, 0x5025, 0x5034, 0x5041, 0x0000, 0x5051, 0x881f,\n0x0000, 0xa318, 0x5060, 0x3137, 0x506a, 0x3149, 0x5075, 0x5082,\n0x0000, 0x0000, 0xaca5, 0x508f, 0x0000, 0x0000, 0x509d, 0x0000,\n0x50ac, 0x0000, 0x50bc, 0x0000, 0x50cb, 0xa7aa, 0x0000, 0x88b2,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x931b, 0x0000, 0x0000, 0xa494, 0x6ced, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x9348, 0x0000, 0x0000, 0x895d, 0x50da, 0x9356, 0x0000, 0x0000,\n0x0000, 0x0000, 0x9365, 0x0000, 0x0000, 0x0000, 0x0000, 0x9373,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x9390, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xad00, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9b66, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x93c9, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x93e7, 0x8aff,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9227,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8b5f,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8bc2,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8c23,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9420, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9c5d, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x757a, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x73fe, 0x0000, 0x51f2, 0x0000,\n0x740b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x7790, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0xa552, 0x0000, 0x0000, 0x0000, 0x4579, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x50ea,\n0x5105, 0x5118, 0x513b, 0x5162, 0x5189, 0x5199, 0x51aa, 0x51cf,\n0x4608, 0x5215, 0x5226, 0x523d, 0x524f, 0x5262, 0x5278, 0x5289,\n0x529f, 0x52b0, 0x52d8, 0x52ea, 0x52ff, 0x530f, 0x533d, 0x5361,\n0x5384, 0x5396, 0x53a8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8fe1,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\n0x0000, 0x0000, 0x0000\n};\n#endif /* NEEDVTABLE */\n"
  },
  {
    "path": "common/rfb/ledStates.h",
    "content": "/* Copyright 2016 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_LEDSTATES_H__\n#define __RFB_LEDSTATES_H__\n\nnamespace rfb {\n\n  const unsigned int ledScrollLock = 1 << 0;\n  const unsigned int ledNumLock = 1 << 1;\n  const unsigned int ledCapsLock = 1 << 2;\n\n  const unsigned int ledUnknown = (unsigned int)-1;\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/msgTypes.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_MSGTYPES_H__\n#define __RFB_MSGTYPES_H__\n\nnamespace rfb {\n  // server to client\n\n  const int msgTypeFramebufferUpdate = 0;\n  const int msgTypeSetColourMapEntries = 1;\n  const int msgTypeBell = 2;\n  const int msgTypeServerCutText = 3;\n\n  const int msgTypeEndOfContinuousUpdates = 150;\n\n  const int msgTypeServerFence = 248;\n\n  // client to server\n\n  const int msgTypeSetPixelFormat = 0;\n  const int msgTypeFixColourMapEntries = 1;\n  const int msgTypeSetEncodings = 2;\n  const int msgTypeFramebufferUpdateRequest = 3;\n  const int msgTypeKeyEvent = 4;\n  const int msgTypePointerEvent = 5;\n  const int msgTypeClientCutText = 6;\n\n  const int msgTypeEnableContinuousUpdates = 150;\n\n  const int msgTypeClientFence = 248;\n\n  const int msgTypeSetDesktopSize = 251;\n\n  const int msgTypeQEMUClientMessage = 255;\n}\n#endif\n"
  },
  {
    "path": "common/rfb/obfuscate.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2023 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n//\n// XXX not thread-safe, because d3des isn't - do we need to worry about this?\n//\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <string.h>\n\n#include <stdexcept>\n\nextern \"C\" {\n#include <rfb/d3des.h>\n}\n\n#include <rfb/obfuscate.h>\n\nstatic unsigned char d3desObfuscationKey[] = {23,82,107,6,35,78,88,7};\n\nstd::vector<uint8_t> rfb::obfuscate(const char *str)\n{\n  std::vector<uint8_t> buf(8);\n\n  assert(str != nullptr);\n\n  size_t l = strlen(str), i;\n  for (i=0; i<8; i++)\n    buf[i] = i<l ? str[i] : 0;\n  deskey(d3desObfuscationKey, EN0);\n  des(buf.data(), buf.data());\n\n  return buf;\n}\n\nstd::string rfb::deobfuscate(const uint8_t *data, size_t len)\n{\n  char buf[9];\n\n  if (len != 8)\n    throw std::invalid_argument(\"Bad obfuscated password length\");\n\n  assert(data != nullptr);\n\n  deskey(d3desObfuscationKey, DE1);\n  des((uint8_t*)data, (uint8_t*)buf);\n  buf[8] = 0;\n\n  return buf;\n}\n"
  },
  {
    "path": "common/rfb/obfuscate.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2023 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_OBFUSCATE_H__\n#define __RFB_OBFUSCATE_H__\n\n#include <stdint.h>\n\n#include <string>\n#include <vector>\n\nnamespace rfb {\n\n  std::vector<uint8_t> obfuscate(const char *str);\n  std::string deobfuscate(const uint8_t *data, size_t len);\n\n}\n\n#endif\n"
  },
  {
    "path": "common/rfb/qemuTypes.h",
    "content": "/* Copyright 2017 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_QEMUTYPES_H__\n#define __RFB_QEMUTYPES_H__\n\nnamespace rfb {\n  const int qemuExtendedKeyEvent = 0;\n  const int qemuAudio = 1;\n}\n#endif\n"
  },
  {
    "path": "common/rfb/screenTypes.h",
    "content": "/* Copyright 2009 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __RFB_SCREENTYPES_H__\n#define __RFB_SCREENTYPES_H__\n\nnamespace rfb {\n\n  // Reasons\n  const unsigned int reasonServer = 0;\n  const unsigned int reasonClient = 1;\n  const unsigned int reasonOtherClient = 2;\n\n  // Result codes\n  const unsigned int resultSuccess = 0;\n  const unsigned int resultProhibited = 1;\n  const unsigned int resultNoResources = 2;\n  const unsigned int resultInvalid = 3;\n\n  const int resultUnsolicited = 0xffff; // internal code used for server changes\n\n}\n#endif\n"
  },
  {
    "path": "config.h.in",
    "content": "#define PACKAGE_NAME \"@CMAKE_PROJECT_NAME@\"\n#define PACKAGE_VERSION \"@VERSION@\"\n\n#cmakedefine ENABLE_NLS 1\n\n#cmakedefine CMAKE_INSTALL_FULL_LIBEXECDIR \"@CMAKE_INSTALL_FULL_LIBEXECDIR@\"\n#cmakedefine CMAKE_INSTALL_FULL_DATADIR \"@CMAKE_INSTALL_FULL_DATADIR@\"\n#cmakedefine CMAKE_INSTALL_FULL_LOCALEDIR \"@CMAKE_INSTALL_FULL_LOCALEDIR@\"\n\n/* MS Visual Studio 2008 and newer doesn't know ssize_t */\n#if defined(HAVE_GNUTLS) && defined(WIN32) && !defined(__MINGW32__)\n    #if defined(_WIN64)\n        typedef __int64 ssize_t;\n    #else\n        typedef long ssize_t;\n    #endif\n#endif\n\n/* We know we use deprecated stuff, it's to support older macOS */\n#if defined(__APPLE__) && defined(__clang__)\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n#endif\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/changelog",
    "content": "tigervnc (1.11.80) focal; urgency=low\n\n  * Initial release.\n\n -- Brian P. Hinz <bphinz@users.sourceforge.net>  Sat, 19 Dec 2020 15:27:35 -0400\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/compat",
    "content": "10\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/control",
    "content": "Source: tigervnc\nSection: x11\nPriority: optional\nMaintainer: Brian P. Hinz <bphinz@users.sourceforge.net>\nStandards-Version: 3.8.4\nBuild-Depends:\n# TigerVNC dependencies\n debhelper (>= 9),\n dh-autoreconf,\n po-debconf,\n dpkg-dev (>= 1.16.1),\n appstream,\n cmake,\n gettext,\n zlib1g-dev,\n libjpeg-turbo8-dev,\n libavcodec-dev,\n libavutil-dev,\n libswscale-dev,\n libgnutls28-dev,\n libgmp-dev,\n libpam0g-dev,\n libpng-dev,\n libxrandr-dev,\n libxdamage-dev,\n libfltk1.3-dev,\n xorg-server-source,\n xserver-xorg-dev,\n openjdk-8-jdk,\n uuid-dev,\n libglib2.0-dev,\n libpipewire-0.3-dev,\n libwayland-dev,\n libxkbcommon-dev,\n# Xorg dependencies\n# debhelper-compat (= 12),\n po-debconf,\n quilt,\n pkg-config,\n bison,\n flex,\n xutils-dev (>= 1:7.6+4),\n xfonts-utils (>= 1:7.5+1),\n x11proto-dev (>= 2021.5),\n xtrans-dev (>= 1.3.5),\n libxau-dev (>= 1:1.0.5-2),\n libxcvt-dev,\n libxdmcp-dev (>= 1:0.99.1),\n libxfont-dev (>= 1:2.0.1),\n libxkbfile-dev (>= 1:0.99.1),\n libpixman-1-dev (>= 0.27.2),\n libpciaccess-dev (>= 0.12.901),\n libgcrypt-dev,\n nettle-dev,\n libudev-dev (>= 151-3) [linux-any],\n libselinux1-dev (>= 2.0.80) [linux-any],\n libaudit-dev [linux-any],\n libdrm-dev (>= 2.4.107-5~) [!hurd-i386],\n libgl1-mesa-dev (>= 9.2),\n mesa-common-dev,\n# Don't use libunwind for armel, armhf, and arm64 as this library is buggy (bug #923962) on those architectures.\n libunwind-dev [amd64 hppa i386 ia64 mips64 mips64el mipsel powerpc powerpcspe ppc64 ppc64el sh4],\n libxmuu-dev (>= 1:0.99.1),\n libxext-dev (>= 1:0.99.1),\n libx11-dev (>= 2:1.6),\n libxrender-dev (>= 1:0.9.0),\n libxi-dev (>= 2:1.8),\n libxpm-dev (>= 1:3.5.3),\n libxaw7-dev (>= 1:0.99.1),\n libxt-dev (>= 1:0.99.1),\n libxmu-dev (>= 1:0.99.1),\n libxtst-dev (>= 1:0.99.1),\n libxres-dev (>= 1:0.99.1),\n libxfixes-dev (>= 1:3.0.0),\n libxv-dev,\n libxinerama-dev,\n libxshmfence-dev (>= 1.1) [!hurd-i386],\n# glamor\n libepoxy-dev [linux-any kfreebsd-any],\n libegl1-mesa-dev [linux-any kfreebsd-any],\n libgbm-dev (>= 10.2) [linux-any kfreebsd-any],\n## XCB bits for Xephyr\n# libx11-xcb-dev,\n# libxcb1-dev,\n# libxcb-xkb-dev,\n# libxcb-shape0-dev,\n# libxcb-render0-dev,\n# libxcb-render-util0-dev,\n# libxcb-util0-dev,\n# libxcb-image0-dev,\n# libxcb-icccm4-dev,\n# libxcb-shm0-dev,\n# libxcb-keysyms1-dev,\n# libxcb-randr0-dev,\n# libxcb-xv0-dev,\n# libxcb-glx0-dev,\n# libxcb-xf86dri0-dev (>= 1.6),\n# unit tests\n xkb-data,\n x11-xkb-utils,\n# arc4random_buf(), getpeereid()\n libbsd-dev,\n#logind\n  libdbus-1-dev (>= 1.0) [linux-any],\n# systemd-daemon\n  libsystemd-dev [linux-any],\nHomepage: http://www.tigervnc.com\n\nPackage: tigervncserver\nArchitecture: any\nProvides:\n xserver,\n vnc-server\nDepends:\n x11-common | xserver-common,\n x11-utils,\n xauth,\n x11-xkb-utils,\n ${shlibs:Depends},\n ${perl:Depends},\n ${misc:Depends}\nRecommends:\n xfonts-base,\n x11-xserver-utils\nSuggests:\n xtigervncviewer,\n tigervnc-java\nDescription: virtual network computing server software\n Virtual Network Computing (VNC) is a remote display system which allows you to\n view and interact with a virtual desktop environment that is running on another\n computer on the network.  Using VNC, you can run graphical applications on a\n remote machine and send only the display from these applications to your local\n machine.  VNC is platform-independent and supports a wide variety of operating\n systems and architectures as both servers and clients.\n .\n TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code\n bases.  TigerVNC started as a next-generation development effort for TightVNC\n on Unix and Linux platforms, but it split from its parent project in early 2009\n so that TightVNC could focus on Windows platforms.  TigerVNC supports a variant\n of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo\n JPEG codec.\n\nPackage: xtigervncviewer\nArchitecture: any\nProvides:\n vncviewer,\n vnc-viewer\nDepends:\n ${shlibs:Depends},\n ${misc:Depends}\nRecommends:\n xfonts-base\nSuggests:\n tigervncserver,\n ssh\nDescription: virtual network computing client software for X\n Virtual Network Computing (VNC) is a remote display system which allows you to\n view and interact with a virtual desktop environment that is running on another\n computer on the network.  Using VNC, you can run graphical applications on a\n remote machine and send only the display from these applications to your local\n machine.  VNC is platform-independent and supports a wide variety of operating\n systems and architectures as both servers and clients.\n .\n TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code\n bases.  TigerVNC started as a next-generation development effort for TightVNC\n on Unix and Linux platforms, but it split from its parent project in early 2009\n so that TightVNC could focus on Windows platforms.  TigerVNC supports a variant\n of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo\n JPEG codec.\n\nPackage: tigervnc-java\nArchitecture: any\nSuggests:\n tigervncserver\nProvides:\n vncviewer,\n vnc-viewer\nDepends:\n default-jre\nDescription: TigerVNC java applet\n Virtual Network Computing (VNC) is a remote display system which allows you to\n view and interact with a virtual desktop environment that is running on another\n computer on the network.  Using VNC, you can run graphical applications on a\n remote machine and send only the display from these applications to your local\n machine.  VNC is platform-independent and supports a wide variety of operating\n systems and architectures as both servers and clients.\n .\n TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code\n bases.  TigerVNC started as a next-generation development effort for TightVNC\n on Unix and Linux platforms, but it split from its parent project in early 2009\n so that TightVNC could focus on Windows platforms.  TigerVNC supports a variant\n of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo\n JPEG codec.\n\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/copyright",
    "content": "This package was packaged for Debian by Brian P. Hinz <bphinz@users.sourceforge.net>\non Mon, 28 Oct 2019 21:29:33 +0500 using the tightvnc package as a base.\n\nIt was downloaded from:\n\thttps://www.tigervnc.org/\n\nCOPYRIGHT:\n==========\n\nTigerVNC is\n\n        Copyright (C) 1999 AT&T Laboratories Cambridge\n        Copyright (C) 2002-2005 RealVNC Ltd.\n        Copyright (C) 2000-2006 TightVNC Group\n        Copyright (C) 2005-2006 Martin Koegler\n        Copyright (C) 2005-2006 Sun Microsystems, Inc.\n        Copyright (C) 2006 OCCAM Financial Technology\n        Copyright (C) 2000-2008 Constantin Kaplinsky\n        Copyright (C) 2004-2017 Peter Astrand for Cendio AB\n        Copyright (C) 2010 Antoine Martin\n        Copyright (C) 2010 m-privacy GmbH\n        Copyright (C) 2009-2011 D. R. Commander\n        Copyright (C) 2009-2011 Pierre Ossman for Cendio AB\n        Copyright (C) 2004, 2009-2011 Red Hat, Inc.\n        Copyright (C) 2009-2024 TigerVNC Team\n        All Rights Reserved.\n\nThis software is distributed under the GNU General Public Licence as published\nby the Free Software Foundation.  See the file LICENCE.TXT for the conditions\nunder which this software is made available.  TigerVNC also contains code from\nother sources.  See the Acknowledgements section below, and the individual\nsource files, for details of the conditions under which they are made\navailable.\n\nACKNOWLEDGEMENTS\n================\n\nThis distribution contains zlib compression software.  This is:\n\n  Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n\n  Jean-loup Gailly        Mark Adler\n  jloup@gzip.org          madler@alumni.caltech.edu\n\n  The data format used by the zlib library is described by RFCs (Request for\n  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt\n  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).\n\n\nThis distribution contains public domain DES software by Richard Outerbridge.\nThis is:\n\n    Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.\n    (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.\n\n\nThis distribution contains software from the X Window System.  This is:\n\n Copyright 1987, 1988, 1998  The Open Group\n \n Permission to use, copy, modify, distribute, and sell this software and its\n documentation for any purpose is hereby granted without fee, provided that\n the above copyright notice appear in all copies and that both that\n copyright notice and this permission notice appear in supporting\n documentation.\n \n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\n OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\n AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n \n Except as contained in this notice, the name of The Open Group shall not be\n used in advertising or otherwise to promote the sale, use or other dealings\n in this Software without prior written authorization from The Open Group.\n \n \n Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.\n \n                         All Rights Reserved\n \n Permission to use, copy, modify, and distribute this software and its \n documentation for any purpose and without fee is hereby granted, \n provided that the above copyright notice appear in all copies and that\n both that copyright notice and this permission notice appear in \n supporting documentation, and that the name of Digital not be\n used in advertising or publicity pertaining to distribution of the\n software without specific, written prior permission.  \n \n DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\n ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\n DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\n ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\n WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\n ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\n SOFTWARE.\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/rules",
    "content": "#!/usr/bin/make -f\n# Sample debian/rules that uses debhelper.\n# GNU copyright 1997 by Joey Hess.\nexport DEB_BUILD_MAINT_OPTIONS=hardening=+all\n\nCFLAGS   := $(shell dpkg-buildflags --get CFLAGS)\nCPPFLAGS := $(shell dpkg-buildflags --get CPPFLAGS)\nCXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS)\nLDFLAGS  := $(shell dpkg-buildflags --get LDFLAGS)\n\nexport CFLAGS CPPFLAGS CXXFLAGS LDFLAGS\n\nNUMJOBS := -j$(shell nproc)\n\n# Uncomment this to turn on verbose mode.\n#export DH_VERBOSE=1\n\nDEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)\nDEB_HOST_ARCH      ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)\nDEB_HOST_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)\nDEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)\nDEB_HOST_ARCH_OS   ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)\nifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))\n\tconfflags += --build=$(DEB_HOST_GNU_TYPE)\nelse\n\tconfflags += --build=$(DEB_BUILD_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE)\nendif\nSOURCE_NAME    := tigervnc\nSOURCE_VERSION := $(shell dpkg-parsechangelog | awk -F': ' '/^Version: / {print $$2}')\nBUILDER=For technical support please see http://sourceforge.net/projects/tigervnc/support\nlibdir = /usr/lib/$(DEB_HOST_MULTIARCH)\n\n\nifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))\n\tCFLAGS += -g -O2 -fPIC\nendif\nifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))\n\tINSTALL_PROGRAM += -s\nendif\n\nexport CC = gcc\n\n# use xorg sources as shipped in xorg-server-source package\nXORG_SOURCE_ARCHIVE = /usr/src/xorg-server.tar.xz\n\nxorg-source-stamp: $(XORG_SOURCE_ARCHIVE)\n\ttar -C unix/xserver -axf $(XORG_SOURCE_ARCHIVE) --strip-components=1\n\tcd unix/xserver && patch -p1 < ../xserver21.patch\n\tpatch -p1 < debian/xorg-source-patches/516_tigervnc-xorg-manpages.patch\n\ttouch xorg-source-stamp\n\nconfigure: config-stamp\nconfig-stamp: xorg-source-stamp\n\tdh_testdir\n\t# Add here commands to configure the package.\n\tcmake -G\"Unix Makefiles\" \\\n\t\t-DBUILD_STATIC=off \\\n\t\t-DENABLE_NLS=ON \\\n\t\t-DENABLE_H264=ON \\\n\t\t-DENABLE_GNUTLS=ON \\\n\t\t-DENABLE_NETTLE=ON \\\n\t\t-DENABLE_SYSTEMD=ON \\\n\t\t-DENABLE_WAYLAND=ON \\\n\t\t-DBUILD_VIEWER=ON \\\n\t\t-DCMAKE_INSTALL_PREFIX:PATH=/usr \\\n\t\t-DCMAKE_INSTALL_LIBEXECDIR:PATH=lib/$(DEB_HOST_MULTIARCH) \\\n\t\t-DCMAKE_INSTALL_UNITDIR:PATH=/lib/systemd/system\n\t(cd unix/xserver; \\\n\texport PIXMANINCDIR=/usr/include/pixman-1; \\\n\tautoreconf -fiv; \\\n  patch -p1 -i ../../debian/xorg-source-patches/debian_libtool.patch; \\\n\t./configure --prefix=/usr \\\n\t\t--disable-silent-rules \\\n\t\t--disable-static \\\n\t\t--without-dtrace \\\n\t\t--disable-strict-compilation \\\n\t\t--disable-debug \\\n\t\t--disable-unit-tests \\\n\t\t--with-int10=x86emu \\\n\t\t--with-extra-module-dir=\"/usr/lib/${DEB_HOST_MULTIARCH}/xorg/extra-modules,/usr/lib/xorg/extra-modules\" \\\n\t\t--with-os-vendor=\"$(VENDOR)\" \\\n\t\t--with-builderstring=\"$(SOURCE_NAME) $(SOURCE_VERSION) ($(BUILDER))\" \\\n\t\t--with-xkb-path=/usr/share/X11/xkb \\\n\t\t--with-xkb-output=/var/lib/xkb \\\n\t\t--with-default-xkb-rules=evdev \\\n\t\t--disable-devel-docs \\\n\t\t--enable-mitshm \\\n\t\t--enable-xres \\\n\t\t--disable-xcsecurity \\\n\t\t--disable-tslib \\\n\t\t--enable-dbe \\\n\t\t--disable-xf86bigfont \\\n\t\t--disable-dpms \\\n\t\t--disable-config-hal \\\n\t\t--disable-config-udev \\\n\t\t--disable-xorg \\\n\t\t--disable-xquartz \\\n\t\t--disable-xwin \\\n\t\t--disable-xfake \\\n\t\t--disable-install-setuid \\\n\t\t--with-default-font-path=\"/usr/share/fonts/X11/misc,/usr/share/fonts/X11/cyrillic,/usr/share/fonts/X11/100dpi/:unscaled,/usr/share/fonts/X11/75dpi/:unscaled,/usr/share/fonts/X11/Type1,/usr/share/fonts/X11/100dpi,/usr/share/fonts/X11/75dpi,/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType,built-ins\" \\\n\t\t--enable-aiglx \\\n\t\t--enable-composite \\\n\t\t--enable-record \\\n\t\t--enable-xv \\\n\t\t--enable-xvmc \\\n\t\t--enable-dga \\\n\t\t--enable-screensaver \\\n\t\t--enable-xdmcp \\\n\t\t--enable-xdm-auth-1 \\\n\t\t--enable-glx \\\n\t\t--disable-dri --enable-dri2 --enable-dri3 \\\n\t\t--enable-xinerama \\\n\t\t--enable-xf86vidmode \\\n\t\t--enable-xace \\\n\t\t--enable-xfree86-utils \\\n\t\t--disable-dmx \\\n\t\t--disable-xvfb \\\n\t\t--disable-xnest \\\n\t\t--disable-kdrive \\\n\t\t--disable-xephyr \\\n\t\t--enable-xfbdev \\\n\t\t--with-sha1=libgcrypt \\\n\t\t--enable-xcsecurity \\\n\t\t--disable-docs \\\n\t\t--disable-selective-werror)\n\ttouch config-stamp\n\nbuild-arch: config-stamp build-arch-stamp\nbuild-arch-stamp:\n\tdh_testdir\n\n\t# Add here command to compile/build the package.\n\t# Build first things.\n\t# Build Xvnc\n\tmake $(NUMJOBS) LDFLAGS=\"-lpng\" VERBOSE=1\n\tmake $(NUMJOBS) -C unix/xserver\n\n\ttouch build-arch-stamp\n\nbuild-indep: config-stamp  build-indep-stamp\nbuild-indep-stamp:\n\tdh_testdir\n\n\t# Add here command to compile/build the arch indep package.\n\t# It's ok not to do anything here, if you don't need to build\n\t#  anything for this package.\n\t#/usr/bin/docbook-to-man debian/vnc.sgml > vnc.1\n\t(cd media;make)\n\t#(cd java;cmake -G\"Unix Makefiles\";make)\n\n\ttouch build-indep-stamp\n\nbuild: build-arch build-indep\n\nclean:\n\tdh_testdir\n\tdh_testroot\n\trm -f build-arch-stamp build-indep-stamp config-stamp\n\n\t# Add here commands to clean up after the build process.\n\tdh_clean\n\ninstall: DH_OPTIONS=\ninstall: build\n\tdh_testdir\n\tdh_testroot\n\tdh_clean -k\n\tdh_prep\n\tdh_installdirs\n\t# Add here commands to install the package into debian/vnc.\n\tmake install DESTDIR=$(CURDIR)/debian/tigervncserver\n\t(cd unix/xserver/hw/vnc; make install DESTDIR=$(CURDIR)/debian/tigervncserver)\n\t# rename server files to tigervnc specific names\n\tmv $(CURDIR)/debian/tigervncserver/usr/bin/Xvnc \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/bin/Xtigervnc\n\tmv $(CURDIR)/debian/tigervncserver/usr/bin/vncconfig \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/bin/tigervncconfig\n\tmv $(CURDIR)/debian/tigervncserver/usr/bin/vncpasswd \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/bin/tigervncpasswd\n\tmv $(CURDIR)/debian/tigervncserver/usr/bin/x0vncserver \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/bin/x0tigervncserver\n\tmv $(CURDIR)/debian/tigervncserver/usr/sbin/vncsession \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/sbin/tigervncsession\n\tmv $(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/vncserver \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/tigervncserver\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncconfig.1 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncconfig.1\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncpasswd.1 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncpasswd.1\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0vncserver.1 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0tigervncserver.1\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xvnc.1 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xtigervnc.1\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncsession.8 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncsession.8\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncserver.8 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncserver.8\n\t# delete development files\n\trm -f $(CURDIR)/debian/tigervncserver/usr/lib/xorg/modules/extensions/libvnc.la\n\t# move viewer files to viewer package, rename on the fly\n\tmkdir -p $(CURDIR)/debian/xtigervncviewer/usr/bin\n\tmv $(CURDIR)/debian/tigervncserver/usr/bin/vncviewer \\\n\t\t$(CURDIR)/debian/xtigervncviewer/usr/bin/xtigervncviewer\n\tmkdir -p $(CURDIR)/debian/xtigervncviewer/usr/share/man/man1\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncviewer.1 \\\n\t\t$(CURDIR)/debian/xtigervncviewer/usr/share/man/man1/xtigervncviewer.1\n\tmkdir -p $(CURDIR)/debian/xtigervncviewer/usr/share\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/applications \\\n\t\t$(CURDIR)/debian/xtigervncviewer/usr/share/\n\tmkdir -p $(CURDIR)/debian/xtigervncviewer/usr/share\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/icons \\\n\t\t$(CURDIR)/debian/xtigervncviewer/usr/share/\n\t# tigervnc-java\n\t#mkdir -p $(CURDIR)/debian/tigervnc-java/usr/share\n\t#(cd java; make install DESTDIR=$(CURDIR)/debian/tigervnc-java/usr/share)\n\t# install additional license files\n\tmkdir -p $(CURDIR)/debian/xtigervncviewer/usr/share/doc/xtigervncviewer\n\tcp $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervnc/* \\\n\t\t$(CURDIR)/debian/xtigervncviewer/usr/share/doc/xtigervncviewer/\n\t#mkdir -p $(CURDIR)/debian/tigervnc-java/usr/share/doc/tigervnc-java\n\t#cp $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervnc/* \\\n\t\t#$(CURDIR)/debian/tigervnc-java/usr/share/doc/tigervnc-java/\n\tmkdir -p $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervncserver\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervnc \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/doc/tigervncserver\n#\tdh_movefiles\n\tsed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \\\n\t\tdebian/tigervncserver.postinst.in > debian/tigervncserver.postinst\n\n# Build architecture-independent files here.\n# Pass -i to all debhelper commands in this target to reduce clutter.\nbinary-indep: build install\n\nbinary-indep-keep:\n\tdh_testdir -i\n\tdh_testroot -i\n#\tdh_installdebconf -i\n\tdh_install\n\tdh_installdocs -i\n\tdh_installexamples -i\n\tdh_installmenu -i\n#\tdh_installlogrotate -i\n#\tdh_installemacsen -i\n#\tdh_installpam -i\n#\tdh_installmime -i\n#\tdh_installinit -i\n\tdh_installcron -i\n\tdh_installman -i\n\tdh_installinfo -i\n#\tdh_undocumented -i\n\tdh_installchangelogs  -i\n\tdh_link -i\n\tdh_compress -i\n\tdh_fixperms -i\n\tdh_installdeb -i\n\tdh_perl -i\n\tdh_gencontrol -i\n\tdh_md5sums -i\n\tdh_builddeb -i\n\n# Build architecture-dependent files here.\nbinary-arch: build install\n\tdh_testdir -a\n\tdh_testroot -a\n#\tdh_installdebconf -a\n\tdh_installdocs -a\n#\tdh_installexamples -a\n\tdh_installmenu -a\n#\tdh_installlogrotate -a\n#\tdh_installemacsen -a\n#\tdh_installpam -a\n#\tdh_installmime -a\n\tdh_install\n\tdh_installinit -a\n#\tdh_installcron -a\n\tdh_installman -a\n\tdh_installinfo -a\n#\tdh_undocumented -a\n\tdh_installchangelogs  -a\n\t# Remove empty directories\n\tdh_strip -a\n\tdh_link -a\n\tdh_compress -a\n\tdh_fixperms -a\n\tdh_makeshlibs -a\n\tdh_installdeb -a\n\tdh_perl -a\n\tdh_shlibdeps -a\n\tdh_gencontrol -a\n\tdh_md5sums -a\n\tdh_builddeb -a\n\nbinary: binary-indep binary-arch\n.PHONY: build clean binary-indep binary-arch binary install\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/tigervncserver.postinst.in",
    "content": "#!/bin/sh\n\nset -e\n\nif [ \"$1\" = \"configure\" ]; then\n    MAN=/usr/share/man\n    BIN=/usr/bin\n    SBIN=/usr/sbin\n    LIB=/usr/lib/@DEB_HOST_MULTIARCH@\n    update-alternatives --install \\\n       $SBIN/vncsession          vncsession      $SBIN/tigervncsession 64 \\\n       --slave \\\n       $LIB/vncserver            vncserver       $LIB/tigervncserver \\\n       --slave \\\n       $MAN/man8/vncsession.8.gz vncsession.8.gz $MAN/man8/tigervncsession.8.gz \\\n       --slave \\\n       $MAN/man8/vncserver.8.gz  vncserver.8.gz  $MAN/man8/tigervncserver.8.gz\n    update-alternatives --install \\\n       $BIN/Xvnc            Xvnc            $BIN/Xtigervnc 74 \\\n       --slave \\\n       $MAN/man1/Xvnc.1.gz  Xvnc.1.gz       $MAN/man1/Xtigervnc.1.gz\n    update-alternatives --install \\\n       $BIN/x0vncserver           x0vncserver     $BIN/x0tigervncserver 74 \\\n       --slave \\\n       $MAN/man1/x0vncserver.1.gz x0vncserver.1.gz $MAN/man1/x0tigervncserver.1.gz\n    update-alternatives --install \\\n       $BIN/vncpasswd           vncpasswd            $BIN/tigervncpasswd 74 \\\n       --slave \\\n       $MAN/man1/vncpasswd.1.gz vncpasswd.1.gz       $MAN/man1/tigervncpasswd.1.gz\n    update-alternatives --install \\\n       $BIN/vncconfig           vncconfig       $BIN/tigervncconfig 64 \\\n       --slave \\\n       $MAN/man1/vncconfig.1.gz vncconfig.1.gz  $MAN/man1/tigervncconfig.1.gz\nfi\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/tigervncserver.prerm",
    "content": "#!/bin/sh\n\nset -e\n\nif [ \"$1\" = \"remove\" ] ; then\n    BIN=/usr/bin\n    SBIN=/usr/sbin\n    update-alternatives --remove \\\n       vncsession $SBIN/tigervncsession\n    update-alternatives --remove \\\n       Xvnc $BIN/Xtigervnc\n    update-alternatives --remove \\\n       x0vncserver $BIN/x0tigervncserver\n    update-alternatives --remove \\\n       vncpasswd $BIN/tigervncpasswd\n    update-alternatives --remove \\\n       tigervncconfig $BIN/tigervncconfig\nfi\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/xorg-source-patches/516_tigervnc-xorg-manpages.patch",
    "content": "--- a/unix/xserver/man/Makefile.am\t2013-03-30 17:51:01.707258746 -0400\n+++ b/unix/xserver/man/Makefile.am\t2013-03-30 17:51:47.606569692 -0400\n@@ -2,5 +2,7 @@\n # (i.e. those handled in the os/utils.c options processing instead of in\n #  the DDX-level options processing)\n \n+if ENABLE_DOCS\n include $(top_srcdir)/manpages.am\n appman_PRE = Xserver.man\n+endif ENABLE_DOCS \n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/xorg-source-patches/debian_libtool.patch",
    "content": "Index: a/ltmain.sh\n===================================================================\n--- a/ltmain.sh\n+++ b/ltmain.sh\n@@ -7890,19 +7890,19 @@\n \t    # It is a libtool convenience library, so add in its objects.\n \t    func_append convenience \" $ladir/$objdir/$old_library\"\n \t    func_append old_convenience \" $ladir/$objdir/$old_library\"\n-\t    tmp_libs=\n-\t    for deplib in $dependency_libs; do\n-\t      deplibs=\"$deplib $deplibs\"\n-\t      if $opt_preserve_dup_deps; then\n-\t\tcase \"$tmp_libs \" in\n-\t\t*\" $deplib \"*) func_append specialdeplibs \" $deplib\" ;;\n-\t\tesac\n-\t      fi\n-\t      func_append tmp_libs \" $deplib\"\n-\t    done\n \t  elif test prog != \"$linkmode\" && test lib != \"$linkmode\"; then\n \t    func_fatal_error \"'$lib' is not a convenience library\"\n \t  fi\n+\t  tmp_libs=\n+\t  for deplib in $dependency_libs; do\n+\t    deplibs=\"$deplib $deplibs\"\n+\t    if $opt_preserve_dup_deps; then\n+\t      case \"$tmp_libs \" in\n+\t      *\" $deplib \"*) func_append specialdeplibs \" $deplib\" ;;\n+\t      esac\n+\t    fi\n+\t    func_append tmp_libs \" $deplib\"\n+\t  done\n \t  continue\n \tfi # $pass = conv\n \n## Do not link against deplibs.  This is not needed for shared libs\n## on atleast ELF systems since those already know which libs they\n## need themself.  This seems to break a few things and will be fixed\n## in a better way in a future upstream version.\n\nIndex: a/ltmain.sh\n===================================================================\n--- a/ltmain.sh\n+++ b/ltmain.sh\n@@ -7568,10 +7568,7 @@\n \tcase $pass in\n \tdlopen) libs=$dlfiles ;;\n \tdlpreopen) libs=$dlprefiles ;;\n-\tlink)\n-\t  libs=\"$deplibs %DEPLIBS%\"\n-\t  test \"X$link_all_deplibs\" != Xno && libs=\"$libs $dependency_libs\"\n-\t  ;;\n+\tlink) libs=\"$deplibs %DEPLIBS% $dependency_libs\" ;;\n \tesac\n       fi\n       if test lib,dlpreopen = \"$linkmode,$pass\"; then\nIndex: a/m4/libtool.m4\n===================================================================\n--- a/m4/libtool.m4\n+++ b/m4/libtool.m4\n@@ -4936,9 +4936,6 @@\n       ;;\n     esac\n     ;;\n-  linux* | k*bsd*-gnu | gnu*)\n-    _LT_TAGVAR(link_all_deplibs, $1)=no\n-    ;;\n   *)\n     _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\\''s/.* //'\\'' | sort | uniq > $export_symbols'\n     ;;\n@@ -4998,9 +5001,6 @@\n   openbsd* | bitrig*)\n     with_gnu_ld=no\n     ;;\n-  linux* | k*bsd*-gnu | gnu*)\n-    _LT_TAGVAR(link_all_deplibs, $1)=no\n-    ;;\n   esac\n \n   _LT_TAGVAR(ld_shlibs, $1)=yes\n@@ -5773,7 +5779,6 @@\n \tif test yes = \"$lt_cv_irix_exported_symbol\"; then\n           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n \"$verstring\" && func_echo_all \"$wl-set_version $wl$verstring\"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'\n \tfi\n-\t_LT_TAGVAR(link_all_deplibs, $1)=no\n       else\n \t_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry $output_objdir/so_locations -o $lib'\n \t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/xtigervncviewer.menu",
    "content": "?package(xtigervncviewer):needs=\"x11\" \\\n  section=\"Applications/Network/Communication\" \\\n  hints=\"VNC,remote-control\"\\\n  title=\"xtigervncviewer\" \\\n  command=\"/usr/bin/xtigervncviewer\"\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/xtigervncviewer.postinst",
    "content": "#!/bin/sh -e\n\nif [ \"$1\" = \"configure\" ]; then\n    MAN=/usr/share/man/man1\n    BIN=/usr/bin\n    update-alternatives --install \\\n       $BIN/vncviewer       vncviewer       $BIN/xtigervncviewer 74 \\\n       --slave \\\n       $MAN/vncviewer.1.gz  vncviewer.1.gz  $MAN/xtigervncviewer.1.gz \\\n       --slave \\\n       $MAN/xvncviewer.1.gz xvncviewer.1.gz $MAN/xtigervncviewer.1.gz \\\n       --slave \\\n       $BIN/xvncviewer      xvncviewer      $BIN/xtigervncviewer\nfi\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-jammy/debian/xtigervncviewer.prerm",
    "content": "#!/bin/sh -e\n\nif [ \"$1\" = \"remove\" ] ; then\n    BIN=/usr/bin\n    update-alternatives --remove \\\n       vncviewer $BIN/xtigervncviewer\nfi\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/changelog",
    "content": "tigervnc (1.13.80) noble; urgency=low\n\n  * Initial release.\n\n -- Brian P. Hinz <bphinz@users.sourceforge.net>  Tue, 18 Jun 2024 18:50:23 -0400\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/compat",
    "content": "10\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/control",
    "content": "Source: tigervnc\nSection: x11\nPriority: optional\nMaintainer: Brian P. Hinz <bphinz@users.sourceforge.net>\nStandards-Version: 3.8.4\nBuild-Depends:\n# TigerVNC dependencies\n debhelper (>= 9),\n dh-autoreconf,\n po-debconf,\n dpkg-dev (>= 1.16.1),\n appstream,\n cmake,\n pkg-config,\n gettext,\n zlib1g-dev,\n libjpeg-turbo8-dev,\n libavcodec-dev,\n libavutil-dev,\n libswscale-dev,\n libgnutls28-dev,\n nettle-dev,\n libgmp-dev,\n libpam0g-dev,\n libpng-dev,\n libxrandr-dev,\n libxdamage-dev,\n libfltk1.3-dev,\n xorg-server-source,\n xserver-xorg-dev,\n openjdk-8-jdk,\n uuid-dev,\n libglib2.0-dev,\n libpipewire-0.3-dev,\n libwayland-dev,\n libxkbcommon-dev,\n# Xorg dependencies\n# debhelper-compat (= 12),\n quilt,\n bison,\n flex,\n xutils-dev (>= 1:7.6+4),\n xfonts-utils (>= 1:7.5+1),\n x11proto-dev (>= 2021.5),\n xtrans-dev (>= 1.3.5),\n libxau-dev (>= 1:1.0.5-2),\n libxcvt-dev,\n libxdmcp-dev (>= 1:0.99.1),\n libxfont-dev (>= 1:2.0.1),\n libxkbfile-dev (>= 1:0.99.1),\n libpixman-1-dev (>= 0.27.2),\n libpciaccess-dev (>= 0.12.901),\n libgcrypt20-dev,\n libudev-dev (>= 151-3) [linux-any],\n libselinux1-dev (>= 2.0.80) [linux-any],\n libaudit-dev [linux-any],\n libdrm-dev (>= 2.4.107-5~) [!hurd-i386],\n libgl1-mesa-dev (>= 9.2),\n mesa-common-dev,\n# Don't use libunwind for armel, armhf, and arm64 as this library is buggy (bug #923962) on those architectures.\n libunwind-dev [amd64 hppa i386 ia64 mips64 mips64el mipsel powerpc powerpcspe ppc64 ppc64el sh4],\n libxmuu-dev (>= 1:0.99.1),\n libxext-dev (>= 1:0.99.1),\n libx11-dev (>= 2:1.6),\n libxrender-dev (>= 1:0.9.0),\n libxi-dev (>= 2:1.8),\n libxpm-dev (>= 1:3.5.3),\n libxaw7-dev (>= 1:0.99.1),\n libxt-dev (>= 1:0.99.1),\n libxmu-dev (>= 1:0.99.1),\n libxtst-dev (>= 1:0.99.1),\n libxres-dev (>= 1:0.99.1),\n libxfixes-dev (>= 1:3.0.0),\n libxv-dev,\n libxinerama-dev,\n libxshmfence-dev (>= 1.1) [!hurd-i386],\n# glamor\n libepoxy-dev [linux-any kfreebsd-any],\n libegl1-mesa-dev [linux-any kfreebsd-any],\n libgbm-dev (>= 10.2) [linux-any kfreebsd-any],\n## XCB bits for Xephyr\n# libx11-xcb-dev,\n# libxcb1-dev,\n# libxcb-xkb-dev,\n# libxcb-shape0-dev,\n# libxcb-render0-dev,\n# libxcb-render-util0-dev,\n# libxcb-util0-dev,\n# libxcb-image0-dev,\n# libxcb-icccm4-dev,\n# libxcb-shm0-dev,\n# libxcb-keysyms1-dev,\n# libxcb-randr0-dev,\n# libxcb-xv0-dev,\n# libxcb-glx0-dev,\n# libxcb-xf86dri0-dev (>= 1.6),\n# unit tests\n xkb-data,\n x11-xkb-utils,\n# arc4random_buf(), getpeereid()\n libbsd-dev,\n#logind\n  libdbus-1-dev (>= 1.0) [linux-any],\n# systemd-daemon\n  libsystemd-dev [linux-any],\nHomepage: http://www.tigervnc.com\n\nPackage: tigervncserver\nArchitecture: any\nProvides:\n xserver,\n vnc-server\nDepends:\n x11-common | xserver-common,\n x11-utils,\n xauth,\n x11-xkb-utils,\n ${shlibs:Depends},\n ${perl:Depends},\n ${misc:Depends}\nRecommends:\n xfonts-base,\n x11-xserver-utils\nSuggests:\n xtigervncviewer,\n tigervnc-java\nDescription: virtual network computing server software\n Virtual Network Computing (VNC) is a remote display system which allows you to\n view and interact with a virtual desktop environment that is running on another\n computer on the network.  Using VNC, you can run graphical applications on a\n remote machine and send only the display from these applications to your local\n machine.  VNC is platform-independent and supports a wide variety of operating\n systems and architectures as both servers and clients.\n .\n TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code\n bases.  TigerVNC started as a next-generation development effort for TightVNC\n on Unix and Linux platforms, but it split from its parent project in early 2009\n so that TightVNC could focus on Windows platforms.  TigerVNC supports a variant\n of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo\n JPEG codec.\n\nPackage: xtigervncviewer\nArchitecture: any\nProvides:\n vncviewer,\n vnc-viewer\nDepends:\n ${shlibs:Depends},\n ${misc:Depends}\nRecommends:\n xfonts-base\nSuggests:\n tigervncserver,\n ssh\nDescription: virtual network computing client software for X\n Virtual Network Computing (VNC) is a remote display system which allows you to\n view and interact with a virtual desktop environment that is running on another\n computer on the network.  Using VNC, you can run graphical applications on a\n remote machine and send only the display from these applications to your local\n machine.  VNC is platform-independent and supports a wide variety of operating\n systems and architectures as both servers and clients.\n .\n TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code\n bases.  TigerVNC started as a next-generation development effort for TightVNC\n on Unix and Linux platforms, but it split from its parent project in early 2009\n so that TightVNC could focus on Windows platforms.  TigerVNC supports a variant\n of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo\n JPEG codec.\n\nPackage: tigervnc-java\nArchitecture: any\nSuggests:\n tigervncserver\nProvides:\n vncviewer,\n vnc-viewer\nDepends:\n default-jre\nDescription: TigerVNC java applet\n Virtual Network Computing (VNC) is a remote display system which allows you to\n view and interact with a virtual desktop environment that is running on another\n computer on the network.  Using VNC, you can run graphical applications on a\n remote machine and send only the display from these applications to your local\n machine.  VNC is platform-independent and supports a wide variety of operating\n systems and architectures as both servers and clients.\n .\n TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code\n bases.  TigerVNC started as a next-generation development effort for TightVNC\n on Unix and Linux platforms, but it split from its parent project in early 2009\n so that TightVNC could focus on Windows platforms.  TigerVNC supports a variant\n of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo\n JPEG codec.\n\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/copyright",
    "content": "This package was packaged for Debian by Brian P. Hinz <bphinz@users.sourceforge.net>\non Tue, 18 Jun 2024 18:54:03 -0400 using the tightvnc package as a base.\n\nIt was downloaded from:\n\thttps://www.tigervnc.org/\n\nCOPYRIGHT:\n==========\n\nTigerVNC is\n\n        Copyright (C) 1999 AT&T Laboratories Cambridge\n        Copyright (C) 2002-2005 RealVNC Ltd.\n        Copyright (C) 2000-2006 TightVNC Group\n        Copyright (C) 2005-2006 Martin Koegler\n        Copyright (C) 2005-2006 Sun Microsystems, Inc.\n        Copyright (C) 2006 OCCAM Financial Technology\n        Copyright (C) 2000-2008 Constantin Kaplinsky\n        Copyright (C) 2004-2017 Peter Astrand for Cendio AB\n        Copyright (C) 2010 Antoine Martin\n        Copyright (C) 2010 m-privacy GmbH\n        Copyright (C) 2009-2011 D. R. Commander\n        Copyright (C) 2009-2011 Pierre Ossman for Cendio AB\n        Copyright (C) 2004, 2009-2011 Red Hat, Inc.\n        Copyright (C) 2009-2024 TigerVNC Team\n        All Rights Reserved.\n\nThis software is distributed under the GNU General Public Licence as published\nby the Free Software Foundation.  See the file LICENCE.TXT for the conditions\nunder which this software is made available.  TigerVNC also contains code from\nother sources.  See the Acknowledgements section below, and the individual\nsource files, for details of the conditions under which they are made\navailable.\n\nACKNOWLEDGEMENTS\n================\n\nThis distribution contains zlib compression software.  This is:\n\n  Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n\n  Jean-loup Gailly        Mark Adler\n  jloup@gzip.org          madler@alumni.caltech.edu\n\n  The data format used by the zlib library is described by RFCs (Request for\n  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt\n  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).\n\n\nThis distribution contains public domain DES software by Richard Outerbridge.\nThis is:\n\n    Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.\n    (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.\n\n\nThis distribution contains software from the X Window System.  This is:\n\n Copyright 1987, 1988, 1998  The Open Group\n \n Permission to use, copy, modify, distribute, and sell this software and its\n documentation for any purpose is hereby granted without fee, provided that\n the above copyright notice appear in all copies and that both that\n copyright notice and this permission notice appear in supporting\n documentation.\n \n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\n OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\n AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n \n Except as contained in this notice, the name of The Open Group shall not be\n used in advertising or otherwise to promote the sale, use or other dealings\n in this Software without prior written authorization from The Open Group.\n \n \n Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.\n \n                         All Rights Reserved\n \n Permission to use, copy, modify, and distribute this software and its \n documentation for any purpose and without fee is hereby granted, \n provided that the above copyright notice appear in all copies and that\n both that copyright notice and this permission notice appear in \n supporting documentation, and that the name of Digital not be\n used in advertising or publicity pertaining to distribution of the\n software without specific, written prior permission.  \n \n DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\n ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\n DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\n ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\n WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\n ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\n SOFTWARE.\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/rules",
    "content": "#!/usr/bin/make -f\n# Sample debian/rules that uses debhelper.\n# GNU copyright 1997 by Joey Hess.\nexport DEB_BUILD_MAINT_OPTIONS=hardening=+all\n\nCFLAGS   := $(shell dpkg-buildflags --get CFLAGS)\nCPPFLAGS := $(shell dpkg-buildflags --get CPPFLAGS)\nCXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS)\nLDFLAGS  := $(shell dpkg-buildflags --get LDFLAGS)\n\nexport CFLAGS CPPFLAGS CXXFLAGS LDFLAGS\n\nNUMJOBS := -j$(shell nproc)\n\n# Uncomment this to turn on verbose mode.\n#export DH_VERBOSE=1\n\nDEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)\nDEB_HOST_ARCH      ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)\nDEB_HOST_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)\nDEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)\nDEB_HOST_ARCH_OS   ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)\nifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))\n\tconfflags += --build=$(DEB_HOST_GNU_TYPE)\nelse\n\tconfflags += --build=$(DEB_BUILD_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE)\nendif\nSOURCE_NAME    := tigervnc\nSOURCE_VERSION := $(shell dpkg-parsechangelog | awk -F': ' '/^Version: / {print $$2}')\nBUILDER=For technical support please see http://sourceforge.net/projects/tigervnc/support\nlibdir = /usr/lib/$(DEB_HOST_MULTIARCH)\n\n\nifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))\n\tCFLAGS += -g -O2 -fPIC\nendif\nifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))\n\tINSTALL_PROGRAM += -s\nendif\n\nexport CC = gcc\n\n# use xorg sources as shipped in xorg-server-source package\nXORG_SOURCE_ARCHIVE = /usr/src/xorg-server.tar.xz\n\nxorg-source-stamp: $(XORG_SOURCE_ARCHIVE)\n\ttar -C unix/xserver -axf $(XORG_SOURCE_ARCHIVE) --strip-components=1\n\tcd unix/xserver && patch -p1 < ../xserver21.patch\n\tpatch -p1 < debian/xorg-source-patches/516_tigervnc-xorg-manpages.patch\n\ttouch xorg-source-stamp\n\nconfigure: config-stamp\nconfig-stamp: xorg-source-stamp\n\tdh_testdir\n\t# Add here commands to configure the package.\n\tcmake -G\"Unix Makefiles\" \\\n\t\t-DBUILD_STATIC=off \\\n\t\t-DENABLE_NLS=ON \\\n\t\t-DENABLE_H264=ON \\\n\t\t-DENABLE_GNUTLS=ON \\\n\t\t-DENABLE_NETTLE=ON \\\n\t\t-DENABLE_SYSTEMD=ON \\\n\t\t-DENABLE_WAYLAND=ON \\\n\t\t-DBUILD_VIEWER=ON \\\n\t\t-DCMAKE_INSTALL_PREFIX:PATH=/usr \\\n\t\t-DCMAKE_INSTALL_LIBEXECDIR:PATH=lib/$(DEB_HOST_MULTIARCH) \\\n\t\t-DCMAKE_INSTALL_UNITDIR:PATH=/lib/systemd/system\n\t(cd unix/xserver; \\\n\texport PIXMANINCDIR=/usr/include/pixman-1; \\\n\tautoreconf -fiv; \\\n  patch -p1 -i ../../debian/xorg-source-patches/debian_libtool.patch; \\\n\t./configure --prefix=/usr \\\n\t\t--disable-silent-rules \\\n\t\t--disable-static \\\n\t\t--without-dtrace \\\n\t\t--disable-strict-compilation \\\n\t\t--disable-debug \\\n\t\t--disable-unit-tests \\\n\t\t--with-int10=x86emu \\\n\t\t--with-extra-module-dir=\"/usr/lib/${DEB_HOST_MULTIARCH}/xorg/extra-modules,/usr/lib/xorg/extra-modules\" \\\n\t\t--with-os-vendor=\"$(VENDOR)\" \\\n\t\t--with-builderstring=\"$(SOURCE_NAME) $(SOURCE_VERSION) ($(BUILDER))\" \\\n\t\t--with-xkb-path=/usr/share/X11/xkb \\\n\t\t--with-xkb-output=/var/lib/xkb \\\n\t\t--with-default-xkb-rules=evdev \\\n\t\t--disable-devel-docs \\\n\t\t--enable-mitshm \\\n\t\t--enable-xres \\\n\t\t--disable-xcsecurity \\\n\t\t--disable-tslib \\\n\t\t--enable-dbe \\\n\t\t--disable-xf86bigfont \\\n\t\t--disable-dpms \\\n\t\t--disable-config-hal \\\n\t\t--disable-config-udev \\\n\t\t--disable-xorg \\\n\t\t--disable-xquartz \\\n\t\t--disable-xwin \\\n\t\t--disable-xfake \\\n\t\t--disable-install-setuid \\\n\t\t--with-default-font-path=\"/usr/share/fonts/X11/misc,/usr/share/fonts/X11/cyrillic,/usr/share/fonts/X11/100dpi/:unscaled,/usr/share/fonts/X11/75dpi/:unscaled,/usr/share/fonts/X11/Type1,/usr/share/fonts/X11/100dpi,/usr/share/fonts/X11/75dpi,/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType,built-ins\" \\\n\t\t--enable-aiglx \\\n\t\t--enable-composite \\\n\t\t--enable-record \\\n\t\t--enable-xv \\\n\t\t--enable-xvmc \\\n\t\t--enable-dga \\\n\t\t--enable-screensaver \\\n\t\t--enable-xdmcp \\\n\t\t--enable-xdm-auth-1 \\\n\t\t--enable-glx \\\n\t\t--disable-dri --enable-dri2 --enable-dri3 \\\n\t\t--enable-xinerama \\\n\t\t--enable-xf86vidmode \\\n\t\t--enable-xace \\\n\t\t--enable-xfree86-utils \\\n\t\t--disable-dmx \\\n\t\t--disable-xvfb \\\n\t\t--disable-xnest \\\n\t\t--disable-kdrive \\\n\t\t--disable-xephyr \\\n\t\t--enable-xfbdev \\\n\t\t--with-sha1=libgcrypt \\\n\t\t--enable-xcsecurity \\\n\t\t--disable-docs \\\n\t\t--disable-selective-werror)\n\ttouch config-stamp\n\nbuild-arch: config-stamp build-arch-stamp\nbuild-arch-stamp:\n\tdh_testdir\n\n\t# Add here command to compile/build the package.\n\t# Build first things.\n\t# Build Xvnc\n\tmake $(NUMJOBS) LDFLAGS=\"-lpng\" VERBOSE=1\n\tmake $(NUMJOBS) -C unix/xserver\n\n\ttouch build-arch-stamp\n\nbuild-indep: config-stamp  build-indep-stamp\nbuild-indep-stamp:\n\tdh_testdir\n\n\t# Add here command to compile/build the arch indep package.\n\t# It's ok not to do anything here, if you don't need to build\n\t#  anything for this package.\n\t#/usr/bin/docbook-to-man debian/vnc.sgml > vnc.1\n\t(cd media;make)\n\t#(cd java;cmake -G\"Unix Makefiles\";make)\n\n\ttouch build-indep-stamp\n\nbuild: build-arch build-indep\n\nclean:\n\tdh_testdir\n\tdh_testroot\n\trm -f build-arch-stamp build-indep-stamp config-stamp\n\n\t# Add here commands to clean up after the build process.\n\tdh_clean\n\ninstall: DH_OPTIONS=\ninstall: build\n\tdh_testdir\n\tdh_testroot\n\tdh_clean -k\n\tdh_prep\n\tdh_installdirs\n\t# Add here commands to install the package into debian/vnc.\n\tmake install DESTDIR=$(CURDIR)/debian/tigervncserver\n\t(cd unix/xserver/hw/vnc; make install DESTDIR=$(CURDIR)/debian/tigervncserver)\n\t# rename server files to tigervnc specific names\n\tmv $(CURDIR)/debian/tigervncserver/usr/bin/Xvnc \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/bin/Xtigervnc\n\tmv $(CURDIR)/debian/tigervncserver/usr/bin/vncconfig \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/bin/tigervncconfig\n\tmv $(CURDIR)/debian/tigervncserver/usr/bin/vncpasswd \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/bin/tigervncpasswd\n\tmv $(CURDIR)/debian/tigervncserver/usr/bin/x0vncserver \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/bin/x0tigervncserver\n\tmv $(CURDIR)/debian/tigervncserver/usr/sbin/vncsession \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/sbin/tigervncsession\n\tmv $(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/vncserver \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/tigervncserver\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncconfig.1 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncconfig.1\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncpasswd.1 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncpasswd.1\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0vncserver.1 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0tigervncserver.1\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xvnc.1 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xtigervnc.1\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncsession.8 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncsession.8\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncserver.8 \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncserver.8\n\t# delete development files\n\trm -f $(CURDIR)/debian/tigervncserver/usr/lib/xorg/modules/extensions/libvnc.la\n\t# move viewer files to viewer package, rename on the fly\n\tmkdir -p $(CURDIR)/debian/xtigervncviewer/usr/bin\n\tmv $(CURDIR)/debian/tigervncserver/usr/bin/vncviewer \\\n\t\t$(CURDIR)/debian/xtigervncviewer/usr/bin/xtigervncviewer\n\tmkdir -p $(CURDIR)/debian/xtigervncviewer/usr/share/man/man1\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncviewer.1 \\\n\t\t$(CURDIR)/debian/xtigervncviewer/usr/share/man/man1/xtigervncviewer.1\n\tmkdir -p $(CURDIR)/debian/xtigervncviewer/usr/share\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/applications \\\n\t\t$(CURDIR)/debian/xtigervncviewer/usr/share/\n\tmkdir -p $(CURDIR)/debian/xtigervncviewer/usr/share\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/icons \\\n\t\t$(CURDIR)/debian/xtigervncviewer/usr/share/\n\t# tigervnc-java\n\t#mkdir -p $(CURDIR)/debian/tigervnc-java/usr/share\n\t#(cd java; make install DESTDIR=$(CURDIR)/debian/tigervnc-java/usr/share)\n\t# install additional license files\n\tmkdir -p $(CURDIR)/debian/xtigervncviewer/usr/share/doc/xtigervncviewer\n\tcp $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervnc/* \\\n\t\t$(CURDIR)/debian/xtigervncviewer/usr/share/doc/xtigervncviewer/\n\t#mkdir -p $(CURDIR)/debian/tigervnc-java/usr/share/doc/tigervnc-java\n\t#cp $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervnc/* \\\n\t\t#$(CURDIR)/debian/tigervnc-java/usr/share/doc/tigervnc-java/\n\tmkdir -p $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervncserver\n\tmv $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervnc \\\n\t\t$(CURDIR)/debian/tigervncserver/usr/share/doc/tigervncserver\n#\tdh_movefiles\n\tsed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \\\n\t\tdebian/tigervncserver.postinst.in > debian/tigervncserver.postinst\n\n# Build architecture-independent files here.\n# Pass -i to all debhelper commands in this target to reduce clutter.\nbinary-indep: build install\n\nbinary-indep-keep:\n\tdh_testdir -i\n\tdh_testroot -i\n#\tdh_installdebconf -i\n\tdh_install\n\tdh_installdocs -i\n\tdh_installexamples -i\n\tdh_installmenu -i\n#\tdh_installlogrotate -i\n#\tdh_installemacsen -i\n#\tdh_installpam -i\n#\tdh_installmime -i\n#\tdh_installinit -i\n\tdh_installcron -i\n\tdh_installman -i\n\tdh_installinfo -i\n#\tdh_undocumented -i\n\tdh_installchangelogs  -i\n\tdh_link -i\n\tdh_compress -i\n\tdh_fixperms -i\n\tdh_installdeb -i\n\tdh_perl -i\n\tdh_gencontrol -i\n\tdh_md5sums -i\n\tdh_builddeb -i\n\n# Build architecture-dependent files here.\nbinary-arch: build install\n\tdh_testdir -a\n\tdh_testroot -a\n#\tdh_installdebconf -a\n\tdh_installdocs -a\n#\tdh_installexamples -a\n\tdh_installmenu -a\n#\tdh_installlogrotate -a\n#\tdh_installemacsen -a\n#\tdh_installpam -a\n#\tdh_installmime -a\n\tdh_install\n\tdh_installinit -a\n#\tdh_installcron -a\n\tdh_installman -a\n\tdh_installinfo -a\n#\tdh_undocumented -a\n\tdh_installchangelogs  -a\n\t# Remove empty directories\n\tdh_strip -a\n\tdh_link -a\n\tdh_compress -a\n\tdh_fixperms -a\n\tdh_makeshlibs -a\n\tdh_installdeb -a\n\tdh_perl -a\n\tdh_shlibdeps -a\n\tdh_gencontrol -a\n\tdh_md5sums -a\n\tdh_builddeb -a\n\nbinary: binary-indep binary-arch\n.PHONY: build clean binary-indep binary-arch binary install\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/tigervncserver.postinst.in",
    "content": "#!/bin/sh\n\nset -e\n\nif [ \"$1\" = \"configure\" ]; then\n    MAN=/usr/share/man\n    BIN=/usr/bin\n    SBIN=/usr/sbin\n    LIB=/usr/lib/@DEB_HOST_MULTIARCH@\n    update-alternatives --install \\\n       $SBIN/vncsession          vncsession      $SBIN/tigervncsession 64 \\\n       --slave \\\n       $LIB/vncserver            vncserver       $LIB/tigervncserver \\\n       --slave \\\n       $MAN/man8/vncsession.8.gz vncsession.8.gz $MAN/man8/tigervncsession.8.gz \\\n       --slave \\\n       $MAN/man8/vncserver.8.gz  vncserver.8.gz  $MAN/man8/tigervncserver.8.gz\n    update-alternatives --install \\\n       $BIN/Xvnc            Xvnc            $BIN/Xtigervnc 74 \\\n       --slave \\\n       $MAN/man1/Xvnc.1.gz  Xvnc.1.gz       $MAN/man1/Xtigervnc.1.gz\n    update-alternatives --install \\\n       $BIN/x0vncserver           x0vncserver     $BIN/x0tigervncserver 74 \\\n       --slave \\\n       $MAN/man1/x0vncserver.1.gz x0vncserver.1.gz $MAN/man1/x0tigervncserver.1.gz\n    update-alternatives --install \\\n       $BIN/vncpasswd           vncpasswd            $BIN/tigervncpasswd 74 \\\n       --slave \\\n       $MAN/man1/vncpasswd.1.gz vncpasswd.1.gz       $MAN/man1/tigervncpasswd.1.gz\n    update-alternatives --install \\\n       $BIN/vncconfig           vncconfig       $BIN/tigervncconfig 64 \\\n       --slave \\\n       $MAN/man1/vncconfig.1.gz vncconfig.1.gz  $MAN/man1/tigervncconfig.1.gz\nfi\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/tigervncserver.prerm",
    "content": "#!/bin/sh\n\nset -e\n\nif [ \"$1\" = \"remove\" ] ; then\n    BIN=/usr/bin\n    SBIN=/usr/sbin\n    update-alternatives --remove \\\n       vncsession $SBIN/tigervncsession\n    update-alternatives --remove \\\n       Xvnc $BIN/Xtigervnc\n    update-alternatives --remove \\\n       x0vncserver $BIN/x0tigervncserver\n    update-alternatives --remove \\\n       vncpasswd $BIN/tigervncpasswd\n    update-alternatives --remove \\\n       tigervncconfig $BIN/tigervncconfig\nfi\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/xorg-source-patches/516_tigervnc-xorg-manpages.patch",
    "content": "--- a/unix/xserver/man/Makefile.am\t2013-03-30 17:51:01.707258746 -0400\n+++ b/unix/xserver/man/Makefile.am\t2013-03-30 17:51:47.606569692 -0400\n@@ -2,5 +2,7 @@\n # (i.e. those handled in the os/utils.c options processing instead of in\n #  the DDX-level options processing)\n \n+if ENABLE_DOCS\n include $(top_srcdir)/manpages.am\n appman_PRE = Xserver.man\n+endif ENABLE_DOCS \n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/xorg-source-patches/debian_libtool.patch",
    "content": "Index: a/ltmain.sh\n===================================================================\n--- a/ltmain.sh\n+++ b/ltmain.sh\n@@ -7890,19 +7890,19 @@\n \t    # It is a libtool convenience library, so add in its objects.\n \t    func_append convenience \" $ladir/$objdir/$old_library\"\n \t    func_append old_convenience \" $ladir/$objdir/$old_library\"\n-\t    tmp_libs=\n-\t    for deplib in $dependency_libs; do\n-\t      deplibs=\"$deplib $deplibs\"\n-\t      if $opt_preserve_dup_deps; then\n-\t\tcase \"$tmp_libs \" in\n-\t\t*\" $deplib \"*) func_append specialdeplibs \" $deplib\" ;;\n-\t\tesac\n-\t      fi\n-\t      func_append tmp_libs \" $deplib\"\n-\t    done\n \t  elif test prog != \"$linkmode\" && test lib != \"$linkmode\"; then\n \t    func_fatal_error \"'$lib' is not a convenience library\"\n \t  fi\n+\t  tmp_libs=\n+\t  for deplib in $dependency_libs; do\n+\t    deplibs=\"$deplib $deplibs\"\n+\t    if $opt_preserve_dup_deps; then\n+\t      case \"$tmp_libs \" in\n+\t      *\" $deplib \"*) func_append specialdeplibs \" $deplib\" ;;\n+\t      esac\n+\t    fi\n+\t    func_append tmp_libs \" $deplib\"\n+\t  done\n \t  continue\n \tfi # $pass = conv\n \n## Do not link against deplibs.  This is not needed for shared libs\n## on atleast ELF systems since those already know which libs they\n## need themself.  This seems to break a few things and will be fixed\n## in a better way in a future upstream version.\n\nIndex: a/ltmain.sh\n===================================================================\n--- a/ltmain.sh\n+++ b/ltmain.sh\n@@ -7568,10 +7568,7 @@\n \tcase $pass in\n \tdlopen) libs=$dlfiles ;;\n \tdlpreopen) libs=$dlprefiles ;;\n-\tlink)\n-\t  libs=\"$deplibs %DEPLIBS%\"\n-\t  test \"X$link_all_deplibs\" != Xno && libs=\"$libs $dependency_libs\"\n-\t  ;;\n+\tlink) libs=\"$deplibs %DEPLIBS% $dependency_libs\" ;;\n \tesac\n       fi\n       if test lib,dlpreopen = \"$linkmode,$pass\"; then\nIndex: a/m4/libtool.m4\n===================================================================\n--- a/m4/libtool.m4\n+++ b/m4/libtool.m4\n@@ -4936,9 +4936,6 @@\n       ;;\n     esac\n     ;;\n-  linux* | k*bsd*-gnu | gnu*)\n-    _LT_TAGVAR(link_all_deplibs, $1)=no\n-    ;;\n   *)\n     _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\\''s/.* //'\\'' | sort | uniq > $export_symbols'\n     ;;\n@@ -4998,9 +5001,6 @@\n   openbsd* | bitrig*)\n     with_gnu_ld=no\n     ;;\n-  linux* | k*bsd*-gnu | gnu*)\n-    _LT_TAGVAR(link_all_deplibs, $1)=no\n-    ;;\n   esac\n \n   _LT_TAGVAR(ld_shlibs, $1)=yes\n@@ -5773,7 +5779,6 @@\n \tif test yes = \"$lt_cv_irix_exported_symbol\"; then\n           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n \"$verstring\" && func_echo_all \"$wl-set_version $wl$verstring\"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'\n \tfi\n-\t_LT_TAGVAR(link_all_deplibs, $1)=no\n       else\n \t_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry $output_objdir/so_locations -o $lib'\n \t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/xtigervncviewer.menu",
    "content": "?package(xtigervncviewer):needs=\"x11\" \\\n  section=\"Applications/Network/Communication\" \\\n  hints=\"VNC,remote-control\"\\\n  title=\"xtigervncviewer\" \\\n  command=\"/usr/bin/xtigervncviewer\"\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/xtigervncviewer.postinst",
    "content": "#!/bin/sh -e\n\nif [ \"$1\" = \"configure\" ]; then\n    MAN=/usr/share/man/man1\n    BIN=/usr/bin\n    update-alternatives --install \\\n       $BIN/vncviewer       vncviewer       $BIN/xtigervncviewer 74 \\\n       --slave \\\n       $MAN/vncviewer.1.gz  vncviewer.1.gz  $MAN/xtigervncviewer.1.gz \\\n       --slave \\\n       $MAN/xvncviewer.1.gz xvncviewer.1.gz $MAN/xtigervncviewer.1.gz \\\n       --slave \\\n       $BIN/xvncviewer      xvncviewer      $BIN/xtigervncviewer\nfi\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "contrib/packages/deb/ubuntu-noble/debian/xtigervncviewer.prerm",
    "content": "#!/bin/sh -e\n\nif [ \"$1\" = \"remove\" ] ; then\n    BIN=/usr/bin\n    update-alternatives --remove \\\n       vncviewer $BIN/xtigervncviewer\nfi\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "contrib/packages/rpm/el10/SOURCES/0001-configure.ac-search-for-the-fontrootdir-ourselves.patch",
    "content": "From e67e988730346c63d2f0cdf2531ed36b0c7ad5a6 Mon Sep 17 00:00:00 2001\nFrom: Peter Hutterer <peter.hutterer@who-t.net>\nDate: Wed, 23 Nov 2022 14:50:29 +1000\nSubject: [PATCH xserver] configure.ac: search for the fontrootdir ourselves\n\nThis replaces the use of font-utils' .m4 macro set with a copy of the\nonly one we actually want: the bit for the fontrootpath.\n\nWe don't need configure options for every single subfont directory, so\nlet's hardcode those in the default font path. Like meson does upstream\ntoo.\n\nWith this patch we no longer require the font-utils dependency.\n\nSigned-off-by: Peter Hutterer <peter.hutterer@who-t.net>\n---\n configure.ac | 28 +++++++++++++++++-----------\n 1 file changed, 17 insertions(+), 11 deletions(-)\n\ndiff --git a/configure.ac b/configure.ac\nindex 0909cc5b4d..2349320888 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -49,9 +49,6 @@ XORG_WITH_XSLTPROC\n XORG_ENABLE_UNIT_TESTS\n XORG_LD_WRAP([optional])\n \n-m4_ifndef([XORG_FONT_MACROS_VERSION], [m4_fatal([must install font-util 1.1 or later before running autoconf/autogen])])\n-XORG_FONT_MACROS_VERSION(1.1)\n-\n dnl this gets generated by autoheader, and thus contains all the defines.  we\n dnl don't ever actually use it, internally.\n AC_CONFIG_HEADERS(include/do-not-use-config.h)\n@@ -450,18 +447,27 @@ AC_MSG_RESULT([$FALLBACK_INPUT_DRIVER])\n AC_DEFINE_UNQUOTED(FALLBACK_INPUT_DRIVER, [\"$FALLBACK_INPUT_DRIVER\"], [ Fallback input driver ])\n \n dnl Determine font path\n-XORG_FONTROOTDIR\n-XORG_FONTSUBDIR(FONTMISCDIR, fontmiscdir, misc)\n-XORG_FONTSUBDIR(FONTOTFDIR, fontotfdir, OTF)\n-XORG_FONTSUBDIR(FONTTTFDIR, fontttfdir, TTF)\n-XORG_FONTSUBDIR(FONTTYPE1DIR, fonttype1dir, Type1)\n-XORG_FONTSUBDIR(FONT75DPIDIR, font75dpidir, 75dpi)\n-XORG_FONTSUBDIR(FONT100DPIDIR, font100dpidir, 100dpi)\n+dnl This is a copy of XORG_FONTROOTDIR from font-utils so we can drop the dependency\n+AC_MSG_CHECKING([for root directory for font files])\n+AC_ARG_WITH(fontrootdir,\n+\t    AS_HELP_STRING([--with-fontrootdir=DIR],\n+\t\t   [Path to root directory for font files]),\n+\t    [FONTROOTDIR=\"$withval\"])\n+# if --with-fontrootdir not specified...\n+if test \"x${FONTROOTDIR}\" = \"x\"; then\n+\tFONTROOTDIR=`$PKG_CONFIG --variable=fontrootdir fontutil`\n+fi\n+# ...and if pkg-config didn't find fontdir in fontutil.pc...\n+if test \"x${FONTROOTDIR}\" = \"x\"; then\n+\tFONTROOTDIR=\"${datadir}/fonts/X11\"\n+fi\n+AC_SUBST(FONTROOTDIR)\n+AC_MSG_RESULT([${FONTROOTDIR}])\n \n dnl Uses --with-default-font-path if set, otherwise uses standard\n dnl subdirectories of FONTROOTDIR. Some distros set the default font path to\n dnl \"catalogue:/etc/X11/fontpath.d,built-ins\"\n-DEFAULT_FONT_PATH=\"${FONTMISCDIR}/,${FONTTTFDIR}/,${FONTOTFDIR}/,${FONTTYPE1DIR}/,${FONT100DPIDIR}/,${FONT75DPIDIR}/\"\n+DEFAULT_FONT_PATH=\"${FONTROOTDIR}/misc,${FONTROOTDIR}/OTF,${FONTROOTDIR}/TTF,${FONTROOTDIR}/Type1,${FONTROOTDIR}/75dpi,${FONTROOTDIR}/100dpi\"\n case $host_os in\n     darwin*) DEFAULT_FONT_PATH=\"${DEFAULT_FONT_PATH},/Library/Fonts,/System/Library/Fonts\" ;;\n esac\n-- \n2.38.1\n\n"
  },
  {
    "path": "contrib/packages/rpm/el10/SPECS/tigervnc.spec",
    "content": "#defining macros needed by SELinux\n%global selinuxtype targeted\n%global modulename vncsession\n\n%global xorgversion 21.1.18\n\nName:           tigervnc\nVersion:        @VERSION@\nRelease:        1%{?snap:.%{snap}}%{?dist}\nSummary:        A TigerVNC remote display system\n\n%global _hardened_build 1\n\nLicense:        GPLv2+\nURL:            http://www.tigervnc.com\n\nSource0:        %{name}-%{version}%{?snap:-%{snap}}.tar.bz2\nSource1:        https://xorg.freedesktop.org/releases/individual/xserver/xorg-server-%{xorgversion}.tar.xz\n# Patch from RHEL to avoid dependency on xorg-x11-font-utils\nSource2:        0001-configure.ac-search-for-the-fontrootdir-ourselves.patch\n\nBuildRequires:  make\nBuildRequires:  gcc-c++\nBuildRequires:  automake, autoconf, libtool, gettext, gettext-autopoint\nBuildRequires:  cmake, desktop-file-utils, appstream\nBuildRequires:  libxkbfile-devel, openssl-devel, libpciaccess-devel\nBuildRequires:  freetype-devel, libjpeg-turbo-devel, pam-devel\nBuildRequires:  gnutls-devel, nettle-devel, gmp-devel\nBuildRequires:  zlib-devel\nBuildRequires:  libuuid-devel, glib2-devel, pipewire-devel\nBuildRequires:  wayland-devel, libxkbcommon-devel\n# X11/graphics dependencies\nBuildRequires: libXext-devel, libX11-devel, libXi-devel, libXfixes-devel\nBuildRequires: libXdamage-devel, libXrandr-devel, libXt-devel, libXdmcp-devel\nBuildRequires: libXinerama-devel, mesa-libGL-devel, libxshmfence-devel\nBuildRequires: pixman-devel, libdrm-devel, mesa-libgbm-devel\nBuildRequires: xorg-x11-util-macros, xorg-x11-xtrans-devel, libXtst-devel\nBuildRequires:  libXfont2-devel\n# SELinux\nBuildRequires:  libselinux-devel, selinux-policy-devel\nBuildRequires:  systemd-devel\n\n# TigerVNC 1.4.x requires fltk 1.3.3 for keyboard handling support\n# See https://github.com/TigerVNC/tigervnc/issues/8, also bug #1208814\nBuildRequires:  fltk-devel >= 1.3.3\n\nRequires:       hicolor-icon-theme\nRequires:       tigervnc-license\nRequires:       tigervnc-icons\n\n%description\nVirtual Network Computing (VNC) is a remote display system which\nallows you to view a computing 'desktop' environment not only on the\nmachine where it is running, but from anywhere on the Internet and\nfrom a wide variety of machine architectures.  This package contains a\nclient which will allow you to connect to other desktops running a VNC\nserver.\n\n%package server\nSummary:        A TigerVNC server\nRequires:       perl-interpreter\nRequires:       tigervnc-server-minimal = %{version}-%{release}\nRequires:       (%{name}-selinux if selinux-policy-%{selinuxtype})\nRequires:       xorg-x11-xauth\nRequires:       xorg-x11-xinit\n\n%description server\nThe VNC system allows you to access the same desktop from a wide\nvariety of platforms.  This package includes set of utilities\nwhich make usage of TigerVNC server more user friendly. It also\ncontains the x0vncserver program which can export your active\nX session, and the w0vncserver program which can export your active\nWayland session.\n\n%package server-minimal\nSummary:        A minimal installation of TigerVNC server\nRequires(post): systemd\nRequires(preun): systemd\nRequires(postun): systemd\nRequires(post): systemd\n\nRequires:       mesa-dri-drivers, xkeyboard-config, xkbcomp\nRequires:       tigervnc-license, dbus-x11\n\n%description server-minimal\nThe VNC system allows you to access the same desktop from a wide\nvariety of platforms. This package contains minimal installation\nof TigerVNC server, allowing others to access the desktop on your\nmachine.\n\n%package license\nSummary:        License of TigerVNC suite\nBuildArch:      noarch\n\n%description license\nThis package contains license of the TigerVNC suite\n\n%package icons\nSummary:        Icons for TigerVNC viewer\nBuildArch:      noarch\n\n%description icons\nThis package contains icons for TigerVNC viewer\n\n%package selinux\nSummary:        SELinux module for TigerVNC\nBuildArch:      noarch\nBuildRequires:  selinux-policy-devel\nRequires:       selinux-policy-%{selinuxtype}\nRequires(post): selinux-policy-%{selinuxtype}\nBuildRequires:  selinux-policy-devel\n%{?selinux_requires}\n\n%description selinux\nThis package provides the SELinux policy module to ensure TigerVNC\nruns properly under an environment with SELinux enabled.\n\n%prep\n%setup -q -n %{name}-%{version}%{?snap:-%{snap}}\n\ntar -axf %{SOURCE1}\ncp -r xorg-server-%{xorgversion}/* unix/xserver\npushd unix/xserver\nfor all in `find . -type f -perm -001`; do\n        chmod -x \"$all\"\ndone\npatch -p1 -b --suffix .fontrootdir < %{SOURCE2}\npatch -p1 -b --suffix .vnc < ../xserver21.patch\npopd\n\n%build\n%ifarch sparcv9 sparc64 s390 s390x\nexport CFLAGS=\"$RPM_OPT_FLAGS -fPIC\"\n%else\nexport CFLAGS=\"$RPM_OPT_FLAGS -fpic\"\n%endif\nexport CXXFLAGS=\"$CFLAGS -std=c++11\"\n\n%cmake \\\n  -DENABLE_NLS=ON \\\n  -DENABLE_GNUTLS=ON \\\n  -DENABLE_NETTLE=ON \\\n  -DENABLE_SELINUX=ON \\\n  -DENABLE_SYSTEMD=ON \\\n  -DENABLE_WAYLAND=ON \\\n  -DBUILD_VIEWER=ON\n\n%cmake_build\n\npushd unix/xserver\n\nautoreconf -fiv\n%configure \\\n        --disable-xorg --disable-xnest --disable-xvfb --disable-dmx \\\n        --disable-xwin --disable-xephyr --disable-kdrive --disable-xwayland \\\n        --with-pic --disable-static \\\n        --with-default-font-path=\"catalogue:%{_sysconfdir}/X11/fontpath.d,built-ins\" \\\n        --with-xkb-output=%{_localstatedir}/lib/xkb \\\n        --enable-glx --disable-dri --enable-dri2 --enable-dri3 \\\n        --disable-unit-tests \\\n        --disable-config-hal \\\n        --disable-config-udev \\\n        --without-dtrace \\\n        --disable-devel-docs \\\n        --disable-selective-werror\n\nmake TIGERVNC_BUILDDIR=\"`pwd`/../../%{__cmake_builddir}\" %{?_smp_mflags}\npopd\n\n# SELinux\npushd unix/vncserver/selinux\nmake\npopd\n\n%install\n%cmake_install\n\npushd unix/xserver/hw/vnc\n%make_install TIGERVNC_BUILDDIR=\"`pwd`/../../../../%{__cmake_builddir}\"\npopd\n\n# Install systemd unit file\npushd unix/vncserver/selinux\nmake install DESTDIR=%{buildroot}\npopd\n\n%find_lang %{name} %{name}.lang\n\n# No Xorg server, so no use for the module\nrm -f  %{buildroot}%{_libdir}/xorg/modules/extensions/libvnc.*\n\n%pre selinux\n%selinux_relabel_pre -s %{selinuxtype}\n\n%post selinux\n%selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.bz2\n%selinux_relabel_post -s %{selinuxtype}\n\n%postun selinux\nif [ $1 -eq 0 ]; then\n    %selinux_modules_uninstall -s %{selinuxtype} %{modulename}\n    %selinux_relabel_post -s %{selinuxtype}\nfi\n\n\n%files -f %{name}.lang\n%doc %{_docdir}/%{name}/README.rst\n%{_bindir}/vncviewer\n%{_datadir}/applications/*\n%{_datadir}/metainfo/*\n%{_mandir}/man1/vncviewer.1*\n\n%files server\n%config(noreplace) %{_sysconfdir}/pam.d/tigervnc\n%config(noreplace) %{_sysconfdir}/tigervnc/vncserver-config-defaults\n%config(noreplace) %{_sysconfdir}/tigervnc/vncserver-config-mandatory\n%config(noreplace) %{_sysconfdir}/tigervnc/vncserver.users\n%{_unitdir}/vncserver@.service\n%{_bindir}/x0vncserver\n%{_bindir}/w0vncserver\n%{_bindir}/w0vncserver-forget\n%{_sbindir}/vncsession\n%{_libexecdir}/vncserver\n%{_libexecdir}/vncsession-start\n%{_mandir}/man1/x0vncserver.1*\n%{_mandir}/man1/w0vncserver.1*\n%{_mandir}/man1/w0vncserver-forget.1*\n%{_mandir}/man8/vncserver.8*\n%{_mandir}/man8/vncsession.8*\n%doc %{_docdir}/%{name}/HOWTO.md\n\n%files server-minimal\n%{_bindir}/vncconfig\n%{_bindir}/vncpasswd\n%{_bindir}/Xvnc\n%{_mandir}/man1/Xvnc.1*\n%{_mandir}/man1/vncpasswd.1*\n%{_mandir}/man1/vncconfig.1*\n\n%files license\n%doc %{_docdir}/%{name}/LICENCE.TXT\n\n%files icons\n%{_datadir}/icons/hicolor/*/apps/*\n\n%files selinux\n%{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.*\n%ghost %verify(not md5 size mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}\n\n%changelog\n* Fri Aug 19 2022 Pierre Ossman <ossman@cendio.se> 1.12.80-1\n- Synced with current Fedora packaging\n\n* Tue May 18 2021 Jan Grulich <jgrulich@redhat.com> 1.11.0-1\n- SELinux package improvements\n\n* Mon Jul 27 2020 Mark Mielke <mmielke@ciena.com> 1.10.1-1\n- Update build requirements and fix unexpected rpm macro expansion.\n\n* Tue Oct 22 2019 Evan Burns <evanburnsdev@gmail.com> 1.9.80-5\n- Add support for CentOS 8\n\n* Mon Feb 11 2019 Mark Mielke <mmielke@ciena.com> 1.9.80-5\n- Automatically detect and apply the correct X.org patch.\n\n* Mon Jan 14 2019 Pierre Ossman <ossman@cendio.se> 1.9.80-4\n- Use system FLTK for build\n- Add libXrandr-devel as a dependency so x0vncserver gets resize support.\n\n* Sun Dec 09 2018 Mark Mielke <mmielke@ciena.com> 1.9.80-3\n- Update package dependencies to require version alignment between packages.\n\n* Mon Nov 26 2018 Brian P. Hinz <bphinz@users.sourceforge.net> 1.9.80-2\n- Bumped Xorg version to 1.20\n\n* Sun Jul 22 2018 Brian P. Hinz <bphinz@users.sourceforge.net> 1.9.80-1\n- Updated fltk to latest version\n\n* Thu Dec 24 2015 Brian P. Hinz <bphinz@users.sourceforge.net> 1.6.80-1\n- Adapted from RedHat EL7 Spec\n\n* Wed Sep 02 2015 Jan Grulich <jgrulich@redhat.com> - 1.3.1-3\n- Do not mention that display number is required in the file name\n  Resolves: bz#1195266\n\n* Thu Jul 30 2015 Jan Grulich <jgrulich@redhat.com> - 1.3.1-2\n- Resolves: bz#1248422\n  CVE-2014-8240 CVE-2014-8241 tigervnc: various flaws\n\n* Wed Apr 15 2015 Jan Grulich <jgrulich@redhat.com> - 1.3.1-1\n- Drop unecessary patches\n- Re-base to 1.3.1 (bug #1199453)\n- Re-build against re-based xserver (bug #1194898)\n- Check the return value from XShmAttach (bug #1072733)\n- Add missing part of xserver114.patch (bug #1140603)\n- Keep pointer in sync (bug #1100661)\n- Make input device class global (bug #1119640)\n- Add IPv6 support (bug #1162722)\n- Set initial mode as prefered (bug #1181287)\n- Do not mention that display number is required in the file name (bug #1195266)\n- Enable Xinerama extension (bug #1199437)\n- Specify full path for runuser command (bug #1208817)\n\n* Tue Sep 23 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.31.20130314svn5065\n- Rebuilt against xorg-x11-server to pick up ppc64le fix (bug #1140424).\n\n* Mon Mar 10 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.30.20130314svn5065\n- Fixed heap-based buffer overflow (CVE-2014-0011, bug #1050928).\n\n* Tue Feb 18 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.29.20130314svn5065\n- Previous patch was not applied.\n\n* Mon Feb 10 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.28.20130314svn5065\n- Clearer xstartup file (bug #923655).\n\n* Tue Jan 28 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.27.20130314svn5065\n- Use keyboard input code from tigervnc-1.3.0 (bug #1053536).\n\n* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 1.2.80-0.26.20130314svn5065\n- Mass rebuild 2014-01-24\n\n* Fri Jan 10 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.25.20130314svn5065\n- Fixed viewer crash when cursor has not been set (bug #1051333).\n\n* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 1.2.80-0.24.20130314svn5065\n- Mass rebuild 2013-12-27\n\n* Thu Dec 12 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.23.20130314svn5065\n- Avoid invalid read when ZRLE connection closed (bug #1039926).\n\n* Tue Dec 10 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.22.20130314svn5065\n- Fixed GLX initialisation (bug #1039126).\n\n* Tue Nov 19 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.21.20130314svn5065\n- Better fix for PIDFile problem (bug #1031625).\n\n* Fri Nov 08 2013 Adam Jackson <ajax@redhat.com> 1.2.80-0.20.20130314svn5065\n- Rebuild against xserver 1.15RC1\n\n* Wed Jul 24 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.18.20130314svn5065\n- Avoid PIDFile problems in systemd unit file (bug #983232).\n- Don't use shebang in vncserver script.\n\n* Wed Jul  3 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.18.20130314svn5065\n- Removed systemd_requires macro in order to fix the build.\n\n* Wed Jul  3 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.17.20130314svn5065\n- Synchronise manpages and --help output (bug #980870).\n\n* Mon Jun 17 2013 Adam Jackson <ajax@redhat.com> 1.2.80-0.16.20130314svn5065\n- tigervnc-setcursor-crash.patch: Attempt to paper over a crash in Xvnc when\n  setting the cursor.\n\n* Sat Jun 08 2013 Dennis Gilmore <dennis@ausil.us> 1.2.80-0.15.20130314svn5065\n- bump to rebuild and pick up bugfix causing X to crash on ppc and arm\n\n* Thu May 23 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.14.20130314svn5065\n- Use systemd rpm macros (bug #850340).  Moved systemd requirements\n  from main package to server sub-package.\n- Applied Debian patch to fix busy loop when run from inetd in nowait\n  mode (bug #920373).\n- Added dependency on xorg-x11-xinit to server sub-package so that\n  default window manager can be found (bug #896284, bug #923655).\n- Fixed bogus changelog date.\n\n* Thu Mar 14 2013 Adam Jackson <ajax@redhat.com> 1.2.80-0.13.20130314svn5065\n- Less RHEL customization\n\n* Thu Mar 14 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.12.20130314svn5065\n- include /etc/X11/xorg.conf.d/10-libvnc.conf sample configuration (#712482)\n- vncserver now honors specified -geometry parameter (#755947)\n\n* Tue Mar 12 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.11.20130307svn5060\n- update to r5060\n- split icons to separate package to avoid multilib issues\n\n* Tue Feb 19 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.10.20130219svn5047\n- update to r5047 (X.Org 1.14 support)\n\n* Fri Feb 15 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.80-0.9.20121126svn5015\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild\n\n* Mon Jan 21 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.8.20121126svn5015\n- rebuild due to \"jpeg8-ABI\" feature drop\n\n* Wed Jan 16 2013 Adam Tkac <atkac redhat com> 1.2.80-0.7.20121126svn5015\n- rebuild\n\n* Tue Dec 04 2012 Adam Tkac <atkac redhat com> 1.2.80-0.6.20121126svn5015\n- rebuild against new fltk\n\n* Mon Nov 26 2012 Adam Tkac <atkac redhat com> 1.2.80-0.5.20121126svn5015\n- update to r5015\n- build with -fpic instead of -fPIC on all archs except s390/sparc\n\n* Wed Nov  7 2012 Peter Robinson <pbrobinson@fedoraproject.org> 1.2.80-0.4.20120905svn4996\n- Build with -fPIC to fix FTBFS on ARM\n\n* Wed Oct 31 2012 Adam Jackson <ajax@redhat.com> 1.2.80-0.3.20120905svn4996\n- tigervnc12-xorg113-glx.patch: Fix to only init glx on the first server\n  generation\n\n* Fri Sep 28 2012 Adam Jackson <ajax@redhat.com> 1.2.80-0.2.20120905svn4996\n- tigervnc12-xorg113-glx.patch: Re-enable GLX against xserver 1.13\n\n* Fri Aug 17 2012 Adam Tkac <atkac redhat com> 1.2.80-0.1.20120905svn4996\n- update to 1.2.80\n- remove deprecated patches\n  - tigervnc-102434.patch\n  - tigervnc-viewer-reparent.patch\n  - tigervnc11-java7.patch\n- patches merged\n  - tigervnc11-xorg111.patch\n  - tigervnc11-xorg112.patch\n\n* Fri Aug 10 2012 Dave Airlie <airlied@redhat.com> 1.1.0-10\n- fix build against newer X server\n\n* Mon Jul 23 2012 Adam Jackson <ajax@redhat.com> 1.1.0-9\n- Build with the Composite extension for feature parity with other X servers\n\n* Sat Jul 21 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.0-8\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild\n\n* Thu Jul 19 2012 Dave Airlie <airlied@redhat.com> 1.1.0-7\n- fix building against X.org 1.13\n\n* Wed Apr 04 2012 Adam Jackson <ajax@redhat.com> 1.1.0-6\n- RHEL exclusion for -server-module on ppc* too\n\n* Mon Mar 26 2012 Adam Tkac <atkac redhat com> - 1.1.0-5\n- clean Xvnc's /tmp environment in service file before startup\n- fix building against the latest JAVA 7 and X.Org 1.12\n\n* Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.0-4\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild\n\n* Tue Nov 22 2011 Adam Tkac <atkac redhat com> - 1.1.0-3\n- don't build X.Org devel docs (#755782)\n- applet: BR generic java-devel instead of java-gcj-devel (#755783)\n- use runuser to start Xvnc in systemd service file (#754259)\n- don't attepmt to restart Xvnc session during update/erase (#753216)\n\n* Fri Nov 11 2011 Adam Tkac <atkac redhat com> - 1.1.0-2\n- libvnc.so: don't use unexported GetMaster function (#744881)\n- remove nasm buildreq\n\n* Mon Sep 12 2011 Adam Tkac <atkac redhat com> - 1.1.0-1\n- update to 1.1.0\n- update the xorg11 patch\n- patches merged\n  - tigervnc11-glx.patch\n  - tigervnc11-CVE-2011-1775.patch\n  - 0001-Use-memmove-instead-of-memcpy-in-fbblt.c-when-memory.patch\n\n* Thu Jul 28 2011 Adam Tkac <atkac redhat com> - 1.0.90-6\n- add systemd service file and remove legacy SysV initscript (#717227)\n\n* Thu May 12 2011 Adam Tkac <atkac redhat com> - 1.0.90-5\n- make Xvnc buildable against X.Org 1.11\n\n* Tue May 10 2011 Adam Tkac <atkac redhat com> - 1.0.90-4\n- viewer can send password without proper validation of X.509 certs\n  (CVE-2011-1775)\n\n* Wed Apr 13 2011 Adam Tkac <atkac redhat com> - 1.0.90-3\n- fix wrong usage of memcpy which caused screen artifacts (#652590)\n- don't point to inaccessible link in sysconfig/vncservers (#644975)\n\n* Fri Apr 08 2011 Adam Tkac <atkac redhat com> - 1.0.90-2\n- improve compatibility with vinagre client (#692048)\n\n* Tue Mar 22 2011 Adam Tkac <atkac redhat com> - 1.0.90-1\n- update to 1.0.90\n\n* Wed Feb 09 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.90-0.32.20110117svn4237\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild\n\n* Mon Jan 17 2011 Adam Tkac <atkac redhat com> 1.0.90-0.31.20110117svn4237\n- fix libvnc.so module loading\n\n* Mon Jan 17 2011 Adam Tkac <atkac redhat com> 1.0.90-0.30.20110117svn4237\n- update to r4237\n- patches merged\n  - tigervnc11-optionsdialog.patch\n  - tigervnc11-rh607866.patch\n\n* Fri Jan 14 2011 Adam Tkac <atkac redhat com> 1.0.90-0.29.20101208svn4225\n- improve patch for keyboard issues\n\n* Fri Jan 14 2011 Adam Tkac <atkac redhat com> 1.0.90-0.28.20101208svn4225\n- attempt to fix various keyboard-related issues (key repeating etc)\n\n* Fri Jan 07 2011 Adam Tkac <atkac redhat com> 1.0.90-0.27.20101208svn4225\n- render \"Ok\" and \"Cancel\" buttons in the options dialog correctly\n\n* Wed Dec 15 2010 Jan Görig <jgorig redhat com> 1.0.90-0.26.20101208svn4225\n- added vncserver lock file (#662784)\n\n* Fri Dec 10 2010 Adam Tkac <atkac redhat com> 1.0.90-0.25.20101208svn4225\n- update to r4225\n- patches merged\n  - tigervnc11-rh611677.patch\n  - tigervnc11-rh633931.patch\n  - tigervnc11-xorg1.10.patch\n- enable VeNCrypt and PAM support\n\n* Mon Dec 06 2010 Adam Tkac <atkac redhat com> 1.0.90-0.24.20100813svn4123\n- rebuild against xserver 1.10.X\n- 0001-Return-Success-from-generate_modkeymap-when-max_keys.patch merged\n\n* Wed Sep 29 2010 jkeating - 1.0.90-0.23.20100813svn4123\n- Rebuilt for gcc bug 634757\n\n* Tue Sep 21 2010 Adam Tkac <atkac redhat com> 1.0.90-0.22.20100420svn4030\n- drop xorg-x11-fonts-misc dependency (#636170)\n\n* Tue Sep 21 2010 Adam Tkac <atkac redhat com> 1.0.90-0.21.20100420svn4030\n- improve patch for #633645 (fix tcsh incompatibilities)\n\n* Thu Sep 16 2010 Adam Tkac <atkac redhat com> 1.0.90-0.20.20100813svn4123\n- press fake modifiers correctly (#633931)\n- supress unneeded debug information emitted from initscript (#633645)\n\n* Wed Aug 25 2010 Adam Tkac <atkac redhat com> 1.0.90-0.19.20100813svn4123\n- separate Xvnc, vncpasswd and vncconfig to -server-minimal subpkg (#626946)\n- move license to separate subpkg and Requires it from main subpkgs\n- Xvnc: handle situations when no modifiers exist well (#611677)\n\n* Fri Aug 13 2010 Adam Tkac <atkac redhat com> 1.0.90-0.18.20100813svn4123\n- update to r4123 (#617973)\n- add perl requires to -server subpkg (#619791)\n\n* Thu Jul 22 2010 Adam Tkac <atkac redhat com> 1.0.90-0.17.20100721svn4113\n- update to r4113\n- patches merged\n  - tigervnc11-rh586406.patch\n  - tigervnc11-libvnc.patch\n  - tigervnc11-rh597172.patch\n  - tigervnc11-rh600070.patch\n  - tigervnc11-options.patch\n- don't own %%{_datadir}/icons directory (#614301)\n- minor improvements in the .desktop file (#616340)\n- bundled libjpeg configure requires nasm; is executed even if system-wide\n  libjpeg is used\n\n* Fri Jul 02 2010 Adam Tkac <atkac redhat com> 1.0.90-0.16.20100420svn4030\n- build against system-wide libjpeg-turbo (#494458)\n- build no longer requires nasm\n\n* Mon Jun 28 2010 Adam Tkac <atkac redhat com> 1.0.90-0.15.20100420svn4030\n- vncserver: accept <+optname> option when specified as the first one\n\n* Thu Jun 24 2010 Adam Tkac <atkac redhat com> 1.0.90-0.14.20100420svn4030\n- fix memory leak in Xvnc input code (#597172)\n- don't crash when receive negative encoding (#600070)\n- explicitly disable udev configuration support\n- add gettext-autopoint to BR\n\n* Mon Jun 14 2010 Adam Tkac <atkac redhat com> 1.0.90-0.13.20100420svn4030\n- update URL about SSH tunneling in the sysconfig file (#601996)\n\n* Fri Jun 11 2010 Adam Tkac <atkac redhat com> 1.0.90-0.12.20100420svn4030\n- use newer gettext\n- autopoint now uses git instead of cvs, adjust BuildRequires appropriately\n\n* Thu May 13 2010 Adam Tkac <atkac redhat com> 1.0.90-0.11.20100420svn4030\n- link libvnc.so \"now\" to catch \"undefined symbol\" errors during Xorg startup\n- use always XkbConvertCase instead of XConvertCase (#580159, #586406)\n- don't link libvnc.so against libXi.la, libdix.la and libxkb.la; use symbols\n  from Xorg instead\n\n* Thu May 13 2010 Adam Tkac <atkac redhat com> 1.0.90-0.10.20100420svn4030\n- update to r4030 snapshot\n- patches merged to upstream\n  - tigervnc11-rh522369.patch\n  - tigervnc11-rh551262.patch\n  - tigervnc11-r4002.patch\n  - tigervnc11-r4014.patch\n\n* Thu Apr 08 2010 Adam Tkac <atkac redhat com> 1.0.90-0.9.20100219svn3993\n- add server-applet subpackage which contains Java vncviewer applet\n- fix Java applet; it didn't work when run from web browser\n- add xorg-x11-xkb-utils to server Requires\n\n* Fri Mar 12 2010 Adam Tkac <atkac redhat com> 1.0.90-0.8.20100219svn3993\n- add French translation to vncviewer.desktop (thanks to Alain Portal)\n\n* Thu Mar 04 2010 Adam Tkac <atkac redhat com> 1.0.90-0.7.20100219svn3993\n- don't crash during pixel format change (#522369, #551262)\n\n* Mon Mar 01 2010 Adam Tkac <atkac redhat com> 1.0.90-0.6.20100219svn3993\n- add mesa-dri-drivers and xkeyboard-config to -server Requires\n- update to r3993 1.0.90 snapshot\n  - tigervnc11-noexecstack.patch merged\n  - tigervnc11-xorg18.patch merged\n  - xserver18.patch is no longer needed\n\n* Wed Jan 27 2010 Jan Gorig <jgorig redhat com> 1.0.90-0.5.20091221svn3929\n- initscript LSB compliance fixes (#523974)\n\n* Fri Jan 22 2010 Adam Tkac <atkac redhat com> 1.0.90-0.4.20091221svn3929\n- mark stack as non-executable in jpeg ASM code\n- add xorg-x11-xauth to Requires\n- add support for X.Org 1.8\n- drop shave sources, they are no longer needed\n\n* Thu Jan 21 2010 Adam Tkac <atkac redhat com> 1.0.90-0.3.20091221svn3929\n- drop tigervnc-xorg25909.patch, it has been merged to X.Org upstream\n\n* Thu Jan 07 2010 Adam Tkac <atkac redhat com> 1.0.90-0.2.20091221svn3929\n- add patch for upstream X.Org issue #25909\n- add libXdmcp-devel to build requires to build Xvnc with XDMCP support (#552322)\n\n* Mon Dec 21 2009 Adam Tkac <atkac redhat com> 1.0.90-0.1.20091221svn3929\n- update to 1.0.90 snapshot\n- patches merged\n  - tigervnc10-compat.patch\n  - tigervnc10-rh510185.patch\n  - tigervnc10-rh524340.patch\n  - tigervnc10-rh516274.patch\n\n* Mon Oct 26 2009 Adam Tkac <atkac redhat com> 1.0.0-3\n- create Xvnc keyboard mapping before first keypress (#516274)\n\n* Thu Oct 08 2009 Adam Tkac <atkac redhat com> 1.0.0-2\n- update underlying X source to 1.6.4-0.3.fc11\n- remove bogus '-nohttpd' parameter from /etc/sysconfig/vncservers (#525629)\n- initscript LSB compliance fixes (#523974)\n- improve -LowColorSwitch documentation and handling (#510185)\n- honor dotWhenNoCursor option (and it's changes) every time (#524340)\n\n* Fri Aug 28 2009 Adam Tkac <atkac redhat com> 1.0.0-1\n- update to 1.0.0\n- tigervnc10-rh495457.patch merged to upstream\n\n* Mon Aug 24 2009 Karsten Hopp <karsten@redhat.com> 0.0.91-0.17\n- fix ifnarch s390x for server-module\n\n* Fri Aug 21 2009 Tomas Mraz <tmraz@redhat.com> - 0.0.91-0.16\n- rebuilt with new openssl\n\n* Tue Aug 04 2009 Adam Tkac <atkac redhat com> 0.0.91-0.15\n- make Xvnc compilable\n\n* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.0.91-0.14.1\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild\n\n* Mon Jul 13 2009 Adam Tkac <atkac redhat com> 0.0.91-0.13.1\n- don't write warning when initscript is called with condrestart param (#508367)\n\n* Tue Jun 23 2009 Adam Tkac <atkac redhat com> 0.0.91-0.13\n- temporary use F11 Xserver base to make Xvnc compilable\n- BuildRequires: libXi-devel\n- don't ship tigervnc-server-module on s390/s390x\n\n* Mon Jun 22 2009 Adam Tkac <atkac redhat com> 0.0.91-0.12\n- fix local rendering of cursor (#495457)\n\n* Thu Jun 18 2009 Adam Tkac <atkac redhat com> 0.0.91-0.11\n- update to 0.0.91 (1.0.0 RC1)\n- patches merged\n  - tigervnc10-rh499401.patch\n  - tigervnc10-rh497592.patch\n  - tigervnc10-rh501832.patch\n- after discusion in upstream drop tigervnc-bounds.patch\n- configure flags cleanup\n\n* Thu May 21 2009 Adam Tkac <atkac redhat com> 0.0.90-0.10\n- rebuild against 1.6.1.901 X server (#497835)\n- disable i18n, vncviewer is not UTF-8 compatible (#501832)\n\n* Mon May 18 2009 Adam Tkac <atkac redhat com> 0.0.90-0.9\n- fix vncpasswd crash on long passwords (#499401)\n- start session dbus daemon correctly (#497592)\n\n* Mon May 11 2009 Adam Tkac <atkac redhat com> 0.0.90-0.8.1\n- remove merged tigervnc-manminor.patch\n\n* Tue May 05 2009 Adam Tkac <atkac redhat com> 0.0.90-0.8\n- update to 0.0.90\n\n* Thu Apr 30 2009 Adam Tkac <atkac redhat com> 0.0.90-0.7.20090427svn3789\n- server package now requires xorg-x11-fonts-misc (#498184)\n\n* Mon Apr 27 2009 Adam Tkac <atkac redhat com> 0.0.90-0.6.20090427svn3789\n- update to r3789\n  - tigervnc-rh494801.patch merged\n- tigervnc-newfbsize.patch is no longer needed\n- fix problems when vncviewer and Xvnc run on different endianess (#496653)\n- UltraVNC and TightVNC clients work fine again (#496786)\n\n* Wed Apr 08 2009 Adam Tkac <atkac redhat com> 0.0.90-0.5.20090403svn3751\n- workaround broken fontpath handling in vncserver script (#494801)\n\n* Fri Apr 03 2009 Adam Tkac <atkac redhat com> 0.0.90-0.4.20090403svn3751\n- update to r3751\n- patches merged\n  - tigervnc-xclients.patch\n  - tigervnc-clipboard.patch\n  - tigervnc-rh212985.patch\n- basic RandR support in Xvnc (resize of the desktop)\n- use built-in libjpeg (SSE2/MMX accelerated encoding on x86 platform)\n- use Tight encoding by default\n- use TigerVNC icons\n\n* Tue Mar 03 2009 Adam Tkac <atkac redhat com> 0.0.90-0.3.20090303svn3631\n- update to r3631\n\n* Tue Mar 03 2009 Adam Tkac <atkac redhat com> 0.0.90-0.2.20090302svn3621\n- package review related fixes\n\n* Mon Mar 02 2009 Adam Tkac <atkac redhat com> 0.0.90-0.1.20090302svn3621\n- initial package, r3621\n"
  },
  {
    "path": "contrib/packages/rpm/el8/SOURCES/10-libvnc.conf",
    "content": "# This file contains configuration of libvnc.so module\n#\n# To get libvnc.so module working, do this:\n# 1. run \"vncpasswd\" from tigervnc-server package as root user\n# 2. uncomment configuration lines below\n#\n# Please note you can specify any option which Xvnc accepts.\n# Refer to `Xvnc -help` output for detailed list of options.\n\n#Section \"Module\"\n#    Load \"vnc\"\n#EndSection\n\n#Section \"Screen\"\n#    Identifier \"Screen0\n#    DefaultDepth 16\n#    Option \"SecurityTypes\" \"VncAuth\"\n#    Option \"PasswordFile\" \"/root/.config/tigervnc/passwd\"\n#EndSection\n"
  },
  {
    "path": "contrib/packages/rpm/el8/SPECS/tigervnc.spec",
    "content": "#defining macros needed by SELinux\n%global selinuxtype targeted\n%global modulename vncsession\n\nName:           tigervnc\nVersion:        @VERSION@\nRelease:        1%{?snap:.%{snap}}%{?dist}\nSummary:        A TigerVNC remote display system\n\n%global _hardened_build 1\n\nLicense:        GPLv2+\nURL:            http://www.tigervnc.com\n\nSource0:        %{name}-%{version}%{?snap:-%{snap}}.tar.bz2\nSource3:        10-libvnc.conf\n\nBuildRequires:  make\nBuildRequires:  gcc-c++\nBuildRequires:  automake, autoconf, libtool, gettext, gettext-autopoint\nBuildRequires:  cmake, desktop-file-utils, appstream\nBuildRequires:  libxkbfile-devel, openssl-devel, libpciaccess-devel\nBuildRequires:  freetype-devel, libjpeg-turbo-devel, pam-devel\nBuildRequires:  gnutls-devel, nettle-devel, gmp-devel\nBuildRequires:  zlib-devel\nBuildRequires:  libuuid-devel, glib2-devel, pipewire-devel\nBuildRequires:  wayland-devel, libxkbcommon-devel\n# X11/graphics dependencies\nBuildRequires: xorg-x11-server-source\nBuildRequires: libXext-devel, libX11-devel, libXi-devel, libXfixes-devel\nBuildRequires: libXdamage-devel, libXrandr-devel, libXt-devel, libXdmcp-devel\nBuildRequires: libXinerama-devel, mesa-libGL-devel, libxshmfence-devel\nBuildRequires: pixman-devel, libdrm-devel, mesa-libgbm-devel\nBuildRequires: xorg-x11-util-macros, xorg-x11-xtrans-devel, libXtst-devel\nBuildRequires: xorg-x11-font-utils\nBuildRequires:  libXfont2-devel\n# SELinux\nBuildRequires:  libselinux-devel, selinux-policy-devel\nBuildRequires:  systemd-devel\n\n# TigerVNC 1.4.x requires fltk 1.3.3 for keyboard handling support\n# See https://github.com/TigerVNC/tigervnc/issues/8, also bug #1208814\nBuildRequires:  fltk-devel >= 1.3.3\nBuildRequires:  xorg-x11-server-devel\n\nRequires:       hicolor-icon-theme\nRequires:       tigervnc-license\nRequires:       tigervnc-icons\n\n%description\nVirtual Network Computing (VNC) is a remote display system which\nallows you to view a computing 'desktop' environment not only on the\nmachine where it is running, but from anywhere on the Internet and\nfrom a wide variety of machine architectures.  This package contains a\nclient which will allow you to connect to other desktops running a VNC\nserver.\n\n%package server\nSummary:        A TigerVNC server\nRequires:       perl-interpreter\nRequires:       tigervnc-server-minimal = %{version}-%{release}\nRequires:       (%{name}-selinux if selinux-policy-%{selinuxtype})\nRequires:       xorg-x11-xauth\nRequires:       xorg-x11-xinit\n\n%description server\nThe VNC system allows you to access the same desktop from a wide\nvariety of platforms.  This package includes set of utilities\nwhich make usage of TigerVNC server more user friendly. It also\ncontains the x0vncserver program which can export your active\nX session, and the w0vncserver program which can export your active\nWayland session.\n\n%package server-minimal\nSummary:        A minimal installation of TigerVNC server\nRequires(post): systemd\nRequires(preun): systemd\nRequires(postun): systemd\nRequires(post): systemd\n\nRequires:       mesa-dri-drivers, xkeyboard-config, xkbcomp\nRequires:       tigervnc-license, dbus-x11\n\n%description server-minimal\nThe VNC system allows you to access the same desktop from a wide\nvariety of platforms. This package contains minimal installation\nof TigerVNC server, allowing others to access the desktop on your\nmachine.\n\n%package server-module\nSummary:        TigerVNC module to Xorg\nRequires:       xorg-x11-server-Xorg %(xserver-sdk-abi-requires ansic) %(xserver-sdk-abi-requires videodrv)\nRequires:       tigervnc-license\n\n%description server-module\nThis package contains libvnc.so module to X server, allowing others\nto access the desktop on your machine.\n\n%package license\nSummary:        License of TigerVNC suite\nBuildArch:      noarch\n\n%description license\nThis package contains license of the TigerVNC suite\n\n%package icons\nSummary:        Icons for TigerVNC viewer\nBuildArch:      noarch\n\n%description icons\nThis package contains icons for TigerVNC viewer\n\n%package selinux\nSummary:        SELinux module for TigerVNC\nBuildArch:      noarch\nBuildRequires:  selinux-policy-devel\nRequires:       selinux-policy-%{selinuxtype}\nRequires(post): selinux-policy-%{selinuxtype}\nBuildRequires:  selinux-policy-devel\n%{?selinux_requires}\n\n%description selinux\nThis package provides the SELinux policy module to ensure TigerVNC\nruns properly under an environment with SELinux enabled.\n\n%prep\n%setup -q -n %{name}-%{version}%{?snap:-%{snap}}\n\ncp -r /usr/share/xorg-x11-server-source/* unix/xserver\npushd unix/xserver\nfor all in `find . -type f -perm -001`; do\n        chmod -x \"$all\"\ndone\nxserver_patch=\"../xserver$(rpm -q --qf '%%{VERSION}' xorg-x11-server-source | awk -F. '{ print $1 $2 }').patch\"\npatch -p1 -b --suffix .vnc < \"$xserver_patch\"\npopd\n\n%build\n%ifarch sparcv9 sparc64 s390 s390x\nexport CFLAGS=\"$RPM_OPT_FLAGS -fPIC\"\n%else\nexport CFLAGS=\"$RPM_OPT_FLAGS -fpic\"\n%endif\nexport CXXFLAGS=\"$CFLAGS -std=c++11\"\n\n%cmake \\\n  -DENABLE_NLS=ON \\\n  -DENABLE_GNUTLS=ON \\\n  -DENABLE_NETTLE=ON \\\n  -DENABLE_SELINUX=ON \\\n  -DENABLE_SYSTEMD=ON \\\n  -DENABLE_WAYLAND=ON \\\n  -DBUILD_VIEWER=ON\n\n%cmake_build\n\npushd unix/xserver\n\nautoreconf -fiv\n%configure \\\n        --disable-xorg --disable-xnest --disable-xvfb --disable-dmx \\\n        --disable-xwin --disable-xephyr --disable-kdrive --disable-xwayland \\\n        --with-pic --disable-static \\\n        --with-default-font-path=\"catalogue:%{_sysconfdir}/X11/fontpath.d,built-ins\" \\\n        --with-xkb-output=%{_localstatedir}/lib/xkb \\\n        --enable-glx --disable-dri --enable-dri2 --enable-dri3 \\\n        --disable-unit-tests \\\n        --disable-config-hal \\\n        --disable-config-udev \\\n        --without-dtrace \\\n        --disable-devel-docs \\\n        --disable-selective-werror\n\nmake %{?_smp_mflags}\npopd\n\n# SELinux\npushd unix/vncserver/selinux\nmake\npopd\n\n%install\n%cmake_install\n\npushd unix/xserver/hw/vnc\n%make_install\npopd\n\n# Install systemd unit file\npushd unix/vncserver/selinux\nmake install DESTDIR=%{buildroot}\npopd\n\n%find_lang %{name} %{name}.lang\n\n# remove unwanted files\nrm -f  %{buildroot}%{_libdir}/xorg/modules/extensions/libvnc.la\n\nmkdir -p %{buildroot}%{_sysconfdir}/X11/xorg.conf.d/\ninstall -m 644 %{SOURCE3} %{buildroot}%{_sysconfdir}/X11/xorg.conf.d/10-libvnc.conf\n\n%pre selinux\n%selinux_relabel_pre -s %{selinuxtype}\n\n%post selinux\n%selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.bz2\n%selinux_relabel_post -s %{selinuxtype}\n\n%postun selinux\nif [ $1 -eq 0 ]; then\n    %selinux_modules_uninstall -s %{selinuxtype} %{modulename}\n    %selinux_relabel_post -s %{selinuxtype}\nfi\n\n\n%files -f %{name}.lang\n%doc %{_docdir}/%{name}/README.rst\n%{_bindir}/vncviewer\n%{_datadir}/applications/*\n%{_datadir}/metainfo/*\n%{_mandir}/man1/vncviewer.1*\n\n%files server\n%config(noreplace) %{_sysconfdir}/pam.d/tigervnc\n%config(noreplace) %{_sysconfdir}/tigervnc/vncserver-config-defaults\n%config(noreplace) %{_sysconfdir}/tigervnc/vncserver-config-mandatory\n%config(noreplace) %{_sysconfdir}/tigervnc/vncserver.users\n%{_unitdir}/vncserver@.service\n%{_bindir}/x0vncserver\n%{_bindir}/w0vncserver\n%{_bindir}/w0vncserver-forget\n%{_sbindir}/vncsession\n%{_libexecdir}/vncserver\n%{_libexecdir}/vncsession-start\n%{_mandir}/man1/x0vncserver.1*\n%{_mandir}/man1/w0vncserver.1*\n%{_mandir}/man1/w0vncserver-forget.1*\n%{_mandir}/man8/vncserver.8*\n%{_mandir}/man8/vncsession.8*\n%doc %{_docdir}/%{name}/HOWTO.md\n\n%files server-minimal\n%{_bindir}/vncconfig\n%{_bindir}/vncpasswd\n%{_bindir}/Xvnc\n%{_mandir}/man1/Xvnc.1*\n%{_mandir}/man1/vncpasswd.1*\n%{_mandir}/man1/vncconfig.1*\n\n%files server-module\n%{_libdir}/xorg/modules/extensions/libvnc.so\n%config(noreplace) %{_sysconfdir}/X11/xorg.conf.d/10-libvnc.conf\n\n%files license\n%doc %{_docdir}/%{name}/LICENCE.TXT\n\n%files icons\n%{_datadir}/icons/hicolor/*/apps/*\n\n%files selinux\n%{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.*\n%ghost %verify(not md5 size mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}\n\n%changelog\n* Fri Aug 19 2022 Pierre Ossman <ossman@cendio.se> 1.12.80-1\n- Synced with current Fedora packaging\n\n* Tue May 18 2021 Jan Grulich <jgrulich@redhat.com> 1.11.0-1\n- SELinux package improvements\n\n* Mon Jul 27 2020 Mark Mielke <mmielke@ciena.com> 1.10.1-1\n- Update build requirements and fix unexpected rpm macro expansion.\n\n* Tue Oct 22 2019 Evan Burns <evanburnsdev@gmail.com> 1.9.80-5\n- Add support for CentOS 8\n\n* Mon Feb 11 2019 Mark Mielke <mmielke@ciena.com> 1.9.80-5\n- Automatically detect and apply the correct X.org patch.\n\n* Mon Jan 14 2019 Pierre Ossman <ossman@cendio.se> 1.9.80-4\n- Use system FLTK for build\n- Add libXrandr-devel as a dependency so x0vncserver gets resize support.\n\n* Sun Dec 09 2018 Mark Mielke <mmielke@ciena.com> 1.9.80-3\n- Update package dependencies to require version alignment between packages.\n\n* Mon Nov 26 2018 Brian P. Hinz <bphinz@users.sourceforge.net> 1.9.80-2\n- Bumped Xorg version to 1.20\n\n* Sun Jul 22 2018 Brian P. Hinz <bphinz@users.sourceforge.net> 1.9.80-1\n- Updated fltk to latest version\n\n* Thu Dec 24 2015 Brian P. Hinz <bphinz@users.sourceforge.net> 1.6.80-1\n- Adapted from RedHat EL7 Spec\n\n* Wed Sep 02 2015 Jan Grulich <jgrulich@redhat.com> - 1.3.1-3\n- Do not mention that display number is required in the file name\n  Resolves: bz#1195266\n\n* Thu Jul 30 2015 Jan Grulich <jgrulich@redhat.com> - 1.3.1-2\n- Resolves: bz#1248422\n  CVE-2014-8240 CVE-2014-8241 tigervnc: various flaws\n\n* Wed Apr 15 2015 Jan Grulich <jgrulich@redhat.com> - 1.3.1-1\n- Drop unecessary patches\n- Re-base to 1.3.1 (bug #1199453)\n- Re-build against re-based xserver (bug #1194898)\n- Check the return value from XShmAttach (bug #1072733)\n- Add missing part of xserver114.patch (bug #1140603)\n- Keep pointer in sync (bug #1100661)\n- Make input device class global (bug #1119640)\n- Add IPv6 support (bug #1162722)\n- Set initial mode as prefered (bug #1181287)\n- Do not mention that display number is required in the file name (bug #1195266)\n- Enable Xinerama extension (bug #1199437)\n- Specify full path for runuser command (bug #1208817)\n\n* Tue Sep 23 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.31.20130314svn5065\n- Rebuilt against xorg-x11-server to pick up ppc64le fix (bug #1140424).\n\n* Mon Mar 10 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.30.20130314svn5065\n- Fixed heap-based buffer overflow (CVE-2014-0011, bug #1050928).\n\n* Tue Feb 18 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.29.20130314svn5065\n- Previous patch was not applied.\n\n* Mon Feb 10 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.28.20130314svn5065\n- Clearer xstartup file (bug #923655).\n\n* Tue Jan 28 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.27.20130314svn5065\n- Use keyboard input code from tigervnc-1.3.0 (bug #1053536).\n\n* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 1.2.80-0.26.20130314svn5065\n- Mass rebuild 2014-01-24\n\n* Fri Jan 10 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.25.20130314svn5065\n- Fixed viewer crash when cursor has not been set (bug #1051333).\n\n* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 1.2.80-0.24.20130314svn5065\n- Mass rebuild 2013-12-27\n\n* Thu Dec 12 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.23.20130314svn5065\n- Avoid invalid read when ZRLE connection closed (bug #1039926).\n\n* Tue Dec 10 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.22.20130314svn5065\n- Fixed GLX initialisation (bug #1039126).\n\n* Tue Nov 19 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.21.20130314svn5065\n- Better fix for PIDFile problem (bug #1031625).\n\n* Fri Nov 08 2013 Adam Jackson <ajax@redhat.com> 1.2.80-0.20.20130314svn5065\n- Rebuild against xserver 1.15RC1\n\n* Wed Jul 24 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.18.20130314svn5065\n- Avoid PIDFile problems in systemd unit file (bug #983232).\n- Don't use shebang in vncserver script.\n\n* Wed Jul  3 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.18.20130314svn5065\n- Removed systemd_requires macro in order to fix the build.\n\n* Wed Jul  3 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.17.20130314svn5065\n- Synchronise manpages and --help output (bug #980870).\n\n* Mon Jun 17 2013 Adam Jackson <ajax@redhat.com> 1.2.80-0.16.20130314svn5065\n- tigervnc-setcursor-crash.patch: Attempt to paper over a crash in Xvnc when\n  setting the cursor.\n\n* Sat Jun 08 2013 Dennis Gilmore <dennis@ausil.us> 1.2.80-0.15.20130314svn5065\n- bump to rebuild and pick up bugfix causing X to crash on ppc and arm\n\n* Thu May 23 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.14.20130314svn5065\n- Use systemd rpm macros (bug #850340).  Moved systemd requirements\n  from main package to server sub-package.\n- Applied Debian patch to fix busy loop when run from inetd in nowait\n  mode (bug #920373).\n- Added dependency on xorg-x11-xinit to server sub-package so that\n  default window manager can be found (bug #896284, bug #923655).\n- Fixed bogus changelog date.\n\n* Thu Mar 14 2013 Adam Jackson <ajax@redhat.com> 1.2.80-0.13.20130314svn5065\n- Less RHEL customization\n\n* Thu Mar 14 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.12.20130314svn5065\n- include /etc/X11/xorg.conf.d/10-libvnc.conf sample configuration (#712482)\n- vncserver now honors specified -geometry parameter (#755947)\n\n* Tue Mar 12 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.11.20130307svn5060\n- update to r5060\n- split icons to separate package to avoid multilib issues\n\n* Tue Feb 19 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.10.20130219svn5047\n- update to r5047 (X.Org 1.14 support)\n\n* Fri Feb 15 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.80-0.9.20121126svn5015\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild\n\n* Mon Jan 21 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.8.20121126svn5015\n- rebuild due to \"jpeg8-ABI\" feature drop\n\n* Wed Jan 16 2013 Adam Tkac <atkac redhat com> 1.2.80-0.7.20121126svn5015\n- rebuild\n\n* Tue Dec 04 2012 Adam Tkac <atkac redhat com> 1.2.80-0.6.20121126svn5015\n- rebuild against new fltk\n\n* Mon Nov 26 2012 Adam Tkac <atkac redhat com> 1.2.80-0.5.20121126svn5015\n- update to r5015\n- build with -fpic instead of -fPIC on all archs except s390/sparc\n\n* Wed Nov  7 2012 Peter Robinson <pbrobinson@fedoraproject.org> 1.2.80-0.4.20120905svn4996\n- Build with -fPIC to fix FTBFS on ARM\n\n* Wed Oct 31 2012 Adam Jackson <ajax@redhat.com> 1.2.80-0.3.20120905svn4996\n- tigervnc12-xorg113-glx.patch: Fix to only init glx on the first server\n  generation\n\n* Fri Sep 28 2012 Adam Jackson <ajax@redhat.com> 1.2.80-0.2.20120905svn4996\n- tigervnc12-xorg113-glx.patch: Re-enable GLX against xserver 1.13\n\n* Fri Aug 17 2012 Adam Tkac <atkac redhat com> 1.2.80-0.1.20120905svn4996\n- update to 1.2.80\n- remove deprecated patches\n  - tigervnc-102434.patch\n  - tigervnc-viewer-reparent.patch\n  - tigervnc11-java7.patch\n- patches merged\n  - tigervnc11-xorg111.patch\n  - tigervnc11-xorg112.patch\n\n* Fri Aug 10 2012 Dave Airlie <airlied@redhat.com> 1.1.0-10\n- fix build against newer X server\n\n* Mon Jul 23 2012 Adam Jackson <ajax@redhat.com> 1.1.0-9\n- Build with the Composite extension for feature parity with other X servers\n\n* Sat Jul 21 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.0-8\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild\n\n* Thu Jul 19 2012 Dave Airlie <airlied@redhat.com> 1.1.0-7\n- fix building against X.org 1.13\n\n* Wed Apr 04 2012 Adam Jackson <ajax@redhat.com> 1.1.0-6\n- RHEL exclusion for -server-module on ppc* too\n\n* Mon Mar 26 2012 Adam Tkac <atkac redhat com> - 1.1.0-5\n- clean Xvnc's /tmp environment in service file before startup\n- fix building against the latest JAVA 7 and X.Org 1.12\n\n* Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.0-4\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild\n\n* Tue Nov 22 2011 Adam Tkac <atkac redhat com> - 1.1.0-3\n- don't build X.Org devel docs (#755782)\n- applet: BR generic java-devel instead of java-gcj-devel (#755783)\n- use runuser to start Xvnc in systemd service file (#754259)\n- don't attepmt to restart Xvnc session during update/erase (#753216)\n\n* Fri Nov 11 2011 Adam Tkac <atkac redhat com> - 1.1.0-2\n- libvnc.so: don't use unexported GetMaster function (#744881)\n- remove nasm buildreq\n\n* Mon Sep 12 2011 Adam Tkac <atkac redhat com> - 1.1.0-1\n- update to 1.1.0\n- update the xorg11 patch\n- patches merged\n  - tigervnc11-glx.patch\n  - tigervnc11-CVE-2011-1775.patch\n  - 0001-Use-memmove-instead-of-memcpy-in-fbblt.c-when-memory.patch\n\n* Thu Jul 28 2011 Adam Tkac <atkac redhat com> - 1.0.90-6\n- add systemd service file and remove legacy SysV initscript (#717227)\n\n* Thu May 12 2011 Adam Tkac <atkac redhat com> - 1.0.90-5\n- make Xvnc buildable against X.Org 1.11\n\n* Tue May 10 2011 Adam Tkac <atkac redhat com> - 1.0.90-4\n- viewer can send password without proper validation of X.509 certs\n  (CVE-2011-1775)\n\n* Wed Apr 13 2011 Adam Tkac <atkac redhat com> - 1.0.90-3\n- fix wrong usage of memcpy which caused screen artifacts (#652590)\n- don't point to inaccessible link in sysconfig/vncservers (#644975)\n\n* Fri Apr 08 2011 Adam Tkac <atkac redhat com> - 1.0.90-2\n- improve compatibility with vinagre client (#692048)\n\n* Tue Mar 22 2011 Adam Tkac <atkac redhat com> - 1.0.90-1\n- update to 1.0.90\n\n* Wed Feb 09 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.90-0.32.20110117svn4237\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild\n\n* Mon Jan 17 2011 Adam Tkac <atkac redhat com> 1.0.90-0.31.20110117svn4237\n- fix libvnc.so module loading\n\n* Mon Jan 17 2011 Adam Tkac <atkac redhat com> 1.0.90-0.30.20110117svn4237\n- update to r4237\n- patches merged\n  - tigervnc11-optionsdialog.patch\n  - tigervnc11-rh607866.patch\n\n* Fri Jan 14 2011 Adam Tkac <atkac redhat com> 1.0.90-0.29.20101208svn4225\n- improve patch for keyboard issues\n\n* Fri Jan 14 2011 Adam Tkac <atkac redhat com> 1.0.90-0.28.20101208svn4225\n- attempt to fix various keyboard-related issues (key repeating etc)\n\n* Fri Jan 07 2011 Adam Tkac <atkac redhat com> 1.0.90-0.27.20101208svn4225\n- render \"Ok\" and \"Cancel\" buttons in the options dialog correctly\n\n* Wed Dec 15 2010 Jan Görig <jgorig redhat com> 1.0.90-0.26.20101208svn4225\n- added vncserver lock file (#662784)\n\n* Fri Dec 10 2010 Adam Tkac <atkac redhat com> 1.0.90-0.25.20101208svn4225\n- update to r4225\n- patches merged\n  - tigervnc11-rh611677.patch\n  - tigervnc11-rh633931.patch\n  - tigervnc11-xorg1.10.patch\n- enable VeNCrypt and PAM support\n\n* Mon Dec 06 2010 Adam Tkac <atkac redhat com> 1.0.90-0.24.20100813svn4123\n- rebuild against xserver 1.10.X\n- 0001-Return-Success-from-generate_modkeymap-when-max_keys.patch merged\n\n* Wed Sep 29 2010 jkeating - 1.0.90-0.23.20100813svn4123\n- Rebuilt for gcc bug 634757\n\n* Tue Sep 21 2010 Adam Tkac <atkac redhat com> 1.0.90-0.22.20100420svn4030\n- drop xorg-x11-fonts-misc dependency (#636170)\n\n* Tue Sep 21 2010 Adam Tkac <atkac redhat com> 1.0.90-0.21.20100420svn4030\n- improve patch for #633645 (fix tcsh incompatibilities)\n\n* Thu Sep 16 2010 Adam Tkac <atkac redhat com> 1.0.90-0.20.20100813svn4123\n- press fake modifiers correctly (#633931)\n- supress unneeded debug information emitted from initscript (#633645)\n\n* Wed Aug 25 2010 Adam Tkac <atkac redhat com> 1.0.90-0.19.20100813svn4123\n- separate Xvnc, vncpasswd and vncconfig to -server-minimal subpkg (#626946)\n- move license to separate subpkg and Requires it from main subpkgs\n- Xvnc: handle situations when no modifiers exist well (#611677)\n\n* Fri Aug 13 2010 Adam Tkac <atkac redhat com> 1.0.90-0.18.20100813svn4123\n- update to r4123 (#617973)\n- add perl requires to -server subpkg (#619791)\n\n* Thu Jul 22 2010 Adam Tkac <atkac redhat com> 1.0.90-0.17.20100721svn4113\n- update to r4113\n- patches merged\n  - tigervnc11-rh586406.patch\n  - tigervnc11-libvnc.patch\n  - tigervnc11-rh597172.patch\n  - tigervnc11-rh600070.patch\n  - tigervnc11-options.patch\n- don't own %%{_datadir}/icons directory (#614301)\n- minor improvements in the .desktop file (#616340)\n- bundled libjpeg configure requires nasm; is executed even if system-wide\n  libjpeg is used\n\n* Fri Jul 02 2010 Adam Tkac <atkac redhat com> 1.0.90-0.16.20100420svn4030\n- build against system-wide libjpeg-turbo (#494458)\n- build no longer requires nasm\n\n* Mon Jun 28 2010 Adam Tkac <atkac redhat com> 1.0.90-0.15.20100420svn4030\n- vncserver: accept <+optname> option when specified as the first one\n\n* Thu Jun 24 2010 Adam Tkac <atkac redhat com> 1.0.90-0.14.20100420svn4030\n- fix memory leak in Xvnc input code (#597172)\n- don't crash when receive negative encoding (#600070)\n- explicitly disable udev configuration support\n- add gettext-autopoint to BR\n\n* Mon Jun 14 2010 Adam Tkac <atkac redhat com> 1.0.90-0.13.20100420svn4030\n- update URL about SSH tunneling in the sysconfig file (#601996)\n\n* Fri Jun 11 2010 Adam Tkac <atkac redhat com> 1.0.90-0.12.20100420svn4030\n- use newer gettext\n- autopoint now uses git instead of cvs, adjust BuildRequires appropriately\n\n* Thu May 13 2010 Adam Tkac <atkac redhat com> 1.0.90-0.11.20100420svn4030\n- link libvnc.so \"now\" to catch \"undefined symbol\" errors during Xorg startup\n- use always XkbConvertCase instead of XConvertCase (#580159, #586406)\n- don't link libvnc.so against libXi.la, libdix.la and libxkb.la; use symbols\n  from Xorg instead\n\n* Thu May 13 2010 Adam Tkac <atkac redhat com> 1.0.90-0.10.20100420svn4030\n- update to r4030 snapshot\n- patches merged to upstream\n  - tigervnc11-rh522369.patch\n  - tigervnc11-rh551262.patch\n  - tigervnc11-r4002.patch\n  - tigervnc11-r4014.patch\n\n* Thu Apr 08 2010 Adam Tkac <atkac redhat com> 1.0.90-0.9.20100219svn3993\n- add server-applet subpackage which contains Java vncviewer applet\n- fix Java applet; it didn't work when run from web browser\n- add xorg-x11-xkb-utils to server Requires\n\n* Fri Mar 12 2010 Adam Tkac <atkac redhat com> 1.0.90-0.8.20100219svn3993\n- add French translation to vncviewer.desktop (thanks to Alain Portal)\n\n* Thu Mar 04 2010 Adam Tkac <atkac redhat com> 1.0.90-0.7.20100219svn3993\n- don't crash during pixel format change (#522369, #551262)\n\n* Mon Mar 01 2010 Adam Tkac <atkac redhat com> 1.0.90-0.6.20100219svn3993\n- add mesa-dri-drivers and xkeyboard-config to -server Requires\n- update to r3993 1.0.90 snapshot\n  - tigervnc11-noexecstack.patch merged\n  - tigervnc11-xorg18.patch merged\n  - xserver18.patch is no longer needed\n\n* Wed Jan 27 2010 Jan Gorig <jgorig redhat com> 1.0.90-0.5.20091221svn3929\n- initscript LSB compliance fixes (#523974)\n\n* Fri Jan 22 2010 Adam Tkac <atkac redhat com> 1.0.90-0.4.20091221svn3929\n- mark stack as non-executable in jpeg ASM code\n- add xorg-x11-xauth to Requires\n- add support for X.Org 1.8\n- drop shave sources, they are no longer needed\n\n* Thu Jan 21 2010 Adam Tkac <atkac redhat com> 1.0.90-0.3.20091221svn3929\n- drop tigervnc-xorg25909.patch, it has been merged to X.Org upstream\n\n* Thu Jan 07 2010 Adam Tkac <atkac redhat com> 1.0.90-0.2.20091221svn3929\n- add patch for upstream X.Org issue #25909\n- add libXdmcp-devel to build requires to build Xvnc with XDMCP support (#552322)\n\n* Mon Dec 21 2009 Adam Tkac <atkac redhat com> 1.0.90-0.1.20091221svn3929\n- update to 1.0.90 snapshot\n- patches merged\n  - tigervnc10-compat.patch\n  - tigervnc10-rh510185.patch\n  - tigervnc10-rh524340.patch\n  - tigervnc10-rh516274.patch\n\n* Mon Oct 26 2009 Adam Tkac <atkac redhat com> 1.0.0-3\n- create Xvnc keyboard mapping before first keypress (#516274)\n\n* Thu Oct 08 2009 Adam Tkac <atkac redhat com> 1.0.0-2\n- update underlying X source to 1.6.4-0.3.fc11\n- remove bogus '-nohttpd' parameter from /etc/sysconfig/vncservers (#525629)\n- initscript LSB compliance fixes (#523974)\n- improve -LowColorSwitch documentation and handling (#510185)\n- honor dotWhenNoCursor option (and it's changes) every time (#524340)\n\n* Fri Aug 28 2009 Adam Tkac <atkac redhat com> 1.0.0-1\n- update to 1.0.0\n- tigervnc10-rh495457.patch merged to upstream\n\n* Mon Aug 24 2009 Karsten Hopp <karsten@redhat.com> 0.0.91-0.17\n- fix ifnarch s390x for server-module\n\n* Fri Aug 21 2009 Tomas Mraz <tmraz@redhat.com> - 0.0.91-0.16\n- rebuilt with new openssl\n\n* Tue Aug 04 2009 Adam Tkac <atkac redhat com> 0.0.91-0.15\n- make Xvnc compilable\n\n* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.0.91-0.14.1\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild\n\n* Mon Jul 13 2009 Adam Tkac <atkac redhat com> 0.0.91-0.13.1\n- don't write warning when initscript is called with condrestart param (#508367)\n\n* Tue Jun 23 2009 Adam Tkac <atkac redhat com> 0.0.91-0.13\n- temporary use F11 Xserver base to make Xvnc compilable\n- BuildRequires: libXi-devel\n- don't ship tigervnc-server-module on s390/s390x\n\n* Mon Jun 22 2009 Adam Tkac <atkac redhat com> 0.0.91-0.12\n- fix local rendering of cursor (#495457)\n\n* Thu Jun 18 2009 Adam Tkac <atkac redhat com> 0.0.91-0.11\n- update to 0.0.91 (1.0.0 RC1)\n- patches merged\n  - tigervnc10-rh499401.patch\n  - tigervnc10-rh497592.patch\n  - tigervnc10-rh501832.patch\n- after discusion in upstream drop tigervnc-bounds.patch\n- configure flags cleanup\n\n* Thu May 21 2009 Adam Tkac <atkac redhat com> 0.0.90-0.10\n- rebuild against 1.6.1.901 X server (#497835)\n- disable i18n, vncviewer is not UTF-8 compatible (#501832)\n\n* Mon May 18 2009 Adam Tkac <atkac redhat com> 0.0.90-0.9\n- fix vncpasswd crash on long passwords (#499401)\n- start session dbus daemon correctly (#497592)\n\n* Mon May 11 2009 Adam Tkac <atkac redhat com> 0.0.90-0.8.1\n- remove merged tigervnc-manminor.patch\n\n* Tue May 05 2009 Adam Tkac <atkac redhat com> 0.0.90-0.8\n- update to 0.0.90\n\n* Thu Apr 30 2009 Adam Tkac <atkac redhat com> 0.0.90-0.7.20090427svn3789\n- server package now requires xorg-x11-fonts-misc (#498184)\n\n* Mon Apr 27 2009 Adam Tkac <atkac redhat com> 0.0.90-0.6.20090427svn3789\n- update to r3789\n  - tigervnc-rh494801.patch merged\n- tigervnc-newfbsize.patch is no longer needed\n- fix problems when vncviewer and Xvnc run on different endianess (#496653)\n- UltraVNC and TightVNC clients work fine again (#496786)\n\n* Wed Apr 08 2009 Adam Tkac <atkac redhat com> 0.0.90-0.5.20090403svn3751\n- workaround broken fontpath handling in vncserver script (#494801)\n\n* Fri Apr 03 2009 Adam Tkac <atkac redhat com> 0.0.90-0.4.20090403svn3751\n- update to r3751\n- patches merged\n  - tigervnc-xclients.patch\n  - tigervnc-clipboard.patch\n  - tigervnc-rh212985.patch\n- basic RandR support in Xvnc (resize of the desktop)\n- use built-in libjpeg (SSE2/MMX accelerated encoding on x86 platform)\n- use Tight encoding by default\n- use TigerVNC icons\n\n* Tue Mar 03 2009 Adam Tkac <atkac redhat com> 0.0.90-0.3.20090303svn3631\n- update to r3631\n\n* Tue Mar 03 2009 Adam Tkac <atkac redhat com> 0.0.90-0.2.20090302svn3621\n- package review related fixes\n\n* Mon Mar 02 2009 Adam Tkac <atkac redhat com> 0.0.90-0.1.20090302svn3621\n- initial package, r3621\n"
  },
  {
    "path": "contrib/packages/rpm/el9/SOURCES/10-libvnc.conf",
    "content": "# This file contains configuration of libvnc.so module\n#\n# To get libvnc.so module working, do this:\n# 1. run \"vncpasswd\" from tigervnc-server package as root user\n# 2. uncomment configuration lines below\n#\n# Please note you can specify any option which Xvnc accepts.\n# Refer to `Xvnc -help` output for detailed list of options.\n\n#Section \"Module\"\n#    Load \"vnc\"\n#EndSection\n\n#Section \"Screen\"\n#    Identifier \"Screen0\n#    DefaultDepth 16\n#    Option \"SecurityTypes\" \"VncAuth\"\n#    Option \"PasswordFile\" \"/root/.config/tigervnc/passwd\"\n#EndSection\n"
  },
  {
    "path": "contrib/packages/rpm/el9/SPECS/tigervnc.spec",
    "content": "#defining macros needed by SELinux\n%global selinuxtype targeted\n%global modulename vncsession\n\nName:           tigervnc\nVersion:        @VERSION@\nRelease:        1%{?snap:.%{snap}}%{?dist}\nSummary:        A TigerVNC remote display system\n\n%global _hardened_build 1\n\nLicense:        GPLv2+\nURL:            http://www.tigervnc.com\n\nSource0:        %{name}-%{version}%{?snap:-%{snap}}.tar.bz2\nSource3:        10-libvnc.conf\n\nBuildRequires:  make\nBuildRequires:  gcc-c++\nBuildRequires:  automake, autoconf, libtool, gettext, gettext-autopoint\nBuildRequires:  cmake, desktop-file-utils, appstream\nBuildRequires:  libxkbfile-devel, openssl-devel, libpciaccess-devel\nBuildRequires:  freetype-devel, libjpeg-turbo-devel, pam-devel\nBuildRequires:  gnutls-devel, nettle-devel, gmp-devel\nBuildRequires:  zlib-devel\nBuildRequires:  libuuid-devel, glib2-devel, pipewire-devel\nBuildRequires:  wayland-devel, libxkbcommon-devel\n# X11/graphics dependencies\nBuildRequires: xorg-x11-server-source\nBuildRequires: libXext-devel, libX11-devel, libXi-devel, libXfixes-devel\nBuildRequires: libXdamage-devel, libXrandr-devel, libXt-devel, libXdmcp-devel\nBuildRequires: libXinerama-devel, mesa-libGL-devel, libxshmfence-devel\nBuildRequires: pixman-devel, libdrm-devel, mesa-libgbm-devel\nBuildRequires: xorg-x11-util-macros, xorg-x11-xtrans-devel, libXtst-devel\nBuildRequires:  libXfont2-devel\n# SELinux\nBuildRequires:  libselinux-devel, selinux-policy-devel\nBuildRequires:  systemd-devel\n\n# TigerVNC 1.4.x requires fltk 1.3.3 for keyboard handling support\n# See https://github.com/TigerVNC/tigervnc/issues/8, also bug #1208814\nBuildRequires:  fltk-devel >= 1.3.3\nBuildRequires:  xorg-x11-server-devel\n\nRequires:       hicolor-icon-theme\nRequires:       tigervnc-license\nRequires:       tigervnc-icons\n\n%description\nVirtual Network Computing (VNC) is a remote display system which\nallows you to view a computing 'desktop' environment not only on the\nmachine where it is running, but from anywhere on the Internet and\nfrom a wide variety of machine architectures.  This package contains a\nclient which will allow you to connect to other desktops running a VNC\nserver.\n\n%package server\nSummary:        A TigerVNC server\nRequires:       perl-interpreter\nRequires:       tigervnc-server-minimal = %{version}-%{release}\nRequires:       (%{name}-selinux if selinux-policy-%{selinuxtype})\nRequires:       xorg-x11-xauth\nRequires:       xorg-x11-xinit\n\n%description server\nThe VNC system allows you to access the same desktop from a wide\nvariety of platforms.  This package includes set of utilities\nwhich make usage of TigerVNC server more user friendly. It also\ncontains the x0vncserver program which can export your active\nX session, and the w0vncserver program which can export your active\nWayland session.\n\n%package server-minimal\nSummary:        A minimal installation of TigerVNC server\nRequires(post): systemd\nRequires(preun): systemd\nRequires(postun): systemd\nRequires(post): systemd\n\nRequires:       mesa-dri-drivers, xkeyboard-config, xkbcomp\nRequires:       tigervnc-license, dbus-x11\n\n%description server-minimal\nThe VNC system allows you to access the same desktop from a wide\nvariety of platforms. This package contains minimal installation\nof TigerVNC server, allowing others to access the desktop on your\nmachine.\n\n%package server-module\nSummary:        TigerVNC module to Xorg\nRequires:       xorg-x11-server-Xorg %(xserver-sdk-abi-requires ansic) %(xserver-sdk-abi-requires videodrv)\nRequires:       tigervnc-license\n\n%description server-module\nThis package contains libvnc.so module to X server, allowing others\nto access the desktop on your machine.\n\n%package license\nSummary:        License of TigerVNC suite\nBuildArch:      noarch\n\n%description license\nThis package contains license of the TigerVNC suite\n\n%package icons\nSummary:        Icons for TigerVNC viewer\nBuildArch:      noarch\n\n%description icons\nThis package contains icons for TigerVNC viewer\n\n%package selinux\nSummary:        SELinux module for TigerVNC\nBuildArch:      noarch\nBuildRequires:  selinux-policy-devel\nRequires:       selinux-policy-%{selinuxtype}\nRequires(post): selinux-policy-%{selinuxtype}\nBuildRequires:  selinux-policy-devel\n%{?selinux_requires}\n\n%description selinux\nThis package provides the SELinux policy module to ensure TigerVNC\nruns properly under an environment with SELinux enabled.\n\n%prep\n%setup -q -n %{name}-%{version}%{?snap:-%{snap}}\n\ncp -r /usr/share/xorg-x11-server-source/* unix/xserver\npushd unix/xserver\nfor all in `find . -type f -perm -001`; do\n        chmod -x \"$all\"\ndone\nxserver_patch=\"../xserver$(rpm -q --qf '%%{VERSION}' xorg-x11-server-source | awk -F. '{ print $1 $2 }').patch\"\npatch -p1 -b --suffix .vnc < \"$xserver_patch\"\npopd\n\n%build\n%ifarch sparcv9 sparc64 s390 s390x\nexport CFLAGS=\"$RPM_OPT_FLAGS -fPIC\"\n%else\nexport CFLAGS=\"$RPM_OPT_FLAGS -fpic\"\n%endif\nexport CXXFLAGS=\"$CFLAGS -std=c++11\"\n\n%cmake \\\n  -DENABLE_NLS=ON \\\n  -DENABLE_GNUTLS=ON \\\n  -DENABLE_NETTLE=ON \\\n  -DENABLE_SELINUX=ON \\\n  -DENABLE_SYSTEMD=ON \\\n  -DENABLE_WAYLAND=ON \\\n  -DBUILD_VIEWER=ON\n\n%cmake_build\n\npushd unix/xserver\n\nautoreconf -fiv\n%configure \\\n        --disable-xorg --disable-xnest --disable-xvfb --disable-dmx \\\n        --disable-xwin --disable-xephyr --disable-kdrive --disable-xwayland \\\n        --with-pic --disable-static \\\n        --with-default-font-path=\"catalogue:%{_sysconfdir}/X11/fontpath.d,built-ins\" \\\n        --with-xkb-output=%{_localstatedir}/lib/xkb \\\n        --enable-glx --disable-dri --enable-dri2 --enable-dri3 \\\n        --disable-unit-tests \\\n        --disable-config-hal \\\n        --disable-config-udev \\\n        --without-dtrace \\\n        --disable-devel-docs \\\n        --disable-selective-werror\n\nmake TIGERVNC_BUILDDIR=\"`pwd`/../../%{__cmake_builddir}\" %{?_smp_mflags}\npopd\n\n# SELinux\npushd unix/vncserver/selinux\nmake\npopd\n\n%install\n%cmake_install\n\npushd unix/xserver/hw/vnc\n%make_install TIGERVNC_BUILDDIR=\"`pwd`/../../../../%{__cmake_builddir}\"\npopd\n\n# Install systemd unit file\npushd unix/vncserver/selinux\nmake install DESTDIR=%{buildroot}\npopd\n\n%find_lang %{name} %{name}.lang\n\n# remove unwanted files\nrm -f  %{buildroot}%{_libdir}/xorg/modules/extensions/libvnc.la\n\nmkdir -p %{buildroot}%{_sysconfdir}/X11/xorg.conf.d/\ninstall -m 644 %{SOURCE3} %{buildroot}%{_sysconfdir}/X11/xorg.conf.d/10-libvnc.conf\n\n%pre selinux\n%selinux_relabel_pre -s %{selinuxtype}\n\n%post selinux\n%selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.bz2\n%selinux_relabel_post -s %{selinuxtype}\n\n%postun selinux\nif [ $1 -eq 0 ]; then\n    %selinux_modules_uninstall -s %{selinuxtype} %{modulename}\n    %selinux_relabel_post -s %{selinuxtype}\nfi\n\n\n%files -f %{name}.lang\n%doc %{_docdir}/%{name}/README.rst\n%{_bindir}/vncviewer\n%{_datadir}/applications/*\n%{_datadir}/metainfo/*\n%{_mandir}/man1/vncviewer.1*\n\n%files server\n%config(noreplace) %{_sysconfdir}/pam.d/tigervnc\n%config(noreplace) %{_sysconfdir}/tigervnc/vncserver-config-defaults\n%config(noreplace) %{_sysconfdir}/tigervnc/vncserver-config-mandatory\n%config(noreplace) %{_sysconfdir}/tigervnc/vncserver.users\n%{_unitdir}/vncserver@.service\n%{_bindir}/x0vncserver\n%{_bindir}/w0vncserver\n%{_bindir}/w0vncserver-forget\n%{_sbindir}/vncsession\n%{_libexecdir}/vncserver\n%{_libexecdir}/vncsession-start\n%{_mandir}/man1/x0vncserver.1*\n%{_mandir}/man1/w0vncserver.1*\n%{_mandir}/man1/w0vncserver-forget.1*\n%{_mandir}/man8/vncserver.8*\n%{_mandir}/man8/vncsession.8*\n%doc %{_docdir}/%{name}/HOWTO.md\n\n%files server-minimal\n%{_bindir}/vncconfig\n%{_bindir}/vncpasswd\n%{_bindir}/Xvnc\n%{_mandir}/man1/Xvnc.1*\n%{_mandir}/man1/vncpasswd.1*\n%{_mandir}/man1/vncconfig.1*\n\n%files server-module\n%{_libdir}/xorg/modules/extensions/libvnc.so\n%config(noreplace) %{_sysconfdir}/X11/xorg.conf.d/10-libvnc.conf\n\n%files license\n%doc %{_docdir}/%{name}/LICENCE.TXT\n\n%files icons\n%{_datadir}/icons/hicolor/*/apps/*\n\n%files selinux\n%{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.*\n%ghost %verify(not md5 size mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}\n\n%changelog\n* Fri Aug 19 2022 Pierre Ossman <ossman@cendio.se> 1.12.80-1\n- Synced with current Fedora packaging\n\n* Tue May 18 2021 Jan Grulich <jgrulich@redhat.com> 1.11.0-1\n- SELinux package improvements\n\n* Mon Jul 27 2020 Mark Mielke <mmielke@ciena.com> 1.10.1-1\n- Update build requirements and fix unexpected rpm macro expansion.\n\n* Tue Oct 22 2019 Evan Burns <evanburnsdev@gmail.com> 1.9.80-5\n- Add support for CentOS 8\n\n* Mon Feb 11 2019 Mark Mielke <mmielke@ciena.com> 1.9.80-5\n- Automatically detect and apply the correct X.org patch.\n\n* Mon Jan 14 2019 Pierre Ossman <ossman@cendio.se> 1.9.80-4\n- Use system FLTK for build\n- Add libXrandr-devel as a dependency so x0vncserver gets resize support.\n\n* Sun Dec 09 2018 Mark Mielke <mmielke@ciena.com> 1.9.80-3\n- Update package dependencies to require version alignment between packages.\n\n* Mon Nov 26 2018 Brian P. Hinz <bphinz@users.sourceforge.net> 1.9.80-2\n- Bumped Xorg version to 1.20\n\n* Sun Jul 22 2018 Brian P. Hinz <bphinz@users.sourceforge.net> 1.9.80-1\n- Updated fltk to latest version\n\n* Thu Dec 24 2015 Brian P. Hinz <bphinz@users.sourceforge.net> 1.6.80-1\n- Adapted from RedHat EL7 Spec\n\n* Wed Sep 02 2015 Jan Grulich <jgrulich@redhat.com> - 1.3.1-3\n- Do not mention that display number is required in the file name\n  Resolves: bz#1195266\n\n* Thu Jul 30 2015 Jan Grulich <jgrulich@redhat.com> - 1.3.1-2\n- Resolves: bz#1248422\n  CVE-2014-8240 CVE-2014-8241 tigervnc: various flaws\n\n* Wed Apr 15 2015 Jan Grulich <jgrulich@redhat.com> - 1.3.1-1\n- Drop unecessary patches\n- Re-base to 1.3.1 (bug #1199453)\n- Re-build against re-based xserver (bug #1194898)\n- Check the return value from XShmAttach (bug #1072733)\n- Add missing part of xserver114.patch (bug #1140603)\n- Keep pointer in sync (bug #1100661)\n- Make input device class global (bug #1119640)\n- Add IPv6 support (bug #1162722)\n- Set initial mode as prefered (bug #1181287)\n- Do not mention that display number is required in the file name (bug #1195266)\n- Enable Xinerama extension (bug #1199437)\n- Specify full path for runuser command (bug #1208817)\n\n* Tue Sep 23 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.31.20130314svn5065\n- Rebuilt against xorg-x11-server to pick up ppc64le fix (bug #1140424).\n\n* Mon Mar 10 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.30.20130314svn5065\n- Fixed heap-based buffer overflow (CVE-2014-0011, bug #1050928).\n\n* Tue Feb 18 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.29.20130314svn5065\n- Previous patch was not applied.\n\n* Mon Feb 10 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.28.20130314svn5065\n- Clearer xstartup file (bug #923655).\n\n* Tue Jan 28 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.27.20130314svn5065\n- Use keyboard input code from tigervnc-1.3.0 (bug #1053536).\n\n* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 1.2.80-0.26.20130314svn5065\n- Mass rebuild 2014-01-24\n\n* Fri Jan 10 2014 Tim Waugh <twaugh@redhat.com> - 1.2.80-0.25.20130314svn5065\n- Fixed viewer crash when cursor has not been set (bug #1051333).\n\n* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 1.2.80-0.24.20130314svn5065\n- Mass rebuild 2013-12-27\n\n* Thu Dec 12 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.23.20130314svn5065\n- Avoid invalid read when ZRLE connection closed (bug #1039926).\n\n* Tue Dec 10 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.22.20130314svn5065\n- Fixed GLX initialisation (bug #1039126).\n\n* Tue Nov 19 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.21.20130314svn5065\n- Better fix for PIDFile problem (bug #1031625).\n\n* Fri Nov 08 2013 Adam Jackson <ajax@redhat.com> 1.2.80-0.20.20130314svn5065\n- Rebuild against xserver 1.15RC1\n\n* Wed Jul 24 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.18.20130314svn5065\n- Avoid PIDFile problems in systemd unit file (bug #983232).\n- Don't use shebang in vncserver script.\n\n* Wed Jul  3 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.18.20130314svn5065\n- Removed systemd_requires macro in order to fix the build.\n\n* Wed Jul  3 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.17.20130314svn5065\n- Synchronise manpages and --help output (bug #980870).\n\n* Mon Jun 17 2013 Adam Jackson <ajax@redhat.com> 1.2.80-0.16.20130314svn5065\n- tigervnc-setcursor-crash.patch: Attempt to paper over a crash in Xvnc when\n  setting the cursor.\n\n* Sat Jun 08 2013 Dennis Gilmore <dennis@ausil.us> 1.2.80-0.15.20130314svn5065\n- bump to rebuild and pick up bugfix causing X to crash on ppc and arm\n\n* Thu May 23 2013 Tim Waugh <twaugh@redhat.com> 1.2.80-0.14.20130314svn5065\n- Use systemd rpm macros (bug #850340).  Moved systemd requirements\n  from main package to server sub-package.\n- Applied Debian patch to fix busy loop when run from inetd in nowait\n  mode (bug #920373).\n- Added dependency on xorg-x11-xinit to server sub-package so that\n  default window manager can be found (bug #896284, bug #923655).\n- Fixed bogus changelog date.\n\n* Thu Mar 14 2013 Adam Jackson <ajax@redhat.com> 1.2.80-0.13.20130314svn5065\n- Less RHEL customization\n\n* Thu Mar 14 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.12.20130314svn5065\n- include /etc/X11/xorg.conf.d/10-libvnc.conf sample configuration (#712482)\n- vncserver now honors specified -geometry parameter (#755947)\n\n* Tue Mar 12 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.11.20130307svn5060\n- update to r5060\n- split icons to separate package to avoid multilib issues\n\n* Tue Feb 19 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.10.20130219svn5047\n- update to r5047 (X.Org 1.14 support)\n\n* Fri Feb 15 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.80-0.9.20121126svn5015\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild\n\n* Mon Jan 21 2013 Adam Tkac <atkac redhat com> - 1.2.80-0.8.20121126svn5015\n- rebuild due to \"jpeg8-ABI\" feature drop\n\n* Wed Jan 16 2013 Adam Tkac <atkac redhat com> 1.2.80-0.7.20121126svn5015\n- rebuild\n\n* Tue Dec 04 2012 Adam Tkac <atkac redhat com> 1.2.80-0.6.20121126svn5015\n- rebuild against new fltk\n\n* Mon Nov 26 2012 Adam Tkac <atkac redhat com> 1.2.80-0.5.20121126svn5015\n- update to r5015\n- build with -fpic instead of -fPIC on all archs except s390/sparc\n\n* Wed Nov  7 2012 Peter Robinson <pbrobinson@fedoraproject.org> 1.2.80-0.4.20120905svn4996\n- Build with -fPIC to fix FTBFS on ARM\n\n* Wed Oct 31 2012 Adam Jackson <ajax@redhat.com> 1.2.80-0.3.20120905svn4996\n- tigervnc12-xorg113-glx.patch: Fix to only init glx on the first server\n  generation\n\n* Fri Sep 28 2012 Adam Jackson <ajax@redhat.com> 1.2.80-0.2.20120905svn4996\n- tigervnc12-xorg113-glx.patch: Re-enable GLX against xserver 1.13\n\n* Fri Aug 17 2012 Adam Tkac <atkac redhat com> 1.2.80-0.1.20120905svn4996\n- update to 1.2.80\n- remove deprecated patches\n  - tigervnc-102434.patch\n  - tigervnc-viewer-reparent.patch\n  - tigervnc11-java7.patch\n- patches merged\n  - tigervnc11-xorg111.patch\n  - tigervnc11-xorg112.patch\n\n* Fri Aug 10 2012 Dave Airlie <airlied@redhat.com> 1.1.0-10\n- fix build against newer X server\n\n* Mon Jul 23 2012 Adam Jackson <ajax@redhat.com> 1.1.0-9\n- Build with the Composite extension for feature parity with other X servers\n\n* Sat Jul 21 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.0-8\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild\n\n* Thu Jul 19 2012 Dave Airlie <airlied@redhat.com> 1.1.0-7\n- fix building against X.org 1.13\n\n* Wed Apr 04 2012 Adam Jackson <ajax@redhat.com> 1.1.0-6\n- RHEL exclusion for -server-module on ppc* too\n\n* Mon Mar 26 2012 Adam Tkac <atkac redhat com> - 1.1.0-5\n- clean Xvnc's /tmp environment in service file before startup\n- fix building against the latest JAVA 7 and X.Org 1.12\n\n* Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.0-4\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild\n\n* Tue Nov 22 2011 Adam Tkac <atkac redhat com> - 1.1.0-3\n- don't build X.Org devel docs (#755782)\n- applet: BR generic java-devel instead of java-gcj-devel (#755783)\n- use runuser to start Xvnc in systemd service file (#754259)\n- don't attepmt to restart Xvnc session during update/erase (#753216)\n\n* Fri Nov 11 2011 Adam Tkac <atkac redhat com> - 1.1.0-2\n- libvnc.so: don't use unexported GetMaster function (#744881)\n- remove nasm buildreq\n\n* Mon Sep 12 2011 Adam Tkac <atkac redhat com> - 1.1.0-1\n- update to 1.1.0\n- update the xorg11 patch\n- patches merged\n  - tigervnc11-glx.patch\n  - tigervnc11-CVE-2011-1775.patch\n  - 0001-Use-memmove-instead-of-memcpy-in-fbblt.c-when-memory.patch\n\n* Thu Jul 28 2011 Adam Tkac <atkac redhat com> - 1.0.90-6\n- add systemd service file and remove legacy SysV initscript (#717227)\n\n* Thu May 12 2011 Adam Tkac <atkac redhat com> - 1.0.90-5\n- make Xvnc buildable against X.Org 1.11\n\n* Tue May 10 2011 Adam Tkac <atkac redhat com> - 1.0.90-4\n- viewer can send password without proper validation of X.509 certs\n  (CVE-2011-1775)\n\n* Wed Apr 13 2011 Adam Tkac <atkac redhat com> - 1.0.90-3\n- fix wrong usage of memcpy which caused screen artifacts (#652590)\n- don't point to inaccessible link in sysconfig/vncservers (#644975)\n\n* Fri Apr 08 2011 Adam Tkac <atkac redhat com> - 1.0.90-2\n- improve compatibility with vinagre client (#692048)\n\n* Tue Mar 22 2011 Adam Tkac <atkac redhat com> - 1.0.90-1\n- update to 1.0.90\n\n* Wed Feb 09 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.90-0.32.20110117svn4237\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild\n\n* Mon Jan 17 2011 Adam Tkac <atkac redhat com> 1.0.90-0.31.20110117svn4237\n- fix libvnc.so module loading\n\n* Mon Jan 17 2011 Adam Tkac <atkac redhat com> 1.0.90-0.30.20110117svn4237\n- update to r4237\n- patches merged\n  - tigervnc11-optionsdialog.patch\n  - tigervnc11-rh607866.patch\n\n* Fri Jan 14 2011 Adam Tkac <atkac redhat com> 1.0.90-0.29.20101208svn4225\n- improve patch for keyboard issues\n\n* Fri Jan 14 2011 Adam Tkac <atkac redhat com> 1.0.90-0.28.20101208svn4225\n- attempt to fix various keyboard-related issues (key repeating etc)\n\n* Fri Jan 07 2011 Adam Tkac <atkac redhat com> 1.0.90-0.27.20101208svn4225\n- render \"Ok\" and \"Cancel\" buttons in the options dialog correctly\n\n* Wed Dec 15 2010 Jan Görig <jgorig redhat com> 1.0.90-0.26.20101208svn4225\n- added vncserver lock file (#662784)\n\n* Fri Dec 10 2010 Adam Tkac <atkac redhat com> 1.0.90-0.25.20101208svn4225\n- update to r4225\n- patches merged\n  - tigervnc11-rh611677.patch\n  - tigervnc11-rh633931.patch\n  - tigervnc11-xorg1.10.patch\n- enable VeNCrypt and PAM support\n\n* Mon Dec 06 2010 Adam Tkac <atkac redhat com> 1.0.90-0.24.20100813svn4123\n- rebuild against xserver 1.10.X\n- 0001-Return-Success-from-generate_modkeymap-when-max_keys.patch merged\n\n* Wed Sep 29 2010 jkeating - 1.0.90-0.23.20100813svn4123\n- Rebuilt for gcc bug 634757\n\n* Tue Sep 21 2010 Adam Tkac <atkac redhat com> 1.0.90-0.22.20100420svn4030\n- drop xorg-x11-fonts-misc dependency (#636170)\n\n* Tue Sep 21 2010 Adam Tkac <atkac redhat com> 1.0.90-0.21.20100420svn4030\n- improve patch for #633645 (fix tcsh incompatibilities)\n\n* Thu Sep 16 2010 Adam Tkac <atkac redhat com> 1.0.90-0.20.20100813svn4123\n- press fake modifiers correctly (#633931)\n- supress unneeded debug information emitted from initscript (#633645)\n\n* Wed Aug 25 2010 Adam Tkac <atkac redhat com> 1.0.90-0.19.20100813svn4123\n- separate Xvnc, vncpasswd and vncconfig to -server-minimal subpkg (#626946)\n- move license to separate subpkg and Requires it from main subpkgs\n- Xvnc: handle situations when no modifiers exist well (#611677)\n\n* Fri Aug 13 2010 Adam Tkac <atkac redhat com> 1.0.90-0.18.20100813svn4123\n- update to r4123 (#617973)\n- add perl requires to -server subpkg (#619791)\n\n* Thu Jul 22 2010 Adam Tkac <atkac redhat com> 1.0.90-0.17.20100721svn4113\n- update to r4113\n- patches merged\n  - tigervnc11-rh586406.patch\n  - tigervnc11-libvnc.patch\n  - tigervnc11-rh597172.patch\n  - tigervnc11-rh600070.patch\n  - tigervnc11-options.patch\n- don't own %%{_datadir}/icons directory (#614301)\n- minor improvements in the .desktop file (#616340)\n- bundled libjpeg configure requires nasm; is executed even if system-wide\n  libjpeg is used\n\n* Fri Jul 02 2010 Adam Tkac <atkac redhat com> 1.0.90-0.16.20100420svn4030\n- build against system-wide libjpeg-turbo (#494458)\n- build no longer requires nasm\n\n* Mon Jun 28 2010 Adam Tkac <atkac redhat com> 1.0.90-0.15.20100420svn4030\n- vncserver: accept <+optname> option when specified as the first one\n\n* Thu Jun 24 2010 Adam Tkac <atkac redhat com> 1.0.90-0.14.20100420svn4030\n- fix memory leak in Xvnc input code (#597172)\n- don't crash when receive negative encoding (#600070)\n- explicitly disable udev configuration support\n- add gettext-autopoint to BR\n\n* Mon Jun 14 2010 Adam Tkac <atkac redhat com> 1.0.90-0.13.20100420svn4030\n- update URL about SSH tunneling in the sysconfig file (#601996)\n\n* Fri Jun 11 2010 Adam Tkac <atkac redhat com> 1.0.90-0.12.20100420svn4030\n- use newer gettext\n- autopoint now uses git instead of cvs, adjust BuildRequires appropriately\n\n* Thu May 13 2010 Adam Tkac <atkac redhat com> 1.0.90-0.11.20100420svn4030\n- link libvnc.so \"now\" to catch \"undefined symbol\" errors during Xorg startup\n- use always XkbConvertCase instead of XConvertCase (#580159, #586406)\n- don't link libvnc.so against libXi.la, libdix.la and libxkb.la; use symbols\n  from Xorg instead\n\n* Thu May 13 2010 Adam Tkac <atkac redhat com> 1.0.90-0.10.20100420svn4030\n- update to r4030 snapshot\n- patches merged to upstream\n  - tigervnc11-rh522369.patch\n  - tigervnc11-rh551262.patch\n  - tigervnc11-r4002.patch\n  - tigervnc11-r4014.patch\n\n* Thu Apr 08 2010 Adam Tkac <atkac redhat com> 1.0.90-0.9.20100219svn3993\n- add server-applet subpackage which contains Java vncviewer applet\n- fix Java applet; it didn't work when run from web browser\n- add xorg-x11-xkb-utils to server Requires\n\n* Fri Mar 12 2010 Adam Tkac <atkac redhat com> 1.0.90-0.8.20100219svn3993\n- add French translation to vncviewer.desktop (thanks to Alain Portal)\n\n* Thu Mar 04 2010 Adam Tkac <atkac redhat com> 1.0.90-0.7.20100219svn3993\n- don't crash during pixel format change (#522369, #551262)\n\n* Mon Mar 01 2010 Adam Tkac <atkac redhat com> 1.0.90-0.6.20100219svn3993\n- add mesa-dri-drivers and xkeyboard-config to -server Requires\n- update to r3993 1.0.90 snapshot\n  - tigervnc11-noexecstack.patch merged\n  - tigervnc11-xorg18.patch merged\n  - xserver18.patch is no longer needed\n\n* Wed Jan 27 2010 Jan Gorig <jgorig redhat com> 1.0.90-0.5.20091221svn3929\n- initscript LSB compliance fixes (#523974)\n\n* Fri Jan 22 2010 Adam Tkac <atkac redhat com> 1.0.90-0.4.20091221svn3929\n- mark stack as non-executable in jpeg ASM code\n- add xorg-x11-xauth to Requires\n- add support for X.Org 1.8\n- drop shave sources, they are no longer needed\n\n* Thu Jan 21 2010 Adam Tkac <atkac redhat com> 1.0.90-0.3.20091221svn3929\n- drop tigervnc-xorg25909.patch, it has been merged to X.Org upstream\n\n* Thu Jan 07 2010 Adam Tkac <atkac redhat com> 1.0.90-0.2.20091221svn3929\n- add patch for upstream X.Org issue #25909\n- add libXdmcp-devel to build requires to build Xvnc with XDMCP support (#552322)\n\n* Mon Dec 21 2009 Adam Tkac <atkac redhat com> 1.0.90-0.1.20091221svn3929\n- update to 1.0.90 snapshot\n- patches merged\n  - tigervnc10-compat.patch\n  - tigervnc10-rh510185.patch\n  - tigervnc10-rh524340.patch\n  - tigervnc10-rh516274.patch\n\n* Mon Oct 26 2009 Adam Tkac <atkac redhat com> 1.0.0-3\n- create Xvnc keyboard mapping before first keypress (#516274)\n\n* Thu Oct 08 2009 Adam Tkac <atkac redhat com> 1.0.0-2\n- update underlying X source to 1.6.4-0.3.fc11\n- remove bogus '-nohttpd' parameter from /etc/sysconfig/vncservers (#525629)\n- initscript LSB compliance fixes (#523974)\n- improve -LowColorSwitch documentation and handling (#510185)\n- honor dotWhenNoCursor option (and it's changes) every time (#524340)\n\n* Fri Aug 28 2009 Adam Tkac <atkac redhat com> 1.0.0-1\n- update to 1.0.0\n- tigervnc10-rh495457.patch merged to upstream\n\n* Mon Aug 24 2009 Karsten Hopp <karsten@redhat.com> 0.0.91-0.17\n- fix ifnarch s390x for server-module\n\n* Fri Aug 21 2009 Tomas Mraz <tmraz@redhat.com> - 0.0.91-0.16\n- rebuilt with new openssl\n\n* Tue Aug 04 2009 Adam Tkac <atkac redhat com> 0.0.91-0.15\n- make Xvnc compilable\n\n* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.0.91-0.14.1\n- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild\n\n* Mon Jul 13 2009 Adam Tkac <atkac redhat com> 0.0.91-0.13.1\n- don't write warning when initscript is called with condrestart param (#508367)\n\n* Tue Jun 23 2009 Adam Tkac <atkac redhat com> 0.0.91-0.13\n- temporary use F11 Xserver base to make Xvnc compilable\n- BuildRequires: libXi-devel\n- don't ship tigervnc-server-module on s390/s390x\n\n* Mon Jun 22 2009 Adam Tkac <atkac redhat com> 0.0.91-0.12\n- fix local rendering of cursor (#495457)\n\n* Thu Jun 18 2009 Adam Tkac <atkac redhat com> 0.0.91-0.11\n- update to 0.0.91 (1.0.0 RC1)\n- patches merged\n  - tigervnc10-rh499401.patch\n  - tigervnc10-rh497592.patch\n  - tigervnc10-rh501832.patch\n- after discusion in upstream drop tigervnc-bounds.patch\n- configure flags cleanup\n\n* Thu May 21 2009 Adam Tkac <atkac redhat com> 0.0.90-0.10\n- rebuild against 1.6.1.901 X server (#497835)\n- disable i18n, vncviewer is not UTF-8 compatible (#501832)\n\n* Mon May 18 2009 Adam Tkac <atkac redhat com> 0.0.90-0.9\n- fix vncpasswd crash on long passwords (#499401)\n- start session dbus daemon correctly (#497592)\n\n* Mon May 11 2009 Adam Tkac <atkac redhat com> 0.0.90-0.8.1\n- remove merged tigervnc-manminor.patch\n\n* Tue May 05 2009 Adam Tkac <atkac redhat com> 0.0.90-0.8\n- update to 0.0.90\n\n* Thu Apr 30 2009 Adam Tkac <atkac redhat com> 0.0.90-0.7.20090427svn3789\n- server package now requires xorg-x11-fonts-misc (#498184)\n\n* Mon Apr 27 2009 Adam Tkac <atkac redhat com> 0.0.90-0.6.20090427svn3789\n- update to r3789\n  - tigervnc-rh494801.patch merged\n- tigervnc-newfbsize.patch is no longer needed\n- fix problems when vncviewer and Xvnc run on different endianess (#496653)\n- UltraVNC and TightVNC clients work fine again (#496786)\n\n* Wed Apr 08 2009 Adam Tkac <atkac redhat com> 0.0.90-0.5.20090403svn3751\n- workaround broken fontpath handling in vncserver script (#494801)\n\n* Fri Apr 03 2009 Adam Tkac <atkac redhat com> 0.0.90-0.4.20090403svn3751\n- update to r3751\n- patches merged\n  - tigervnc-xclients.patch\n  - tigervnc-clipboard.patch\n  - tigervnc-rh212985.patch\n- basic RandR support in Xvnc (resize of the desktop)\n- use built-in libjpeg (SSE2/MMX accelerated encoding on x86 platform)\n- use Tight encoding by default\n- use TigerVNC icons\n\n* Tue Mar 03 2009 Adam Tkac <atkac redhat com> 0.0.90-0.3.20090303svn3631\n- update to r3631\n\n* Tue Mar 03 2009 Adam Tkac <atkac redhat com> 0.0.90-0.2.20090302svn3621\n- package review related fixes\n\n* Mon Mar 02 2009 Adam Tkac <atkac redhat com> 0.0.90-0.1.20090302svn3621\n- initial package, r3621\n"
  },
  {
    "path": "doc/keyboard-test.txt",
    "content": "Test protocol for keyboard handling\n===================================\n\nPlatform specific tests/issues are marked with [].\n\nThese tests are primarily about what is sent over the protocol and some\nmay be difficult or impossible to test using normal applications. One\nsuch case is that xev will see fake KeyRelease events on key repeat,\neven when no such events were sent by the client. In these cases you\ncan turn on debug logging in either the client or the server by\nspecifying \"-Log *:stderr:100\".\n\nWe currently have a limitation in Xvnc where it can run out of symbols,\nresulting in nothing being sent to the applications. Just run setxkbmap\nwith any layout to reset the symbol table.\n\nClient (classic, non-raw, mode)\n-------------------------------\n\n- Normal symbols:\n\n  - ASCII characters\n  - Latin 1 character\n  - Unicode BMP characters\n  - Unicode non-BMP characters (does any layout actually have these?)\n\n- Dead keys:\n\n  These are not available on a single layout, so you need to switch to\n  test everything. The useful layouts also differ per platform:\n\n    X11: US International for most, Greek for some specific diacretics\n    Win: US International, Czech, Greek Polytonic, Vietnamese\n    OS X: ABC Extended (FIXME: lots of broken keys),\n          Greek (FIXME: cannot be used with TigerVNC)\n\n  - Grave\n  - Acute\n  - Circumflex\n  - Tilde\n  - Macron (FIXME: broken on Win)\n  - Breve\n  - Dot above\n  - Dot below\n  - Diaeresis\n  - Ring above\n  - Double acute\n  - Caron\n  - Cedilla\n  - Ogonek\n  - Ypogegrammeni (iota below) (FIXME: broken on Win)\n  - Dialytika tonos [Win] (Diaresis on X11, and maybe OS X?)\n  - Comma above (FIXME: broken on Win)\n  - Reversed comma above (FIXME: broken on Win)\n  - Horn [X11?]\n  - Hook above [Win?]\n  - Hook below [X11?, Win?]\n  - Dakuten (Katakana voiced mark) (Only Input Methods layouts?)\n  - Handakuten (Katakana semi-voiced mark) (Only Input Methods layouts?)\n  - FIXME: Many more that we currently probably don't support\n\n  - No composition on client\n\n- Modifiers:\n\n  X11: You can usually toggle Hyper/Super and Compose/Scroll_Lock using\n       XKB options.\n\n  - CapsLock, NumLock\n  - Shift, Ctrl\n  - Alt, AltGr, Super [Win, X11]\n  - Ctrl+AltGr [Win]\n  - Meta [X11]\n  - Left/right identification (FIXME: broken release for Shift on Win)\n  - CmdL => AltL, CmdR => SuperL, AltL => ModeSwitch, AltR => Level3Shift [OS X]\n  - Hyper sends Super [X11]\n\n  - CapsLock, Shift and AltGr affect symbol lookup\n  - Ctrl does not affect symbol lookup\n  - Ctrl+Alt+<ANY> sends the same symbol as <ANY>\n  - \"Shift press, A press, Shift release, A release\" should not send \"a release\"\n\n- Numpad:\n\n  - NumLock affects symbol lookup [Win, X11]\n  - Numpad specific symbols are sent\n  - Decimal key should send Decimal for layouts with . as a symbol, and\n    Separator for layouts with , as a symbol\n  - Shift inverts NumLock behaviour [X11]\n  - Shift turns NumLock off, but not on [Win] (FIXME: fake Shifts also sent)\n\n- Multimedia keys:\n\n  OS X: FIXME: all broken\n\n  - Back, Forward, Refresh, Stop\n  - HomePage, Search, Favourites (FIXME: broken on Win)\n  - Mail, Calculator\n  - Volume up, down, mute\n  - Media next, previous, stop, play\n  - Sleep (FIXME: broken on Win)\n  - FIXME: probably more keys exist\n\n- Non-character keys:\n\n  - F1-F24 (FIXME: F14-F15 broken on OS X)\n  - Tab, Space, Backspace, Return, Esc\n  - LeftTab sends Tab [X11]\n  - PrntScrn, ScrollLock, Pause [X11, Win]\n  - Help [X11?, OS X]\n  - Insert [X11, Win]\n  - Delete, Home, End, PageUp, PageDown\n  - Arrow keys\n  - Menu\n  - Alt+PrntScrn sends Sys_Req [Win]\n\n- French layout (AZERTY and inverted shift behaviour for many keys)\n\n- Local layout changes are respected\n\nClient (raw mode)\n-----------------\n\n- All physical keys (modifiers or type of symbol shouldn't matter)\n\n  - Normal keys\n  - Dead keys\n  - Numpad\n  - Multimedia keys\n  - Non-character keys\n\nClient (both modes)\n-------------------\n\n- Key repeat should not send repeated release events\n\n- Keys are released on loss of focus\n\n- Local input methods are disabled/enabled with focus\n\n- System keys should be grabbed in full screen (FIXME: lots missing on Win)\n\n  The exact keys depends on the system and configuration, but it\n  is usually variants of these:\n\n  - Alt+Tab\n  - Super (and Super+other)\n  - Multimedia keys\n  - Ctrl+Alt+Delete\n  - Ctrl+Esc\n  - F8-F12\n\n- Lock key states:\n\n  - Adjusted on server when connecting\n  - Adjusted on server when regaining focus\n  - Server changes are honored when focused\n  - Server changes are not honored when not focused\n\n  - CapsLock\n  - NumLock (hidden state on macOS)\n  - ScollLock* [X11, Win]\n\n  * Usually needs to be enabled with: xmodmap -e \"add mod3 = Scroll_Lock\"\n\n- Virtual keyboard (as much of the above as is possible)\n\nServer\n------\n\n- Fake key events\n\n  An extra press or release should be added before the real key press\n  in order to get the correct state to get the desired symbol. A second\n  fake event should be added after the real key press to restore state.\n  No extra events should be added for a key release.\n\n  Possible fake keys:\n\n  - Shift\n  - AltGr\n\n  - Shift+Tab bypasses this and never fake releases Shift\n\n- Alternative keys\n\n  A semantically equivalent key is sent when the desired key cannot be\n  reached in the current keyboard state:\n\n  - Left modifier <=> Right modifier (e.g. Alt_R for Alt_L)\n  - Keypad key <=> Standard key\n  - ISO_Level3_Shift <=> Mode_Switch\n\n- Meta for Shift+Alt (if server keymap agrees)\n\n- Lock key heuristics (for clients without lock key extension)\n\n  - CapsLock is corrected when A-Z or a-z are pressed\n  - CapsLock is corrected when Shift and A-Z or a-z are pressed*\n  - NumLock is corrected when 0-9 on the keypad are pressed\n\n  * Gives incorrect behaviour if the client doesn't have \"Shift cancels\n    CapsLock behaviour\", e.g. macOS\n"
  },
  {
    "path": "java/.gitignore",
    "content": "*.class\n*.jar\n.idea/\ntimestamp\n"
  },
  {
    "path": "java/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.10.0)\n\nproject(tigervnc-java Java)\nif(NOT VERSION)\n  set(VERSION 1.16.80)\nendif()\n\nfind_package(Java)\n\nset(DEFAULT_JAVACFLAGS \"-source 8 -target 8 -encoding UTF-8 -Xlint:all,-serial,-cast,-unchecked,-fallthrough,-dep-ann,-deprecation,-rawtypes\")\nset(JAVACFLAGS ${DEFAULT_JAVACFLAGS} CACHE STRING\n  \"Java compiler flags (Default: ${DEFAULT_JAVACFLAGS})\")\nmessage(STATUS \"Java compiler flags = ${JAVACFLAGS}\")\n\nset(CLASSPATH com/tigervnc/vncviewer)\nset(SRCDIR ${CMAKE_CURRENT_SOURCE_DIR})\nset(BINDIR ${CMAKE_CURRENT_BINARY_DIR})\nset(JAVA_KEYSTORE NOTFOUND CACHE STRING \"URL of keystore location\")\nset(JAVA_KEYSTORE_TYPE \"jks\" CACHE STRING \"Type of keystore (Default: \\\"jks\\\")\")\nset(JAVA_KEY_ALIAS NOTFOUND CACHE STRING \"Alias for the keystore entry used to generate the signature\")\nset(JAVA_STOREPASS NOTFOUND CACHE STRING \"Password required to access the keystore\")\nset(JAVA_KEYPASS NOTFOUND CACHE STRING \"Password used to protect the private key of the specified keystore entry\")\nset(JAVA_PKCS11_PROVIDER_CLASS \"sun.security.pkcs11.SunPKCS11\" CACHE STRING \"PKCS11 SecurityProvider class name\")\nset(JAVA_PKCS11_PROVIDER_ARG NOTFOUND CACHE STRING \"Path to the PKCS11 security provider class config file\")\nset(JAVA_TSA_URL NOTFOUND CACHE STRING \"URL of Time Stamping Authority (TSA)\")\nset(JAVA_CERT_CHAIN NOTFOUND CACHE STRING \"Path to CA certificate chain file\")\n\nif(NOT BUILD)\n\tSTRING(TIMESTAMP BUILD \"%Y%m%d\" UTC)\nendif()\nSTRING(TIMESTAMP JAVA_DATE \"%Y-%m-%d\" UTC)\nSTRING(TIMESTAMP JAVA_TIME \"%H:%M:%S\" UTC)\n\nset(JAVA_SOURCES \"\")\nset(JAVA_CLASSES \"\")\n\nset(JSCH_CLASSNAMES\n  DH\n  DHEC256\n  DHEC384\n  DHEC521\n  DHECN\n  DHGEX256\n  DHG1\n  DHG14\n  DHGEX\n  ECDH\n  JSch\n  Session\n  UserAuth\n  UserAuthKeyboardInteractive\n  UserAuthPassword\n  UserAuthPublicKey\n  UserAuthNone\n  jce/AES128CBC\n  jce/AES128CTR\n  jce/AES192CBC\n  jce/AES192CTR\n  jce/AES256CBC\n  jce/AES256CTR\n  jce/ARCFOUR\n  jce/ARCFOUR128\n  jce/ARCFOUR256\n  jce/BlowfishCBC\n  jce/DH\n\tjce/ECDH256\n\tjce/ECDH384\n\tjce/ECDH521\n\tjce/ECDHN\n  jce/HMAC\n  jce/HMACMD5\n  jce/HMACMD596\n  jce/HMACSHA1\n  jce/HMACSHA196\n  jce/HMACSHA256\n  jce/HMACSHA512\n  jce/KeyPairGenDSA\n  jce/KeyPairGenECDSA\n  jce/KeyPairGenRSA\n  jce/MD5\n  jce/PBKDF\n  jce/Random\n  jce/SHA1\n  jce/SHA256\n  jce/SHA384\n  jce/SHA512\n  jce/SignatureDSA\n  jce/SignatureECDSA\n  jce/SignatureRSA\n  jce/TripleDESCBC\n  jce/TripleDESCTR\n  jcraft/Compression\n  jcraft/HMAC\n  jcraft/HMACMD596\n  jcraft/HMACMD5\n  jcraft/HMACSHA196\n  jcraft/HMACSHA1)\n\nforeach(class ${JSCH_CLASSNAMES})\n  set(JAVA_SOURCES ${JAVA_SOURCES} com/jcraft/jsch/${class}.java)\n  set(JAVA_CLASSES ${JAVA_CLASSES}\n    ${BINDIR}/com/jcraft/jsch/${class}.class)\nendforeach()\n\nfile(GLOB DEPEND_SOURCES\n  ${SRCDIR}/${CLASSPATH}/*.java\n  ${SRCDIR}/com/tigervnc/rfb/*.java\n  ${SRCDIR}/com/tigervnc/rdr/*.java\n  ${SRCDIR}/com/tigervnc/network/*.java\n  ${SRCDIR}/com/jcraft/jsch/*.java\n  ${SRCDIR}/com/jcraft/jsch/jcraft/*.java\n  ${SRCDIR}/com/jcraft/jsch/jgss/*.java\n  ${SRCDIR}/com/jcraft/jzlib/*.java)\n\nstring(REGEX REPLACE \" \" \";\" JAVACFLAGS \"${JAVACFLAGS}\")\nadd_custom_command(OUTPUT ${JAVA_CLASSES}\n  DEPENDS ${JAVA_SOURCES} ${DEPEND_SOURCES}\n  COMMAND ${JAVA_COMPILE}\n  ARGS ${JAVACFLAGS} -sourcepath ${SRCDIR} -d ${BINDIR} \n    ${CLASSPATH}/VncViewer.java ${JAVA_SOURCES}\n\tWORKING_DIRECTORY ${SRCDIR})\n\nconfigure_file(${CLASSPATH}/timestamp.in ${CLASSPATH}/timestamp)\n\nif(NOT \"${SRCDIR}\" STREQUAL \"${BINDIR}\")\n\nset(ICONS\ntigervnc.ico\ntigervnc.png\ninsecure.png\nsecure.png)\n\nforeach(icon ${ICONS})\n  add_custom_command(OUTPUT ${BINDIR}/${CLASSPATH}/${icon}\n    COMMAND ${CMAKE_COMMAND} -E copy_if_different\n      ${SRCDIR}/${CLASSPATH}/${icon} ${BINDIR}/${CLASSPATH}/${icon}\n    DEPENDS ${SRCDIR}/${CLASSPATH}/${icon})\nendforeach()\n\nendif()\n\nstring(REGEX REPLACE \"jar\" \"\" Java_PATH ${Java_JAR_EXECUTABLE})\nstring(REGEX REPLACE \".exe\" \"\" Java_PATH ${Java_PATH})\n\nadd_custom_command(OUTPUT VncViewer.jar\n  DEPENDS ${JAVA_CLASSES}\n    ${SRCDIR}/${CLASSPATH}/MANIFEST.MF\n    ${BINDIR}/${CLASSPATH}/timestamp\n    ${BINDIR}/${CLASSPATH}/tigervnc.ico\n    ${BINDIR}/${CLASSPATH}/tigervnc.png\n    ${BINDIR}/${CLASSPATH}/insecure.png\n    ${BINDIR}/${CLASSPATH}/secure.png\n  COMMAND ${JAVA_ARCHIVE}\n  ARGS cfm VncViewer.jar\n    ${SRCDIR}/${CLASSPATH}/MANIFEST.MF\n    ${CLASSPATH}/timestamp\n    ${CLASSPATH}/*.class\n    com/tigervnc/rfb/*.class\n    com/tigervnc/rdr/*.class\n    com/tigervnc/network/*.class\n    com/jcraft/jzlib/*.class\n    com/jcraft/jsch/jcraft/*.class\n    com/jcraft/jsch/jce/*.class\n    com/jcraft/jsch/*.class\n    com/tigervnc/vncviewer/*.png\n    com/tigervnc/vncviewer/tigervnc.ico\n  COMMAND ${CMAKE_COMMAND}\n  ARGS -DJava_PATH=${Java_PATH} -DJAR_FILE=${BINDIR}/VncViewer.jar\n    -DJAVA_KEYSTORE=${JAVA_KEYSTORE}\n    -DJAVA_KEYSTORE_TYPE=${JAVA_KEYSTORE_TYPE}\n    -DJAVA_STOREPASS=${JAVA_STOREPASS}\n    -DJAVA_PKCS11_PROVIDER_CLASS=${JAVA_PKCS11_PROVIDER_CLASS}\n    -DJAVA_PKCS11_PROVIDER_ARG=${JAVA_PKCS11_PROVIDER_ARG}\n    -DJAVA_KEYPASS=${JAVA_KEYPASS}\n    -DJAVA_KEY_ALIAS=${JAVA_KEY_ALIAS}\n    -DJAVA_TSA_URL=${JAVA_TSA_URL}\n    -DJAVA_CERT_CHAIN=${JAVA_CERT_CHAIN}\n    -P ${SRCDIR}/cmake/SignJar.cmake)\n\nadd_custom_target(java ALL DEPENDS VncViewer.jar)\n"
  },
  {
    "path": "java/cmake/SignJar.cmake",
    "content": "if(NOT Java_PATH)\n  message(FATAL_ERROR \"Java_PATH must be defined\")\nendif()\n\nif(NOT JAR_FILE)\n  message(FATAL_ERROR \"JAR_FILE must be defined\")\nendif()\n\nset(KEYTOOL \"${Java_PATH}/keytool\")\nset(JARSIGNER \"${Java_PATH}/jarsigner\")\n\nif(JAVA_KEYSTORE)\n  if((NOT JAVA_KEYSTORE_TYPE))\n    message(FATAL_ERROR \"When JAVA_KEYSTORE is specified, JAVA_KEYSTORE_TYPE must also be specified:\\n${ERROR}\")\n  endif()\n  string(TOUPPER \"${JAVA_KEYSTORE_TYPE}\" JAVA_KEYSTORE_TYPE_STRING)\n  if(${JAVA_KEYSTORE_TYPE_STRING} MATCHES \"PKCS11\")\n    if((NOT JAVA_PKCS11_PROVIDER_ARG) OR (NOT JAVA_STOREPASS) OR (NOT JAVA_KEY_ALIAS))\n      message(FATAL_ERROR \"When JAVA_KEYSTORE_TYPE is PKCS11, JAVA_STOREPASS, JAVA_PKCS11_PROVIDER_ARG, and JAVA_KEY_ALIAS must also be specified:\\n${ERROR}\")\n    endif()\n  elseif((${JAVA_KEYSTORE_TYPE_STRING} MATCHES \"JKS\") OR (${JAVA_KEYSTORE_TYPE_STRING} MATCHES \"PKCS12\"))\n    if((NOT JAVA_STOREPASS) OR (NOT JAVA_KEYPASS) OR (NOT JAVA_KEY_ALIAS))\n      message(FATAL_ERROR \"When JAVA_KEYSTORE_TYPE is JKS or PKCS12, JAVA_STOREPASS, JAVA_KEYPASS, and JAVA_KEY_ALIAS must also be specified:\\n${ERROR}\")\n    endif()\n  else()\n    message(FATAL_ERROR \"Unsupported keystore type:\\n${ERROR}\")\n  endif()\nelse()\n  message(STATUS \"Generating self-signed certificate\")\n  file(REMOVE tigervnc.keystore)\n  execute_process(COMMAND\n    ${KEYTOOL} -genkey -alias TigerVNC -keystore tigervnc.keystore -keyalg RSA\n      -storepass tigervnc -keypass tigervnc -validity 7300\n      -dname \"CN=TigerVNC, OU=Software development, O=The TigerVNC project, L=Austin, S=Texas, C=US\"\n    RESULT_VARIABLE RESULT OUTPUT_VARIABLE OUTPUT ERROR_VARIABLE ERROR)\n  if(NOT RESULT EQUAL 0)\n    message(FATAL_ERROR \"${KEYTOOL} failed:\\n${ERROR}\")\n  endif()\n  set(JAVA_KEYSTORE \"tigervnc.keystore\")\n  set(JAVA_STOREPASS \"tigervnc\")\n  set(JAVA_KEYPASS \"tigervnc\")\n  set(JAVA_KEY_ALIAS \"TigerVNC\")\nendif()\n\nmessage(STATUS \"Signing ${JAR_FILE}\")\n\nset(ARGS -keystore ${JAVA_KEYSTORE} -storetype ${JAVA_KEYSTORE_TYPE})\n\nif(${JAVA_STOREPASS} MATCHES \"^:env\")\n  string(REGEX REPLACE \"^:env[\\t ]+(.*)$\" \"\\\\1\" JAVA_STOREPASS \"${JAVA_STOREPASS}\")\n  set(ARGS ${ARGS} -storepass:env ${JAVA_STOREPASS})\nelseif(\"${JAVA_STOREPASS}\" MATCHES \"^:file\")\n  string(REGEX REPLACE \"^:file[\\t ]+(.*)$\" \"\\\\1\" JAVA_STOREPASS \"${JAVA_STOREPASS}\")\n  set(ARGS ${ARGS} -storepass:file ${JAVA_STOREPASS})\nelse()\n  set(ARGS ${ARGS} -storepass ${JAVA_STOREPASS})\nendif()\n\nif(${JAVA_KEYSTORE_TYPE_STRING} MATCHES \"PKCS11\")\n  set(ARGS ${ARGS} -providerClass ${JAVA_PKCS11_PROVIDER_CLASS})\n  set(ARGS ${ARGS} -providerArg ${JAVA_PKCS11_PROVIDER_ARG})\nelseif((${JAVA_KEYSTORE_TYPE_STRING} MATCHES \"JKS\") OR (${JAVA_KEYSTORE_TYPE_STRING} MATCHES \"PKCS12\"))\n  if(${JAVA_KEYPASS} MATCHES \"^:env\")\n    string(REGEX REPLACE \"^:env[\\t ]+(.*)$\" \"\\\\1\" JAVA_KEYPASS \"${JAVA_KEYPASS}\")\n    set(ARGS ${ARGS} -keypass:env ${JAVA_KEYPASS})\n  elseif(\"${JAVA_KEYPASS}\" MATCHES \"^:file\")\n    string(REGEX REPLACE \"^:file[\\t ]+(.*)$\" \"\\\\1\" JAVA_KEYPASS \"${JAVA_KEYPASS}\")\n    set(ARGS ${ARGS} -keypass:file ${JAVA_KEYPASS})\n  else()\n    set(ARGS ${ARGS} -keypass ${JAVA_KEYPASS})\n  endif()\nendif()\n\nif(JAVA_CERT_CHAIN)\n  set(ARGS ${ARGS} -certchain ${JAVA_CERT_CHAIN})\nendif()\n\nif(JAVA_TSA_URL)\n  set(ARGS ${ARGS} -tsa ${JAVA_TSA_URL})\nendif()\n\nexecute_process(COMMAND\n  ${JARSIGNER} ${ARGS} ${JAR_FILE} ${JAVA_KEY_ALIAS}\n  RESULT_VARIABLE RESULT OUTPUT_VARIABLE OUTPUT ERROR_VARIABLE ERROR)\n\nif(NOT RESULT EQUAL 0)\n  message(FATAL_ERROR \"${JARSIGNER} failed:\\n${ERROR}\")\nendif()\n\nif(EXISTS tigervnc.keystore)\n  file(REMOVE tigervnc.keystore)\nendif()\n"
  },
  {
    "path": "java/com/jcraft/jsch/Buffer.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class Buffer{\n  final byte[] tmp=new byte[4];\n  byte[] buffer;\n  int index;\n  int s;\n  public Buffer(int size){\n    buffer=new byte[size];\n    index=0;\n    s=0;\n  }\n  public Buffer(byte[] buffer){\n    this.buffer=buffer;\n    index=0;\n    s=0;\n  }\n  public Buffer(){ this(1024*10*2); }\n  public void putByte(byte foo){\n    buffer[index++]=foo;\n  }\n  public void putByte(byte[] foo) {\n    putByte(foo, 0, foo.length);\n  }\n  public void putByte(byte[] foo, int begin, int length) {\n    System.arraycopy(foo, begin, buffer, index, length);\n    index+=length;\n  }\n  public void putString(byte[] foo){\n    putString(foo, 0, foo.length);\n  }\n  public void putString(byte[] foo, int begin, int length) {\n    putInt(length);\n    putByte(foo, begin, length);\n  }\n  public void putInt(int val) {\n    tmp[0]=(byte)(val >>> 24);\n    tmp[1]=(byte)(val >>> 16);\n    tmp[2]=(byte)(val >>> 8);\n    tmp[3]=(byte)(val);\n    System.arraycopy(tmp, 0, buffer, index, 4);\n    index+=4;\n  }\n  public void putLong(long val) {\n    tmp[0]=(byte)(val >>> 56);\n    tmp[1]=(byte)(val >>> 48);\n    tmp[2]=(byte)(val >>> 40);\n    tmp[3]=(byte)(val >>> 32);\n    System.arraycopy(tmp, 0, buffer, index, 4);\n    tmp[0]=(byte)(val >>> 24);\n    tmp[1]=(byte)(val >>> 16);\n    tmp[2]=(byte)(val >>> 8);\n    tmp[3]=(byte)(val);\n    System.arraycopy(tmp, 0, buffer, index+4, 4);\n    index+=8;\n  }\n  void skip(int n) {\n    index+=n;\n  }\n  void putPad(int n) {\n    while(n>0){\n      buffer[index++]=(byte)0;\n      n--;\n    }\n  }\n  public void putMPInt(byte[] foo){\n    int i=foo.length;\n    if((foo[0]&0x80)!=0){\n      i++;\n      putInt(i);\n      putByte((byte)0);\n    }\n    else{\n      putInt(i);\n    }\n    putByte(foo);\n  }\n  public int getLength(){\n    return index-s;\n  }\n  public int getOffSet(){\n    return s;\n  }\n  public void setOffSet(int s){\n    this.s=s;\n  }\n  public long getLong(){\n    long foo = getInt()&0xffffffffL;\n    foo = ((foo<<32)) | (getInt()&0xffffffffL);\n    return foo;\n  }\n  public int getInt(){\n    int foo = getShort();\n    foo = ((foo<<16)&0xffff0000) | (getShort()&0xffff);\n    return foo;\n  }\n  public long getUInt(){\n    long foo = 0L;\n    long bar = 0L;\n    foo = getByte();\n    foo = ((foo<<8)&0xff00)|(getByte()&0xff);\n    bar = getByte();\n    bar = ((bar<<8)&0xff00)|(getByte()&0xff);\n    foo = ((foo<<16)&0xffff0000) | (bar&0xffff);\n    return foo;\n  }\n  int getShort() {\n    int foo = getByte();\n    foo = ((foo<<8)&0xff00)|(getByte()&0xff);\n    return foo;\n  }\n  public int getByte() {\n    return (buffer[s++]&0xff);\n  }\n  public void getByte(byte[] foo) {\n    getByte(foo, 0, foo.length);\n  }\n  void getByte(byte[] foo, int start, int len) {\n    System.arraycopy(buffer, s, foo, start, len); \n    s+=len;\n  }\n  public int getByte(int len) {\n    int foo=s;\n    s+=len;\n    return foo;\n  }\n  public byte[] getMPInt() {\n    int i=getInt();  // uint32\n    if(i<0 ||  // bigger than 0x7fffffff\n       i>8*1024){\n      // TODO: an exception should be thrown.\n      i = 8*1024; // the session will be broken, but working around OOME.\n    }\n    byte[] foo=new byte[i];\n    getByte(foo, 0, i);\n    return foo;\n  }\n  public byte[] getMPIntBits() {\n    int bits=getInt();\n    int bytes=(bits+7)/8;\n    byte[] foo=new byte[bytes];\n    getByte(foo, 0, bytes);\n    if((foo[0]&0x80)!=0){\n      byte[] bar=new byte[foo.length+1];\n      bar[0]=0; // ??\n      System.arraycopy(foo, 0, bar, 1, foo.length);\n      foo=bar;\n    }\n    return foo;\n  }\n  public byte[] getString() {\n    int i = getInt();  // uint32\n    if(i<0 ||  // bigger than 0x7fffffff\n       i>256*1024){\n      // TODO: an exception should be thrown.\n      i = 256*1024; // the session will be broken, but working around OOME.\n    }\n    byte[] foo=new byte[i];\n    getByte(foo, 0, i);\n    return foo;\n  }\n  byte[] getString(int[]start, int[]len) {\n    int i=getInt();\n    start[0]=getByte(i);\n    len[0]=i;\n    return buffer;\n  }\n  public void reset(){\n    index=0;\n    s=0;\n  }\n  public void shift(){\n    if(s==0)return;\n    System.arraycopy(buffer, s, buffer, 0, index-s);\n    index=index-s;\n    s=0;\n  }\n  void rewind(){\n    s=0;\n  }\n\n  byte getCommand(){\n    return buffer[5];\n  }\n\n  void checkFreeSize(int n){\n    int size = index+n+Session.buffer_margin;\n    if(buffer.length<size){\n      int i = buffer.length*2;\n      if(i<size) i = size;\n      byte[] tmp = new byte[i];\n      System.arraycopy(buffer, 0, tmp, 0, index);\n      buffer = tmp;\n    }\n  }\n\n  byte[][] getBytes(int n, String msg) throws JSchException {\n    byte[][] tmp = new byte[n][];\n    for(int i = 0; i < n; i++){\n      int j = getInt();\n      if(getLength() < j){\n        throw new JSchException(msg);\n      }\n      tmp[i] = new byte[j];\n      getByte(tmp[i]);\n    }\n    return tmp;\n  }\n\n  /*\n  static Buffer fromBytes(byte[]... args){\n    int length = args.length*4;\n    for(int i = 0; i < args.length; i++){\n      length += args[i].length;\n    }\n    Buffer buf = new Buffer(length);\n    for(int i = 0; i < args.length; i++){\n      buf.putString(args[i]);\n    }\n    return buf;\n  }\n  */\n\n  static Buffer fromBytes(byte[][] args){\n    int length = args.length*4;\n    for(int i = 0; i < args.length; i++){\n      length += args[i].length;\n    }\n    Buffer buf = new Buffer(length);\n    for(int i = 0; i < args.length; i++){\n      buf.putString(args[i]);\n    }\n    return buf;\n  }\n\n\n/*\n  static String[] chars={\n    \"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\", \"a\",\"b\",\"c\",\"d\",\"e\",\"f\"\n  };\n  static void dump_buffer(){\n    int foo;\n    for(int i=0; i<tmp_buffer_index; i++){\n        foo=tmp_buffer[i]&0xff;\n\tSystem.err.print(chars[(foo>>>4)&0xf]);\n\tSystem.err.print(chars[foo&0xf]);\n        if(i%16==15){\n          System.err.println(\"\");\n\t  continue;\n\t}\n        if(i>0 && i%2==1){\n          System.err.print(\" \");\n\t}\n    }\n    System.err.println(\"\");\n  }\n  static void dump(byte[] b){\n    dump(b, 0, b.length);\n  }\n  static void dump(byte[] b, int s, int l){\n    for(int i=s; i<s+l; i++){\n      System.err.print(Integer.toHexString(b[i]&0xff)+\":\");\n    }\n    System.err.println(\"\");\n  }\n*/\n\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ChangeLog",
    "content": "ChangeLog of JSch\n====================================================================\nLast modified: Fri Jun  5 03:22:57 UTC 2015\n\n\nChanges since version 0.1.52:\n- bugfix: the rekey initiated by the remote may crash the session.\n- change: Logjam: use ecdh-sha2-nistp* if available,\n          ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,\n          diffie-hellman-group14-sha1,\n          diffie-hellman-group-exchange-sha256,\n          diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1\n- change: Logjam: diffie-hellman-group-exchange-sha256 and\n          diffie-hellman-group-exchange-sha1 will use 2048-bit key on\n          Java8's SunJCE, thanks to JDK-6521495 and JDK-7044060.\n- change: key words for OpenSSH's config file should be case-insensitive.\n- change: there should be the host name in \"WARNING: REMOTE HOST\n          IDENTIFICATION HAS CHANGED\" message.\n\n\nChanges since version 0.1.51:\n- bugfix: resource leak: duplicate keys in LocalIdentityRepository.\n- feature: added the support for SSH ECC defined in RFC5656,\n           ecdsa-sha2-nistp256,\n           ecdsa-sha2-nistp384,\n           ecdsa-sha2-nistp521,\n           ecdh-sha2-nistp256,\n           ecdh-sha2-nistp384,\n           ecdh-sha2-nistp521\n           This functionality requires Java7 or later.\n- feature: added the support for server host keys in\n           ecdsa-sha2-nistp256,\n           ecdsa-sha2-nistp384,\n           ecdsa-sha2-nistp521\n- feature: generating key-pairs in\n           ecdh-sha2-nistp256,\n           ecdh-sha2-nistp384,\n           ecdh-sha2-nistp521\n- change: aes192-ctr, aes256-ctr and\n          diffie-hellman-group-exchange-sha256 have been enabled\n          by the default.\n- change: key exchange methods, ecdh-sha2-nistp256,\n          ecdh-sha2-nistp384 and ecdh-sha2-nistp521 have been enabled\n          by the default.\n- change: the support for host keys in ecdsa-sha2-nistp256,\n          ecdsa-sha2-nistp384 and ecdsa-sha2-nistp521 have been enabled\n          by the default.\n- change: 'examples/KeyGen.java' demonstrates how to generate\n          ecdsa-sha2-* key-pairs.\n- change: updating copyright messages; 2014 -> 2015\n- TODO: The ECC support is not functional on Java6 with BouncyCastle.\n\n\nChanges since version 0.1.50:\n- bugfix: reproducibility of \"verify: false\".   FIXED.\n          Hundreds of thousands of connections had caused that exception.\n- bugfix: resource leaks at the failure of making local port forwarding. FIXED.\n- bugfix: NPE in connecting to the non-standard TCP port.  FIXED.\n          This problem had appeared if a host-key does not exist in\n\t  \"known_host\" file.\n- bugfix: TCP connection may not be dropped if error messages from\n\t  the remote are too long.                          FIXED.\n- bugfix: SftpATTRS#getAtimeString() returns the wrong string. FIXED.\n- bugfix: bytes to be added by SSH_MSG_CHANNEL_WINDOW_ADJUST must be in\n\t  unsigned integer. FIXED.\n- bugfix: Util#checkTilde() should not convert a tilde in\n          \"C:\\PROGRA~1\\\". FIXED.\n- bugfix: A long long command for ChannelExec will cause\n          an ArrayIndexOutOfBoundsException. FIXED.\n- bugfix: ChannelSftp should not send bulk request greedily even if the remote\n          window has the enough space.  FIXED.\n- bugfix: Util.createSocket() should throw an exception with 'cause'. FIXED.\n- bugfix: failed to parse .ssh/config in the EBCDIC environment. FIXED.\n- bugfix: com.jcraft.jsch.jcraft.HMACSHA1(used only for MacOSX) is not\n          reusable.  FIXED.\n- bugfix: NPE caused by the delayed response for channel opening\n          requests. FIXED.\n- bugfix: hung-up in uploading huge data to ProFTPd without the config\n          'SFTPClientMatch \"JSCH.*\" channelWindowSize 1GB'  FIXED.\n- bugfix: Cipher#init() may cause an infinite loop with 100% cpu use due to\n          https://bugs.openjdk.java.net/browse/JDK-8028627  FIXED.\n- bugfix: in some case, JSche#setKnowHosts(InputStream stream) may fail\n          to close the given stream.  FIXED\n- change: com.jcraft.jsch.jcraft.HMAC* will not be used.\n          It seems Java6 on Mac OS X has fixed some memory leak bug in JCE,\n\t  so there is no reason to use c.j.j.j.HMAC* introduced at 0.1.30.\n- change: updating copyright messages; 2013 -> 2014\n- change: allowed to create the symbolic/hard link to the relative path by\n          ChannelSftp#symlink(String oldpath, String newpath)\n          ChannelSftp#hardlink(String oldpath, String newpath)\n- change: the availability of ciphers listed in \"CheckCiphers\" config will\n          not be checked if they are not used.\n- change: Util#fromBase64() will throw JSchException in stead of\n          RuntimeException, if the given string is not in base64 format.\n- feature: added the support for private keys in PKCS#8 format.\n- feature: introduced the interface com.jcraft.jsch.PBKDF to abstract\n           the implementation of Password-Based Key Derivation Function,\n           and added its implementation com.jcraft.jsch.jce.PBKDF by using JCE.\n\n\nChanges since version 0.1.49:\n- bugfix: \"verify: false\" error on Java7u6(and later).  FIXED.\n          http://stackoverflow.com/questions/12279836/ssh-using-jschexception-verify-false-sometimes-fails\n          https://issues.apache.org/jira/browse/IVY-1374\n- bugfix: Session#setPortForwardingL(String bind_address,\n\t                             int lport, String host, int rport)\n\t  will not work for the long host name.         FIXED.\n- change: changed JSch#getIdentityRepository() to be public.\n- feature: added the following method to choose a canceled remote\n\t   port-forwarding with the specified bind address,\n             Session#delPortForwardingR(String bind_address, int rport)\n- feature: added support for following OpenSSH's sftp extensions,\n             posix-rename@openssh.com,\n             statvfs@openssh.com,\n             hardlink@openssh.com,\n\t   and some methods and a class to use those functionalities,\n             ChannelSftp#hardlink(String oldpath, String newpath),\n\t     ChannelSftp#statVFS(String path)\n             SftpStatVFS\n- feature: added support for OpenSSH's configuration file,\n\t     JSch#setConfigRepository(ConfigRepository configRepository)\n\t     JSch#getConfigRepository()\n             OpenSSHConfig class\n             Session#getSession(String host)\n\t   and added an example to demonstrate how to use it,\n\t     examples/OpenSSHConfig.java\n\t   OpenSSHConfig class will recognize the following keywords,\n             Host\n             User\n             Hostname\n             Port\n             PreferredAuthentications\n             IdentityFile\n             NumberOfPasswordPrompts\n             ConnectTimeout\n             HostKeyAlias\n             UserKnownHostsFile\n             KexAlgorithms\n             HostKeyAlgorithms\n             Ciphers\n             Macs\n             Compression\n             CompressionLevel\n             ForwardAgent\n             RequestTTY\n             ServerAliveInterval\n             LocalForward\n             RemoteForward\n             ClearAllForwardings\n- feature: added support for \"diffie-hellman-group-exchange-sha256\"\n- feature: allowed to use tilde(~) in the file name,\n             JSch#setIdentity(String prvkey, String pubkey)\n             JSch#setKnownHosts(String prvkey, String pubkey)\n- feature: added support for known_hosts file, which may include\n\t   markers(@revoke) and comments.\n             HostKey(String host, int type, byte[] key, String comment)\n             HostKey(String marker, String host, int type,\n                     byte[] key, String comment)\n             HostKey#getComment()\n             HostKey#getMarker()\n- feature: added following methods to KeyPar class,\n             writePrivateKey(java.io.OutputStream out, byte[] passphrase)\n             writePrivateKey(String name, byte[] passphrase)\n- feature: allowed to set the connection timeout for the local port-forwarding,\n\t   and added following methods,\n             Session#setPortForwardingL(String bind_address,\n                                        int lport, String host, int rport,\n                                        ServerSocketFactory ssf,\n                                        int connectTimeout)\n             ChannelDirectTCPIP#connect(int connectTimeout)\n- feature: added the following method to Session class\n\t     getStreamForwarder(String host, int port)\n           and updated example/StreamForwarding.java to use that method.\n- feature: added following methods to Session class,\n             setPortForwardingL(String conf)\n             setPortForwardingR(String conf)\n- feature: allowed to have the session local HostkeyRepository,\n             Session#setHostKeyRepository(HostKeyRepository hostkeyRepository)\n             Session#getHostKeyRepository()\n- feature: added support for OpenSSH's local extension,\n\t   \"no-more-sessions@openssh.com\" and the method,\n             Session#noMoreSessionChannels()\n\n\nChanges since version 0.1.48:\n- bugfix: Some sftp servers will sometimes fail to handle bulk requests,\n\t  and whenever detecting such failures, we should re-send\n          requests again and again.                                    FIXED\n- bugfix: KeyPair#getFingerPrint() should return a fingerprint instead\n\t  of keysize + \" \" + fingerprint.                              FIXED\n- bugfix: KeyPair#getKeySize() should return its key size.             FIXED\n- bugfix: SftpATTRS#isDir() should return false for unix domain\n\t  socket files.                                                FIXED\n- change: improved the heuristics for the password prompt in\n\t  the keyboard-interactive authentication.  It may not be\n\t  started with \"password:\".\n- change: ChannelSftp#put(InputStream src, String dst) will not check\n\t  if dst is directory or not, and if an exception is thrown,\n\t  the check will be done.\n- change: if the compression is enabled without jzlib.jar,\n\t  an exception will be thrown.\n- feature: JSch#addIdentity() and KeyPair#load() methods will accept\n\t   Putty's private key files.\n\t   Note that Putty encrypts its private key with \"aes256-cbc\".\n\t   So, to handle such key files, \"Java Cryptography\n\t   Extension (JCE) Unlimited Strength Jurisdiction Policy Files\"\n\t   must be installed.\n- feature: hmac-sha2-256 defined in RFC6668 is supported.\n- feature: added following methods to KeyPair class,\n\t   byte[] getSignature(byte[] data)\n\t   Signature getVerifier()\n\t   byte[] forSSHAgent()\n\t   void setPublicKeyComment(String comment)\n- feature: added following methods to SftpATTR class,\n           boolean isChr()\n           boolean isBlk()\n           boolean isFifo()\n           boolean isSock()\n\n\nChanges since version 0.1.47:\n- change: the file transfer speed with ChannelSftp#get(String src) has been\n          improved; sending multiple requests at any one time.\n- change: by the default, at most, 16 requests will be sent at any one time\n          in ChannelSftp.\n- feature: added Session#{setIdentityRepository(),getIdentityRepository()}\n\n\nChanges since version 0.1.46:\n- bugfix: failed to initialize channels for the stream forwarding.     FIXED\n- change: Session#getHostKey() will return the given hostkey\n\t  even if session is not established.\n- change: Logger will record additional messages about algorithm negotiations.\n- feature: added ChannelSftp#ls(String path, LsEntrySelector selector) method.\n- feature: added IdentityRepository#{getName(),getStatus()} methods.\n\n\nChanges since version 0.1.45:\n- bugfix: in the agent forwarding mode, \"ssh-add -l\" on the remote\n          will freeze.                                                 FIXED\n- bugfix: requests should not be sent to the closed channel.           FIXED\n- bugfix: ChannelShell#setAgentForwarding(true) will cause\n          resource leaks.                                              FIXED\n- change: for the efficiency, channel opening will be delayed\n          in local port forwarding.\n- change: added examples/Sudo.java to demonstrate sudo on exec channel.\n- change: authentication trials will be failed at 6 failures by the default.\n- change: updating copyright messages; 2011 -> 2012\n- feature: added JSch#setIdentityRepository(IdentityRepository irepo) to\n\t   integrate with jsch-agent-proxy.\n\n\nChanges since version 0.1.44:\n- bugfix: fields referred by multiple threads simultaneously should be\n\t  volatile.                                                    FIXED\n- bugfix: use local window size offered by the remote in sftp put.\n                                                                       FIXED\n- bugfix: SftpProgressMonitor#init was not invoked in sftp-put\n\t  for input-stream.                                            FIXED\n- bugfix: sftp protocol version 3, 4 and 5 should allow only\n\t  UTF-8 encoding.                                              FIXED\n- bugfix: Channel Subsystem had failed to set X forwarding flag.\n                                                                       FIXED\n- bugfix: Channel X11 had leaked some resources.\n                                                                       FIXED\n- bugfix: packet compression may break sessions\n\t  in some case(transferring deflated data).                    FIXED\n- bugfix: failed to set dev-null for logger\n                                                                       FIXED\n- bugfix: even in sftp protocol version 3 session, some sftpd sends data\n\t  packets defined in sftp protocol 6 ;-( working around it.    FIXED\n- bugfix: ChannelSftp file globbing logic had missed\n\t  the string \"foo\\\\\\*bar\" as a pattern.                        FIXED\n- bugfix: sequential accesses to ChannelSftp by multiple threads may\n\t  break its I/O channel.\n\t  https://bugs.eclipse.org/bugs/show_bug.cgi?id=359184         FIXED\n- bugfix: KeyPair.load can not handle private keys cyphered with AES.  FIXED\n- change: to improve sftp-put performance, send multiple packet at one time.\n- change: wait/notify will be used instead of sleep loop\n          in establishing channel connections.\n- change: increasing local window size for sftp get.\n- change: updating copyright messages; 2010 -> 2011\n- change: src/com -> src/main/java/com\n- feature: key-exchange method \"diffie-hellman-group14-sha1\"\n\t  (RFC4253#section-8.2)\n- feature: KeyPair#getPlulicKeyCommment() is added.\n\n\nChanges since version 0.1.43:\n- bugfix: hmac-md5-96 and hmac-sha1-96 are broken. FIXED.\n- bugfix: working around OOME in parsing broken data from the remote. FIXED.\n- bugfix: failed to send very long command for exec channels. FIXED.\n- bugfix: in some case, failed to get the response\n\t  for remote port-forwarding request.  FIXED.\n- feature: support for private keys ciphered with aes192-cbc and aes128-cbc.\n\n\nChanges since version 0.1.42:\n- bugfix: the remote window size must be in unsigned int.  FIXED.\n- bugfix: support for EBCDIC environment.  FIXED.\n- bugfix: data may be written to the closed channel.  FIXED.\n- bugfix: NPE in closing channels.  FIXED.\n- bugfix: the private key file may include garbage data before its header.  FIXED.\n- bugfix: the session down may not be detected during the re-keying process.  FIXED.\n- change: try keyboard-interactive auth with the given password if UserInfo is not given.\n- change: working around the wrong auth method list sent by some SSHD\n          in the partial auth success.\n- change: working around the CPNI-957037 Plain-text Recovery Attack.\n- change: in searching for [host]:non-default port in known_hosts,\n          host:22 should be also checked.\n- change: updating copyright messages; 2009 -> 2010\n\n\nChanges since version 0.1.41:\n- bugfix: making exec request during re-keying process will cause\n\t  the dead lock for the session.                        FIXED.\n          Many thanks for PanLi at Prominic dot NET and www.prominic.net,\n\t  US based hosting company.  Without their testing JSch with\n  \t  hundreds of hosts and their bug reports, this problem\n\t  was not fixed.\n- change: updating copyright messages; 2008 -> 2009\n\n\nChanges since version 0.1.40:\n- bugfix: canceling the remote port-forwarding with the incorrect\n\t  bind-address.                                         FIXED.\n- bugfix: sftp had missed to close the file in some case.       FIXED.\n- bugfix: ls(sftp) will throw an exception for the empty directory\n\t  in connecting to some sftpd server.                   FIXED.\n- change: dropping the session gently in accepting incorrect packets.\n- change: by the default, aes128-ctr will be chosen if it is available\n\t  on the local and the remote.\n- feature: adding the support for the private key ciphered in AES256.\n- feature: new ciphers: aes128-ctr,aes192-ctr,aes256-ctr,\n\t   3des-ctr,arcfour,arcfour128 ,arcfour256\n\n\nChanges since version 0.1.39:\n- bugfix: ProxySOCKS4 had not been functional.                  FIXED.\n- bugfix: NPE at closing the session when it is not opened.     FIXED.\n- change: JSch#getConfing has become public.\n\n\nChanges since version 0.1.38:\n- bugfix: session will be dropped at rekeying.                  FIXED.\n- bugfix: NPE should not be thrown at unexpected session drop.  FIXED.\n- change: Channel#getSession() may throw JSchExecption.\n\n\nChanges since version 0.1.37:\n- bugfix: NPE should not be thrown at unexpected session drop.  FIXED.\n- bugfix: AIOOBE at Session#connect().                         FIXED.\n- bugfix: Even if 'true' is given for\n\t    Channel#setOutputStream(OutputStream out, boolean dontclose)\n\t  as the second paramter, 'out' will be closed.        FIXED.\n- change: 'examples/Sftp.java' has been modified to demonstrate\n          ChannelSftp#reaplpath(String path)\n- change: setEnv(Hashtable env) for exec and shell channels have been\n\t  marked as @deprecated\n- feature: setEnv(String name, String value) has been added to exec\n\t   and shell channels.\n- feature: setEnv(byte[] name, byte[] value) has been added to exec\n\t   and shell channels.\n- feature: ChannelSftp#realpath(String path) has been added.\n- feature: ChannelExec#setCommand(byte[] command) has been added.\n- feature: com.jcraft.jsch.ChannelSftp.LsEntry has implemented\n\t   java.lang.Comparable\n- feature: Session#getServerAliveInterval(), Session#getServerAliveCountMaX()\n\t   have been added.\n\n\nChanges since version 0.1.36:\n- bugfix: some sftpd will send invalid data in sftp protocol\n          point of view, and we need to work around such data. FIXED.\n- bugfix: the stream forwarding had been broken since 0.1.30.  FIXED.\n- bugfix: failed to detect 'SSH_MSG_CHANNEL_OPEN_FAILURE'.     FIXED.\n- bugfix: ChannelSftp will generate the unfavorable absolute pathname\n\t  in some case.                                        FIXED.\n- bugfix: failed to ignore the invalid public-key file.        FIXED.\n- change: ignoring empty data sent by 'SSH_MSG_CHANNEL_DATA' and\n           'SSH_MSG_CHANNEL_EXTENDED_DATA'.\n- change: updating copyright messages; 2007 -> 2008\n- change: build.xml will enable 'javac.debug' option by the default.\n- change: added logging messages to IndentityFile and Session class.\n- change: followings are deprecated methods,\n\t   InputStream ChannelSftp#get(String src,\n\t                               int mode)\n\t   InputStream ChannelSftp#get(String src,\n\t                               SftpProgressMonitor,\n\t                               int mode)\n- feature: following method is added,\n\t   InputStream ChannelSftp#get(String src,\n\t                               SftpProgressMonitor monitor,\n\t                               long skip)\n\n\nChanges since version 0.1.35:\n- bugfix: ChannelSftp can not handle the local filenames correctly on Windows. FIXED.\n- bugfix: '/' must be handled as the file separator on JVM for Windows.  FIXED.\n- change: the system property\n\t    \"javax.security.auth.useSubjectCredsOnly\"\n\t  will be set to \"false\" for \"gssapi-with-mic\"\n\t  if that property is not given explicitly.\n- change: added changes about ChannelSftp#{pwd(), home()} to\n\t  ChangeLog; 'Changes since version 0.1.34:' section.\n\n\nChanges since version 0.1.34:\n- bugfix: the OutputStream from the channel may make the JVM\n\t  lockup in some case.                                 FIXED.\n\t  There was a possibility that Channel#connect() may be failed\n\t  to initialize its internal without throwing the JSchException.\n\t  On such case, the write operation for OutputStream from\n\t  that channel will cause the system(JVM) to lock up.\n- bugfix: ChannelSftp had problems filename globbing.              FIXED.\n- bugfix: the message included in SSH_FXP_STATUS must be UTF-8.    FIXED.\n- change: ChannelSftp supports the filename globbing for\n\t  the filename in multi-byte characters.\n- change: ChannelSftp will internally handle filenames in UTF-8 encoding.\n- change: ChannelSftp#pwd() may throw an SftpException.\n- change: ChannelSftp#home() may throw an SftpException.\n- feature: following methods have been added in ChannelSftp\n\t   String getServerVersion()\n\t   String getClientVersion()\n\t   void setFilenameEncoding(String encoding)\n\t   String getExtension(String key)\n\nChanges since version 0.1.33:\n- bugfix: there had a possibility that the session may be broken\n\t  if ciphers for upward/downward streams are different.    FIXED.\n- bugfix: the authentication method \"keyboard-interactive\" had\n\t  not been tried without UserInfo.                         FIXED.\n- bugfix: ChannelShell#setTerminalMode(byte[] terminal_mode) had\n\t  not been functional.                                     FIXED.\n- bugfix: the remote port-forwarding to the daemon had been broken\n\t  since 0.1.30.                                            FIXED.\n- change: the cipher \"aes128-cbc\" will be used if AES is available.\n- change: the interface 'com.jcraft.jsch.ForwardedTCPIPDaemon' has been changed.\n- change: the data transfer rate will be improved on some environment.\n- feature: ChannelExec can control the size of pty;\n\t   ChannelExec#setPtySize(int col, int row, int wp, int hp) is\n           added.\n- feature: the property \"CheckCiphers\" has been added.\n\t   Refer to 'examples/AES.java'.\n- feature: Session#setConfig(String key, String value),\n\t   JSch#setConfig(String key, String value) have been added.\n\n\nChanges since version 0.1.32:\n- bugfix: freeze in 'diffie-hellman-group-exchange-sha1'.          FIXED.\n          By the default, 'diffie-hellman-group1-sha1' will be used\n\t  and if you have not chosen 'diffie-hellman-group-exchange-sha1'\n\t  explicitly, you don't have to worry about it.\n- bugfix: there should be timeout mechanism in opening a socket\n\t  for remote port forwarding.                              FIXED.\n\t  At the failure or timeout, 'SSH_MSG_CHANNEL_OPEN_FAILURE'\n\t  will be sent to sshd.\n- bugfix: there should be timeout mechanism in opening a socket\n\t  for X11 forwarding.                                      FIXED.\n\t  At the failure or timeout, 'SSH_MSG_CHANNEL_OPEN_FAILURE'\n          will be sent to sshd.\n\n\nChanges since version 0.1.31:\n- bugfix: remote port forwarding will be hanged at its closing.    FIXED.\n- bugfix: X forwarding channels will be hanged and some resources\n\t  will be leaked whenever they are closed.                 FIXED.\n- bugfix: failed to detect \"Connection refused\".                   FIXED.\n- bugfix: at the failure for keyboard-interactive auth method,\n\ta session will be terminated.                              FIXED.\n- bugfix: due to the cancel for keyboard-interactive auth method,\n\ta session will be terminated.                              FIXED.\n- change: com.jcraft.jsch.jcraft.Compression#uncompress will respect\n\tthe argument \"start\".\n- change: \"gssapi-with-mic\" will choose the default credential.\n- feature: Session#setPortForwardingL will return the assigned local\n\tTCP port number; TCP port will be assigned dynamically if lport==0.\n- feature: support for SSH_MSG_UNIMPLEMENTED.\n- feature: support for PASSWD_CHANGEREQ.\n\n\nChanges since version 0.1.30:\n- bugfix: a problem in padding for ciphered private key.\n\tPKCS#5 padding should be used.                             FIXED.\n- bugfix: crash in parsing invalid public key file.                FIXED.\n- bugfix: a public key may not have a comment.                     FIXED.\n- bugfix: output stream from ChannelSftp#put will hang if it is closed\n\t  twice.                                                   FIXED.\n- feature: agent forwarding. To enable this functionality,\n\tChannel{Exec,Shell,Sftp}#setAgentForwarding(boolean enable) are added.\n- feature: ChannelShell#setTerminalMode(byte[] terminal_mode) is added.\n- feature: Session#setDaemonThread(boolean true) to run internal threads as\n\t   daemon threads.\n- feature: an option \"PreferredAuthentications\" is added.\n\t   The default value is \"gssapi-with-mic,publickey,keyboard-interactive,password\".\n- change: if alias-name is given, non-standard TCP port number will not be\n\t  saved in 'known_hosts' file.\n\n\nChanges since version 0.1.29:\n- bugfix: ChannelSftp#cd() will not throw an exception even if\n\t  a file is given.                                           FIXED.\n- bugfix: ChannelSftp#put() has a bug which will appear in using\n\t  on the slow network.                                       FIXED.\n- bugfix: ChannelSftp#ls() has a bug which will appear in using\n\t  on the slow network.                                       FIXED.\n- bugfix: a bug had sneaked in the remote port forwarding.           FIXED.\n- bugfix: some APIs from JCE have the memory leak on Mac OS X,\n\t  so we have re-written the code(com.jcraft.jsch.jcraft.HMAC*\n\t  classes) without them.  On Mac OS X, such new classes will\n\t  be used automatically.                                     FIXED.\n- bugfix: the session will be crashed by the long banner message.    FIXED.\n- change: '/dev/random' will not be referred on Gnu/Linux.\n- change: if non-standard TCP port number is used, that number will\n\t  be saved in known_hosts file as recent OpenSSH's ssh client does.\n- change: Channel#getOutputStream will not use Piped{Output,Input}Stream.\n- change: com.jcraft.jsch.HostKeyRepository interface has been\n\t  slightly modified.\n- feature: Session#setPortForwardingR(String bind_address, ...) has been added.\n- feature: the packet compression method 'zlib@openssh.com' has been supported.\n- feature: the hashed known_hosts file has been supported.\n\t   Refer to 'examples/KnownHosts.java'.\n- feature: the authentication method 'gssapi-with-mic' has been\n \t   experimentally supported.\n- feature: com.jcraft.jsch.Logger interface and\n\t   JSch#setLogger(Logger logger) have been added.\n\t   Refer to 'examples/Logger.java' for the usage.\n\n\nChanges since version 0.1.28:\n- bugfix: ChannelSftp#put will stack in some situations              FIXED.\n- bugfix: ChannelSftp invoked 'glob_remote' redundantly.             FIXED.\n- bugfix: ChannelSftp failed to make globbing for some file names.    FIXED.\n- bugfix: ChannelSftp did not carefully read its input-stream.       FIXED.\n- bugfix: ChannelSftp#lstat did not try globbing for given path.      FIXED.\n- bugfix: at closing channel, eof_lcoal and eof_remote did not\n          become true.                                               FIXED.\n- bugfix: IdentityFile did not carefully read file input-streams.    FIXED.\n- bugfix: KeyPair did not carefully read file input-streams.         FIXED.\n- bugfix: ProxySOCKS4 did not carefully read file input-streams.     FIXED.\n- bugfix: ProxySOCKS5 did not carefully read file input-streams.     FIXED.\n- bugfix: ForwardedTCPIPDaemom may fail in some situation.           FIXED.\n- bugfix: X forwarding failed to handle the magic-cookie\n\t  in some case                                               FIXED.\n          Thanks to Walter Pfannenmller.\n- bugfix: setKnownHosts in KnownHosts.java doesn't read the last\n\t  line if linefeed is missing                                FIXED.\n          Thanks to Henrik Langos.\n- bugfix: With StrictHostKeyChecking set to yes connect()\n          shouldn't ask.                                             FIXED.\n          Thanks to Henrik Langos.\n- change: Identity#setPassphrase(String passphrase) is replaced with\n          Identity#setPassphrase(byte[] passphrase).\n- change: IdentityFile will clear its internal secrets at finalizing.\n- change: KeyPair will clear its internal secrets at finalizing.\n- change: KeyPair will clear its internal secrets at finalizing.\n- change: MAC#doFinal() is replaced with\n          MAC#doFile(byte[] buf, int offset)\n- change: at TCP socket reading timeout, keep-alive message will be sent\n          to the remote sshd.  To disable this functionality, invoke\n          explicitly Session.setServerAliveCountMax(0)\n- change: PortWatcher stops to use InetAddress.getByAddress().\n- change: in the user authentication, username, password and passphrase\n\t  will be encoded in UTF-8.\n- change: JSch#addIdentity will check duplicate keys.\n- change: SftpException#message has been deleted.\n- change: SftpException#getMessage() will return the detailed message.\n- feature: IdentityFile#setPassphrase(byte[] passphrase) is added.\n- feature: IdentityFile#clear() is added to clear its internal secrets.\n- feature: KeyPair#decrypt(byte[] passphrase) is added.\n- feature: JSch#addIdentity(String path, byte[] passphrase) is added.\n- feature: JSch#getIdentityNames() is added.\n- feature: JSch#removeIdentity(String name) is added.\n- feature: JSch#removeAllIdentity() is added.\n- feature: ChannelSftp#readlink(String path) is added.\n- feature: ChannelSftp#getHome() is added.\n- feature: Channel#connect(int connectTimeout) is added.\n- feature: ChannelShell#setPtyType(String ttype) is added.\n- feature: Session#setPassword(byte[] password) is added.\n- feature: Session#setHostKeyAlias(String alias) is added.\n- feature: KeepAlive is implemented and\n\t   Session#setServerAliveInterval(int interval) and\n\t   Session#setServerAliveCountMax(int count) are added.\n- feature: Session#sendKeepAliveMsg() is added.\n- feature: JSchException#getCause() may return a reason.\n- feature: SftpException#getCause() may return a reason.\n- feature: ChannelExec#setErrStream(OutputStream out, boolean dontclose)\n           is added.\n\n\nChanges since version 0.1.27:\n- bugfix: ChannelSftp#localAbsolutePath did not work correctly.      FIXED.\n- bugfix: ChannelSftp#chmod did not work for directory.              FIXED.\n- bugfix: ProxyHTTP had a bug in processing HTTP headers.            FIXED.\n- bugfix: messages before server's version string should be ignored. FIXED.\n- feature: Environment Variable Passing.\n\n\nChanges since version 0.1.26:\n- bugfix: there was a session crash bug. That occurrence is rare, but\n          depends on the thread scheduling.  FIXED.\n- bugfix: problems in generating remote/local absolute paths on sftp.  FIXED.\n- bugfix: problems in handling cancel operations for sftp.  FIXED.\n- bugfix: ChannelX11s were not terminated for a wrong cookie.  FIXED.\n- bugfix: NoSuchAlgorithmException should be thrown if JCE is not\n\t  accessible.  FIXED.\n- bugfix: ProxyHTTP should check the return code from proxy.  FIXED.\n- bugfix: server's version string should be checked carefully.  FIXED.\n- feature: some more improvements on sftp uploading.\n- feature: 'getUserName' method is added to Session class.\n\n\nChanges since version 0.1.25:\n- bugfix: infinite loop/hang on connection at unexpected error during\n          key-exchanging operation.  FIXED\n- bugfix: delays on sftp uploading.  FIXED\n- bugfix: failed to purge a host-key from its repository in some case. FIXED.\n- feature: SOCKS4 proxy\n\n\nChanges since version 0.1.24:\n- bugfix: remote port forwarding is not established. FIXED.\n- bugfix: failed to parse known_hosts file if it has a long public key blob.\n \t  FIXED.\n- bugfix: sftp put/get operations keep failing.  FIXED.\n- bugfix: ChannelShell.setXForwarding always set xforwarding to be true. FIXED.\n- change: ChannelShell.setPty is added.\n- change: Proxy interface is free from session object.\n- change: added examples/ScpToNoneCipher.java to demonstrate NONE Cipher switching.\n- feature: added NONE Cipher switching support.\n- feature: timeout check will be enabled for proxy connections.\n\n\nChanges since version 0.1.23:\n- bugfix: there was resource leak problems in closing local port forwardings.\n  \t  FIXED.\n- bugfix: there was a session crash problems in using aes-cbc cipher.  FIXED.\n- change: ChannelSession.setPtySize was redefined.\n- feature: added SocketFactory for remote port forwarding.\n\t   Session.setPortForwardingR(int rport, String host, int lport,\n\t                              SocketFactory sf)\n- feature: added ServerSocketFactory for local port forwarding.\n\t   Session.setPortForwardingL(String boundaddress,\n\t                              int lport, String host, int rport,\n\t                              ServerSocketFactory ssf)\n\nChanges since version 0.1.22:\n- bugfix: there was a freeze problem at fails on key-exchanging. FIXED.\n- bugfix: race-condition forcefully disconnects session in closing channels.\n\t  FIXED.\n\n\nChanges since version 0.1.21:\n- bugfix: there is a bug in read() method implementation for the\n          input-stream returned from ChannelSftp.get().  FIXED.\n- bugfix: at fail on requesting for the remote port forwarding,\n\t  an exception should be thrown. FIXED.\n- bugfix: SSH_MSG_CHANNEL_OPEN request for the X11 forwarding should not\n\t  be accepted if clients don not expect it. FIXED.\n- bugfix: there is a problem in transferring large data(mote than 1GB)\n\t  to sshd from recent OpenSSH(3.6.1 or later). FIXED.\n\t  For security concerns, those sshd will re-key periodically and\n\t  jsch had failed to handle it.\n- bugfix: 'exec', 'shell' and 'sftp' channels will fail if the acceptable\n\t  packet size by remote sshd is not so large. FIXED.\n- bugfix: there are problems in 'InputStream ChannelSftp.get(String)'\n   \t  and 'OutputStream put(String)'.  FIXED.\n- feature: added boolean flag 'dontclose' to\n\t   * setInputStream(),\n\t   * setOutputStream() and\n\t   * setExtOutputStream()\n           methods of Channel class.\n- feature: added 'com.jcraft.jsch.ChannelSubsystem'\n- feature: allowed to control the compression level in the packet compression.\n \t   Refer to 'examples/Compression.java'.\n- change: modified 'com/jcraft/jsch/jce/KeyPairGenRSA.java' to be complied\n\t  on JDK 1.2.\n- change: 'examples/ScpTo.java' and 'examples/ScpFrom.java' will use\n\t  'long' type for the file size instead of 'int'.\n- change: 'Identity.getSignature' method will not expect 'session'.\n- change: while waiting for socket connection establishment, Thread.join\n\t  will be used instead of Thread.sleep.\n\n\nChanges since version 0.1.20:\n- known issue: there are problems in 'InputStream ChannelSftp.get(String)'\n   \t       and 'OutputStream put(String)'.  They will be re-implemented\n  \t       in the next release.\n- bugfix: EOF packets should not be sent twice. This bug had crashed\n\t  the session on every channel close. FIXED.\n- bugfix: at the fail on opening connection to remote sshd,\n          a misleading exception \"invalid server's version string\"\n          had been thrown. FIXED.\n- bugfix: fixed a bug in hadling the size of remote channel window.\n- bugfix: channels should not be closed even if EOF is received. FIXED.\n- bugfix: fixed bugs in file name globbing on sftp.\n- change: to transfer packets efficiently, the size of internal buffer\n          for each channel has been increased.\n- change: ChannelSftp.ls will return a vector of\n\t  com.jcraft.jsch.ChannelSftp.LsEntry.  Sorry for inconveniences.\n- feature: added ForwardedTCPIPDaemon.  Refer to 'examples/Daemon.java',\n           which demonstrates to provide network services like inetd.\n- feature: ChannelExec.setPty() method to request for assigning pseudo tty.\n- feature: added ciphers \"aes128-cbc\", \"aes192-cbc\" and \"aes256-cbc\".\n\t   Refer to 'examples/AES.java'.\n- feature: local port-forwarding settings can be dynamically deleted\n           by the bound address.\n- feature: added 'Channel.isClosed()'. Channel.getExitStatus() should be\n\t   invoked after Channel.isClosed()==true.\n\n\nChanges since version 0.1.19:\n- ClassCastException while calling ChannelExec.finalize() method. FIXED.\n  Thanks to wswiatek at ais dot pl.\n\n\nChanges since version 0.1.18:\n- fixed problems related to thread-safety.\n  Thanks to Eric Meek at cs dot utk dot edu.\n- At the lost of the network connectivity to the remote SSHD,  clients\n  connected to the local port were never made aware of the\n  disconnection.  FIXED.\n- fixed confusions in handling EOFs from local input stream and\n  the input stream for remote process.\n- 'com.jcraft.jsch.jce.AES128CBC' is added, but it is not be functional in\n  this release.  It will work in the next release.\n- Some sshd(Foxit-WAC-Serve) waits for SSH_MSG_NEWKEYS request before\n  sending it. FIXED.\n- fixed a problem in connecting to Cisco Devices.\n  Thanks to Jason Jeffords at comcast dot net.\n- changed the method 'add' of 'HostKeyRepository' interface.\n- 'UIKeyborarInteracetive' will ignore empty prompt by sshd.\n- added 'sendIgnore()' method to 'Session' class.\n- added '-p' for scp command in 'examples/ScpTo.java' to preserve\n  modification times, access times, and modes from the original file.\n\n\nChanges since version 0.1.17:\n- added 'com.jcraft.jsch.HostKeyRepository' interface.\n  It will allow you to handle host keys in your own repository\n  (for example, RDB) instead of using 'known_hosts' file.\n- added methods to get the finger-print of host keys.\n  refer to 'examples/KnownHosts.java'.\n- improved 'known_hosts' file handling.\n  - comment lines will be kept.\n  - SSH1 host keys will be kept.\n  - each hostname can have multiple host keys.\n- fixed a crash bug in processing private keys which have too long key-bits.\n\n\nChanges since version 0.1.16:\n- 'com.jcraft.jsch.jce.DHG1' and 'com.jcraft.jsch.jce.DHGEX' are moved to\n  'com.jcraft.jsch' package.\n- added APIs to handle hostkeys included in 'known_hosts',\n     JSch.getHostKeys(),\n     JSch.removeHostKey()\n- allowing to set timeout value in opening sockets,\n     Session.connect(int timeout)\n\n\nChanges since version 0.1.15:\n- adding support of setting mtime for remote files on sftp channel.\n- setKnownHosts method of JSch class will accept InputStream.\n- implementation of Basic password authentication for HTTP proxy.\n- fixed a bug in checking which ssh protocol version remote sshd supports\n- SSH_MSG_CHANNEL_OPEN_FAILURE will be handled correctly.\n- methods in SftpATTRS class has been public.\n- working around SIGBLOB bug hidden in older sshd.\n\n\nChanges since version 0.1.14:\n- fixed a crash bug in accepting keep-alive messages.\n- the parent directory of 'known_hosts' file will be created\n  if it does not exist.\n- the Subsystem channel support was removed.\n\n\nChanges since version 0.1.13:\n- added 'setClientVersion' method to Session class.\n- fixed hung-up problem on SftpChannel in connecting to\n  the sshd, which does not support sftp.\n- fixed OutOfMemory exception problem in decrypting a private key\n  with bad passphrase.\n- fixed hung-up problem in communicating with the sshd,\n  whose window size is small.\n- RuntimeExceptions will be thrown from jsch APIs.\n- SSH_MSG_CHANNEL_SUCCESS and SSH_MSG_CHANNEL_FAILURE requests\n  have been supported.\n\n\nChanges since version 0.1.12:\n- added the partial authentication support.\n- allowing to change the passphrase of a private key file\n  instead of creating a new private key.\n- added 'examples/ChangePassphrase.java'\n- the interface 'UIKeyboardInteractive' has been modified.\n\n\nChanges since version 0.1.11:\n- RSA keypair generation.\n- added the method 'getFingerPrint' to KeyPair class,\n  which will return the finger print of the public key.\n- fixed a bug in generating non-ciphered private key.\n\n\nChanges since version 0.1.10:\n- fixed a bug in the password authentication, sneaked in\n  0.1.9. By this bug, the password authentication had failed every time.\n\n\nChanges since version 0.1.9:\n- username and password can be in UTF-8 encoding.\n- DSA keypair generation.\n- added 'examples/KeyGen.java', which demonstrates\n  the DSA keypair generation.\n\n\nChanges since version 0.1.8:\n- fixed crash problems on the local port forwarding.\n- fixed crash problems on the remote port forwarding.\n- added setErrStream() and getErrStream() to ChannelExec.\n- added keyboard-interactive authentication support.\n- modified TripleDESCBC to support IBM's JDK 1.4.1.\n- added 'examples/UserAuthKI.java', which demonstrates keyboard-interactive\n  authentication.\n\n\nChanges since version 0.1.7:\n- added APIs for sftp resume downloads and uploads.\n  The author greatly appreciates\n\telpernotador(webmaster at unlix dot com dot ar),\n  who motivated him to hack this functionality.\n- 'examples/Sftp.java' demonstrates sftp resume functionality.\n  Please refer to \"put-resume\", \"put-append\", \"get-resume\" and\n  \"get-append\" command.\n- added the support of 'window-change' request.\n- fixed a freeze bug in 'Inputstream get(String src)' method of 'ChannelSftp'\n  class.\n\n\nChanges since version 0.1.6:\n- added 'int getExitStatus()' method to 'Channel' class.\n- fixed crash bugs in closing channels for port forwarding.\n- fixed glitches in managing forwarded ports.\n\n\nChanges since version 0.1.5:\n- fixed crash bugs in port forwarding.\n- modified to use \"ssh-rsa\" for key-exchanging by the default.\n- the port forwarding setting can be canceled dynamically.\n- fixed a freeze bug in getting an empty file on sftp channel.\n\n\nChanges since version 0.1.4:\n- fixed a bug in managing local window size.\n  The local window should be consumed by CHANNEL_EXTENDED_DATA packet.\n- checking the availability of the ssh session in opening channels.\n  In some case, ssh session had been freezed.\n- java.io.File.separator will be refereed in generating local pathname\n  on sftp channel.\n- absolute local pathname will be handled correctly on sftp channel.\n\n\nChanges since version 0.1.3:\n- fixed a serious bug, which had leaked resources related to\n  ChannelExec.\n- added the older SFTP protocol(version 0, 1, 2) support.\n- fixed a problem in the authentication step for FSecure's sshd.\n- fixed a bug, which had broken Diffie-Hellman key exchange in some case.\n- implemented the file name globbing for local files on sftp session.\n- fixed a bug in the file name globbing.\n- added an interface 'SftpProgressMonitor'.\n- modified 'examples/Sftp.java' to demonstrate displaying progress-bar\n  in transferring files.\n\n\nChanges since version 0.1.2:\n- modified 'build.xml' to allow Ant users to compile jsch with debug\n  support (i.e. line-number tables) by overriding the property\n  javac.debug on the command line.\n- added a property 'StrictHostKeyChecking'.\n- added 'UserAuthNone' class to request a list of authentication methods on\n  remote sshd.\n- channels will be managed in each sessions.\n- added 'ChannelSubsystem', which allows users to use their own\n  implementations for subsystems.\n- added 'isEOF()' method to 'Channel' class.\n- supported key pair files in DOS file format.\n\n\nChanges since version 0.1.1:\n- added the file name globbing support on sftp session.\n- fixed a bug in the public key authentication.\n  When there was not a public key in ~/.ssh/, that problem occurred.\n- improved the 'setTimeout' method.\n- fixed a typo in 'LICENSE.txt'\n\n\nChanges since version 0.1.0:\n- added 'rekey' method to 'Session' class for key re-exchanging.\n- added 'rekey' and 'compression' command to 'examples/Sftp.java'.\n- added new 'get' and 'put' methods to 'ChannelSftp'.\n  Those methods will operate I/O streams.\n- methods in 'ChannelSftp' will throw 'SftpException'\n- 'ChannelSftp.Ssh_exp_name' is added for the output of 'ls'.\n  Thanks to Graeme Vetterlein.\n- added 'setTimeout' and 'getTimeout' methods to 'Session' class.\n- guess will be done in the algorithm negotiation step.\n- FSecure's DSA private key has been supported partially.\n- hostkeys will be saved into 'known_hosts' file.\n- fixed a bug in 'Util.toBase64' method.\n- 'Identity' will reject unrecognized keys.\n- 'build.xml' will check if jzlib is available or not.\n  Thanks to Stefan Bodewig.\n- added javadoc target in 'build.xml'.\n  Thanks to Robert Anderson.\n\n\nChanges since version 0.0.13:\n- fixed a bug in connecting to Fsecure's sshd on Windows.\n- the license is changed to BSD style.\n\n\nChanges since version 0.0.12:\n- fixed a bug in verifying DAS signatures.\n- added 'SftpATTR' class, which allow you to get attributes of remote files on\n  sftp channel, and 'stat', 'lstat' method are added to 'ChannelSftp' class.\n- added 'getInputStream' and 'getOutputStream' methods Channel class, which\n  return passive I/O streams.\n- 'setIdentity' method is deleted from 'Session' class and\n  'addIdentity' method is added to 'JSch' class\n- 'setUserName' method is deleted from 'Session' class and\n  'getSession' method of 'JSch' class is changed.\n- 'isConnected' method is added to 'Session' class.\n- 'UserInfo' interface is changed.\n\n\nChanges since version 0.0.11:\n- taking care of remote window size.\n- adding 'disconnect' method to 'Channel' and 'Session' classes.\n- signal sending support.\n- 'mkdir' command for sftp.\n- 'fromBase64' method has been moved to Util class and 'toBase64' method has\n   also been added to that class.\n- 'KnownHosts' class for checking host-key in 'known_host' file.\n- 'examples/KnownHosts.java' has been added.\n- 'setUserName' and 'setPassword' methods have been added to Session class.\n- 'UserInfo' interface has been changed.\n- The implementation of compression has moved to 'com.jcraft.jsch.jcraft'\n  package.\n- fixed a bug in handling 'SSH_MSG_CHANNEL_REQUET' request.\n- fixed a bug in sending multiple requests on a single session.\n\n\nChanges since version 0.0.10:\n- Diffie-Hellman key exchange 'diffie-hellman-group1-sha1' is supported.\n  Refer to 'src/com/jcraft/jsch/jce/DHG1.java'.\n  Thanks to Mitsugu Kitano, whose feedback was very helpful.\n- By the default, 'diffie-hellman-group1-sha1' will be used in the\n  key exchange step.\n- The file attribute on 'SSH File Transfer Protocol' is supported.\n  Now, we can say JSch supports 'SSH File Transfer Protocol'.\n- 'examples/Sftp.java' is updated.\n  'chgrp','chown','chmod' commands are supported.\n\n\nChanges since version 0.0.9:\n- SSH File Transfer Protocol is supported partially.\n- 'examples/Sftp.java' is added.\n  This example is a tiny sftp command and supports 'cd','put','get','rm',etc.\n- 'close' method is added to Channel interface.\n- build.xml for examples is added.\n  Thanks to Ronald Broberg.\n\n\nChanges since version 0.0.8:\n- the tunneling through a SOCKS5 proxy is supported.\n- 'examples/ScpFrom.java' is added.\n- 'com.jcraft.jsch.UserInfo' interface is modified.\n\n\nChanges since version 0.0.7:\n- Packet comression is supported.\n- 'examples/Compression.java' is added.\n- JZlib is included.\n\n\nChanges since version 0.0.6:\n- RSA host key is supported.\n- RSA public key authentication is supported.\n\n\nChanges since version 0.0.5:\n- DSA public key authentication is supported.\n- examples/UserAuthPubKey.java is added.\n- examples/ScpTo.java is added.\n\n\nChanges since version 0.0.4:\n- 3des-cbc is supported.\n- hmac-sha1 is supported.\n- hmac-md5-96 is supported.\n- hmac-sha1-96 is supported.\n\n\nChanges since version 0.0.3:\n- port forwarding, similar to the -L option of SSH.\n- examples/PortForwardingL.java is added.\n- examples/StreamForwarding.java is added.\n- examples/Exec.java is renamed as examples/Shell.java\n- stream forwarding is added.\n- ChannelSftp class is added for implementing filexfer.\n- interfaces for jsch users are changed.\n\n\nChanges since version 0.0.2:\n- remote exec is supported.\n- examples/Exec.java is added.\n- build.xml and some scripts for Ant are added. (lbruand)\n- Const class is added. (lbruand)\n\n\nChanges since version 0.0.1:\n- the tunneling via HTTP proxy is supported.\n- port forwarding like option -R of ssh command.\n  the given port on the remote host will be forwarded to the given host\n  and port on the local side.\n"
  },
  {
    "path": "java/com/jcraft/jsch/Channel.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.PipedInputStream;\nimport java.io.PipedOutputStream;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.IOException;\n\n\npublic abstract class Channel implements Runnable{\n\n  static final int SSH_MSG_CHANNEL_OPEN_CONFIRMATION=      91;\n  static final int SSH_MSG_CHANNEL_OPEN_FAILURE=           92;\n  static final int SSH_MSG_CHANNEL_WINDOW_ADJUST=          93;\n\n  static final int SSH_OPEN_ADMINISTRATIVELY_PROHIBITED=    1;\n  static final int SSH_OPEN_CONNECT_FAILED=                 2;\n  static final int SSH_OPEN_UNKNOWN_CHANNEL_TYPE=           3;\n  static final int SSH_OPEN_RESOURCE_SHORTAGE=              4;\n\n  static int index=0; \n  private static java.util.Vector pool=new java.util.Vector();\n  static Channel getChannel(String type){\n    if(type.equals(\"session\")){\n      return new ChannelSession();\n    }\n    if(type.equals(\"shell\")){\n      return new ChannelShell();\n    }\n    if(type.equals(\"exec\")){\n      return new ChannelExec();\n    }\n    if(type.equals(\"x11\")){\n      return new ChannelX11();\n    }\n    if(type.equals(\"auth-agent@openssh.com\")){\n      return new ChannelAgentForwarding();\n    }\n    if(type.equals(\"direct-tcpip\")){\n      return new ChannelDirectTCPIP();\n    }\n    if(type.equals(\"forwarded-tcpip\")){\n      return new ChannelForwardedTCPIP();\n    }\n    if(type.equals(\"sftp\")){\n      return new ChannelSftp();\n    }\n    if(type.equals(\"subsystem\")){\n      return new ChannelSubsystem();\n    }\n    return null;\n  }\n  static Channel getChannel(int id, Session session){\n    synchronized(pool){\n      for(int i=0; i<pool.size(); i++){\n        Channel c=(Channel)(pool.elementAt(i));\n        if(c.id==id && c.session==session) return c;\n      }\n    }\n    return null;\n  }\n  static void del(Channel c){\n    synchronized(pool){\n      pool.removeElement(c);\n    }\n  }\n\n  int id;\n  volatile int recipient=-1;\n  protected byte[] type=Util.str2byte(\"foo\");\n  volatile int lwsize_max=0x100000;\n  volatile int lwsize=lwsize_max;     // local initial window size\n  volatile int lmpsize=0x4000;     // local maximum packet size\n\n  volatile long rwsize=0;         // remote initial window size\n  volatile int rmpsize=0;        // remote maximum packet size\n\n  IO io=null;    \n  Thread thread=null;\n\n  volatile boolean eof_local=false;\n  volatile boolean eof_remote=false;\n\n  volatile boolean close=false;\n  volatile boolean connected=false;\n  volatile boolean open_confirmation=false;\n\n  volatile int exitstatus=-1;\n\n  volatile int reply=0; \n  volatile int connectTimeout=0;\n\n  private Session session;\n\n  int notifyme=0; \n\n  Channel(){\n    synchronized(pool){\n      id=index++;\n      pool.addElement(this);\n    }\n  }\n  synchronized void setRecipient(int foo){\n    this.recipient=foo;\n    if(notifyme>0)\n      notifyAll();\n  }\n  int getRecipient(){\n    return recipient;\n  }\n\n  void init() throws JSchException {\n  }\n\n  public void connect() throws JSchException{\n    connect(0);\n  }\n\n  public void connect(int connectTimeout) throws JSchException{\n    this.connectTimeout=connectTimeout;\n    try{\n      sendChannelOpen();\n      start();\n    }\n    catch(Exception e){\n      connected=false;\n      disconnect();\n      if(e instanceof JSchException) \n        throw (JSchException)e;\n      throw new JSchException(e.toString(), e);\n    }\n  }\n\n  public void setXForwarding(boolean foo){\n  }\n\n  public void start() throws JSchException{}\n\n  public boolean isEOF() {return eof_remote;}\n\n  void getData(Buffer buf){\n    setRecipient(buf.getInt());\n    setRemoteWindowSize(buf.getUInt());\n    setRemotePacketSize(buf.getInt());\n  }\n\n  public void setInputStream(InputStream in){\n    io.setInputStream(in, false);\n  }\n  public void setInputStream(InputStream in, boolean dontclose){\n    io.setInputStream(in, dontclose);\n  }\n  public void setOutputStream(OutputStream out){\n    io.setOutputStream(out, false);\n  }\n  public void setOutputStream(OutputStream out, boolean dontclose){\n    io.setOutputStream(out, dontclose);\n  }\n  public void setExtOutputStream(OutputStream out){\n    io.setExtOutputStream(out, false);\n  }\n  public void setExtOutputStream(OutputStream out, boolean dontclose){\n    io.setExtOutputStream(out, dontclose);\n  }\n  public InputStream getInputStream() throws IOException {\n    int max_input_buffer_size = 32*1024;\n    try {\n      max_input_buffer_size =\n        Integer.parseInt(getSession().getConfig(\"max_input_buffer_size\"));\n    }\n    catch(Exception e){}\n    PipedInputStream in =\n      new MyPipedInputStream(\n                             32*1024,  // this value should be customizable.\n                             max_input_buffer_size\n                             );\n    boolean resizable = 32*1024<max_input_buffer_size;\n    io.setOutputStream(new PassiveOutputStream(in, resizable), false);\n    return in;\n  }\n  public InputStream getExtInputStream() throws IOException {\n    int max_input_buffer_size = 32*1024;\n    try {\n      max_input_buffer_size =\n        Integer.parseInt(getSession().getConfig(\"max_input_buffer_size\"));\n    }\n    catch(Exception e){}\n    PipedInputStream in =\n      new MyPipedInputStream(\n                             32*1024,  // this value should be customizable.\n                             max_input_buffer_size\n                             );\n    boolean resizable = 32*1024<max_input_buffer_size;\n    io.setExtOutputStream(new PassiveOutputStream(in, resizable), false);\n    return in;\n  }\n  public OutputStream getOutputStream() throws IOException {\n\n    final Channel channel=this;\n    OutputStream out=new OutputStream(){\n        private int dataLen=0;\n        private Buffer buffer=null;\n        private Packet packet=null;\n        private boolean closed=false;\n        private synchronized void init() throws java.io.IOException{\n          buffer=new Buffer(rmpsize);\n          packet=new Packet(buffer);\n\n          byte[] _buf=buffer.buffer;\n          if(_buf.length-(14+0)-Session.buffer_margin<=0){\n            buffer=null;\n            packet=null;\n            throw new IOException(\"failed to initialize the channel.\");\n          }\n\n        }\n        byte[] b=new byte[1];\n        public void write(int w) throws java.io.IOException{\n          b[0]=(byte)w;\n          write(b, 0, 1);\n        }\n        public void write(byte[] buf, int s, int l) throws java.io.IOException{\n          if(packet==null){\n            init();\n          }\n\n          if(closed){\n            throw new java.io.IOException(\"Already closed\");\n          }\n\n          byte[] _buf=buffer.buffer;\n          int _bufl=_buf.length;\n          while(l>0){\n            int _l=l;\n            if(l>_bufl-(14+dataLen)-Session.buffer_margin){\n              _l=_bufl-(14+dataLen)-Session.buffer_margin;\n            }\n\n            if(_l<=0){\n              flush();\n              continue;\n            }\n\n            System.arraycopy(buf, s, _buf, 14+dataLen, _l);\n            dataLen+=_l;\n            s+=_l;\n            l-=_l;\n          }\n        }\n\n        public void flush() throws java.io.IOException{\n          if(closed){\n            throw new java.io.IOException(\"Already closed\");\n          }\n          if(dataLen==0)\n            return;\n          packet.reset();\n          buffer.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);\n          buffer.putInt(recipient);\n          buffer.putInt(dataLen);\n          buffer.skip(dataLen);\n          try{\n            int foo=dataLen;\n            dataLen=0;\n            synchronized(channel){\n              if(!channel.close)\n                getSession().write(packet, channel, foo);\n            }\n          }\n          catch(Exception e){\n            close();\n            throw new java.io.IOException(e.toString());\n          }\n\n        }\n        public void close() throws java.io.IOException{\n          if(packet==null){\n            try{\n              init();\n            }\n            catch(java.io.IOException e){\n              // close should be finished silently.\n              return;\n            }\n          }\n          if(closed){\n            return;\n          }\n          if(dataLen>0){\n            flush();\n          }\n          channel.eof();\n          closed=true;\n        }\n      };\n    return out;\n  }\n\n  class MyPipedInputStream extends PipedInputStream{\n    private int BUFFER_SIZE = 1024;\n    private int max_buffer_size = BUFFER_SIZE;\n    MyPipedInputStream() throws IOException{ super(); }\n    MyPipedInputStream(int size) throws IOException{\n      super();\n      buffer=new byte[size];\n      BUFFER_SIZE = size;\n      max_buffer_size = size;\n    }\n    MyPipedInputStream(int size, int max_buffer_size) throws IOException{\n      this(size);\n      this.max_buffer_size = max_buffer_size;\n    }\n    MyPipedInputStream(PipedOutputStream out) throws IOException{ super(out); }\n    MyPipedInputStream(PipedOutputStream out, int size) throws IOException{\n      super(out);\n      buffer=new byte[size];\n      BUFFER_SIZE=size;\n    }\n\n    /*\n     * TODO: We should have our own Piped[I/O]Stream implementation.\n     * Before accepting data, JDK's PipedInputStream will check the existence of\n     * reader thread, and if it is not alive, the stream will be closed.\n     * That behavior may cause the problem if multiple threads make access to it.\n     */\n    public synchronized void updateReadSide() throws IOException {\n      if(available() != 0){ // not empty\n        return;\n      }\n      in = 0;\n      out = 0;\n      buffer[in++] = 0;\n      read();\n    }\n\n    private int freeSpace(){\n      int size = 0;\n      if(out < in) {\n        size = buffer.length-in;\n      }\n      else if(in < out){\n        if(in == -1) size = buffer.length;\n        else size = out - in;\n      }\n      return size;\n    } \n    synchronized void checkSpace(int len) throws IOException {\n      int size = freeSpace();\n      if(size<len){\n        int datasize=buffer.length-size;\n        int foo = buffer.length;\n        while((foo - datasize) < len){\n          foo*=2;\n        }\n\n        if(foo > max_buffer_size){\n          foo = max_buffer_size;\n        }\n        if((foo - datasize) < len) return;\n\n        byte[] tmp = new byte[foo];\n        if(out < in) {\n          System.arraycopy(buffer, 0, tmp, 0, buffer.length);\n        }\n        else if(in < out){\n          if(in == -1) {\n          }\n          else {\n            System.arraycopy(buffer, 0, tmp, 0, in);\n            System.arraycopy(buffer, out, \n                             tmp, tmp.length-(buffer.length-out),\n                             (buffer.length-out));\n            out = tmp.length-(buffer.length-out);\n          }\n        }\n        else if(in == out){\n          System.arraycopy(buffer, 0, tmp, 0, buffer.length);\n          in=buffer.length;\n        }\n        buffer=tmp;\n      }\n      else if(buffer.length == size && size > BUFFER_SIZE) { \n        int  i = size/2;\n        if(i<BUFFER_SIZE) i = BUFFER_SIZE;\n        byte[] tmp = new byte[i];\n        buffer=tmp;\n      }\n    }\n  }\n  void setLocalWindowSizeMax(int foo){ this.lwsize_max=foo; }\n  void setLocalWindowSize(int foo){ this.lwsize=foo; }\n  void setLocalPacketSize(int foo){ this.lmpsize=foo; }\n  synchronized void setRemoteWindowSize(long foo){ this.rwsize=foo; }\n  synchronized void addRemoteWindowSize(long foo){ \n    this.rwsize+=foo; \n    if(notifyme>0)\n      notifyAll();\n  }\n  void setRemotePacketSize(int foo){ this.rmpsize=foo; }\n\n  public void run(){\n  }\n\n  void write(byte[] foo) throws IOException {\n    write(foo, 0, foo.length);\n  }\n  void write(byte[] foo, int s, int l) throws IOException {\n    try{\n      io.put(foo, s, l);\n    }catch(NullPointerException e){}\n  }\n  void write_ext(byte[] foo, int s, int l) throws IOException {\n    try{\n      io.put_ext(foo, s, l);\n    }catch(NullPointerException e){}\n  }\n\n  void eof_remote(){\n    eof_remote=true;\n    try{\n      io.out_close();\n    }\n    catch(NullPointerException e){}\n  }\n\n  void eof(){\n    if(eof_local)return;\n    eof_local=true;\n\n    int i = getRecipient();\n    if(i == -1) return;\n\n    try{\n      Buffer buf=new Buffer(100);\n      Packet packet=new Packet(buf);\n      packet.reset();\n      buf.putByte((byte)Session.SSH_MSG_CHANNEL_EOF);\n      buf.putInt(i);\n      synchronized(this){\n        if(!close)\n          getSession().write(packet);\n      }\n    }\n    catch(Exception e){\n      //System.err.println(\"Channel.eof\");\n      //e.printStackTrace();\n    }\n    /*\n    if(!isConnected()){ disconnect(); }\n    */\n  }\n\n  /*\n  http://www1.ietf.org/internet-drafts/draft-ietf-secsh-connect-24.txt\n\n5.3  Closing a Channel\n  When a party will no longer send more data to a channel, it SHOULD\n   send SSH_MSG_CHANNEL_EOF.\n\n            byte      SSH_MSG_CHANNEL_EOF\n            uint32    recipient_channel\n\n  No explicit response is sent to this message.  However, the\n   application may send EOF to whatever is at the other end of the\n  channel.  Note that the channel remains open after this message, and\n   more data may still be sent in the other direction.  This message\n   does not consume window space and can be sent even if no window space\n   is available.\n\n     When either party wishes to terminate the channel, it sends\n     SSH_MSG_CHANNEL_CLOSE.  Upon receiving this message, a party MUST\n   send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this\n   message for the channel.  The channel is considered closed for a\n     party when it has both sent and received SSH_MSG_CHANNEL_CLOSE, and\n   the party may then reuse the channel number.  A party MAY send\n   SSH_MSG_CHANNEL_CLOSE without having sent or received\n   SSH_MSG_CHANNEL_EOF.\n\n            byte      SSH_MSG_CHANNEL_CLOSE\n            uint32    recipient_channel\n\n   This message does not consume window space and can be sent even if no\n   window space is available.\n\n   It is recommended that any data sent before this message is delivered\n     to the actual destination, if possible.\n  */\n\n  void close(){\n    if(close)return;\n    close=true;\n    eof_local=eof_remote=true;\n\n    int i = getRecipient();\n    if(i == -1) return;\n\n    try{\n      Buffer buf=new Buffer(100);\n      Packet packet=new Packet(buf);\n      packet.reset();\n      buf.putByte((byte)Session.SSH_MSG_CHANNEL_CLOSE);\n      buf.putInt(i);\n      synchronized(this){\n        getSession().write(packet);\n      }\n    }\n    catch(Exception e){\n      //e.printStackTrace();\n    }\n  }\n  public boolean isClosed(){\n    return close;\n  }\n  static void disconnect(Session session){\n    Channel[] channels=null;\n    int count=0;\n    synchronized(pool){\n      channels=new Channel[pool.size()];\n      for(int i=0; i<pool.size(); i++){\n\ttry{\n\t  Channel c=((Channel)(pool.elementAt(i)));\n\t  if(c.session==session){\n\t    channels[count++]=c;\n\t  }\n\t}\n\tcatch(Exception e){\n\t}\n      } \n    }\n    for(int i=0; i<count; i++){\n      channels[i].disconnect();\n    }\n  }\n\n  public void disconnect(){\n    //System.err.println(this+\":disconnect \"+io+\" \"+connected);\n    //Thread.dumpStack();\n\n    try{\n\n      synchronized(this){\n        if(!connected){\n          return;\n        }\n        connected=false;\n      }\n\n      close();\n\n      eof_remote=eof_local=true;\n\n      thread=null;\n\n      try{\n        if(io!=null){\n          io.close();\n        }\n      }\n      catch(Exception e){\n        //e.printStackTrace();\n      }\n      // io=null;\n    }\n    finally{\n      Channel.del(this);\n    }\n  }\n\n  public boolean isConnected(){\n    Session _session=this.session;\n    if(_session!=null){\n      return _session.isConnected() && connected;\n    }\n    return false;\n  }\n\n  public void sendSignal(String signal) throws Exception {\n    RequestSignal request=new RequestSignal();\n    request.setSignal(signal);\n    request.request(getSession(), this);\n  }\n\n//  public String toString(){\n//      return \"Channel: type=\"+new String(type)+\",id=\"+id+\",recipient=\"+recipient+\",window_size=\"+window_size+\",packet_size=\"+packet_size;\n//  }\n\n/*\n  class OutputThread extends Thread{\n    Channel c;\n    OutputThread(Channel c){ this.c=c;}\n    public void run(){c.output_thread();}\n  }\n*/\n\n  class PassiveInputStream extends MyPipedInputStream{\n    PipedOutputStream out;\n    PassiveInputStream(PipedOutputStream out, int size) throws IOException{\n      super(out, size);\n      this.out=out;\n    }\n    PassiveInputStream(PipedOutputStream out) throws IOException{\n      super(out);\n      this.out=out;\n    }\n    public void close() throws IOException{\n      if(out!=null){\n        this.out.close();\n      }\n      out=null;\n    }\n  }\n  class PassiveOutputStream extends PipedOutputStream{\n    private MyPipedInputStream _sink=null;\n    PassiveOutputStream(PipedInputStream in,\n                        boolean resizable_buffer) throws IOException{\n      super(in);\n      if(resizable_buffer && (in instanceof MyPipedInputStream)) {\n        this._sink=(MyPipedInputStream)in;\n      }\n    }\n    public void write(int b) throws IOException {\n      if(_sink != null) {\n        _sink.checkSpace(1);\n      }\n      super.write(b);\n    }\n    public void write(byte[] b, int off, int len) throws IOException {\n      if(_sink != null) {\n        _sink.checkSpace(len);\n      }\n      super.write(b, off, len); \n    }\n  }\n\n  void setExitStatus(int status){ exitstatus=status; }\n  public int getExitStatus(){ return exitstatus; }\n\n  void setSession(Session session){\n    this.session=session;\n  }\n\n  public Session getSession() throws JSchException{ \n    Session _session=session;\n    if(_session==null){\n      throw new JSchException(\"session is not available\");\n    }\n    return _session;\n  }\n  public int getId(){ return id; }\n\n  protected void sendOpenConfirmation() throws Exception{\n    Buffer buf=new Buffer(100);\n    Packet packet=new Packet(buf);\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_CHANNEL_OPEN_CONFIRMATION);\n    buf.putInt(getRecipient());\n    buf.putInt(id);\n    buf.putInt(lwsize);\n    buf.putInt(lmpsize);\n    getSession().write(packet);\n  }\n\n  protected void sendOpenFailure(int reasoncode){\n    try{\n      Buffer buf=new Buffer(100);\n      Packet packet=new Packet(buf);\n      packet.reset();\n      buf.putByte((byte)SSH_MSG_CHANNEL_OPEN_FAILURE);\n      buf.putInt(getRecipient());\n      buf.putInt(reasoncode);\n      buf.putString(Util.str2byte(\"open failed\"));\n      buf.putString(Util.empty);\n      getSession().write(packet);\n    }\n    catch(Exception e){\n    }\n  }\n\n  protected Packet genChannelOpenPacket(){\n    Buffer buf=new Buffer(100);\n    Packet packet=new Packet(buf);\n    // byte   SSH_MSG_CHANNEL_OPEN(90)\n    // string channel type         //\n    // uint32 sender channel       // 0\n    // uint32 initial window size  // 0x100000(65536)\n    // uint32 maxmum packet size   // 0x4000(16384)\n    packet.reset();\n    buf.putByte((byte)90);\n    buf.putString(this.type);\n    buf.putInt(this.id);\n    buf.putInt(this.lwsize);\n    buf.putInt(this.lmpsize);\n    return packet;\n  }\n\n  protected void sendChannelOpen() throws Exception {\n    Session _session=getSession();\n    if(!_session.isConnected()){\n      throw new JSchException(\"session is down\");\n    }\n\n    Packet packet = genChannelOpenPacket();\n    _session.write(packet);\n\n    int retry=2000;\n    long start=System.currentTimeMillis();\n    long timeout=connectTimeout;\n    if(timeout!=0L) retry = 1;\n    synchronized(this){\n      while(this.getRecipient()==-1 &&\n            _session.isConnected() &&\n             retry>0){\n        if(timeout>0L){\n          if((System.currentTimeMillis()-start)>timeout){\n            retry=0;\n            continue;\n          }\n        }\n        try{\n          long t = timeout==0L ? 10L : timeout;\n          this.notifyme=1;\n          wait(t);\n        }\n        catch(java.lang.InterruptedException e){\n        }\n        finally{\n          this.notifyme=0;\n        }\n        retry--;\n      }\n    }\n    if(!_session.isConnected()){\n      throw new JSchException(\"session is down\");\n    }\n    if(this.getRecipient()==-1){  // timeout\n      throw new JSchException(\"channel is not opened.\");\n    }\n    if(this.open_confirmation==false){  // SSH_MSG_CHANNEL_OPEN_FAILURE\n      throw new JSchException(\"channel is not opened.\");\n    }\n    connected=true;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ChannelAgentForwarding.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.net.*;\nimport java.util.Vector;\n\nclass ChannelAgentForwarding extends Channel{\n\n  static private final int LOCAL_WINDOW_SIZE_MAX=0x20000;\n  static private final int LOCAL_MAXIMUM_PACKET_SIZE=0x4000;\n\n  private final byte SSH_AGENTC_REQUEST_RSA_IDENTITIES = 1;\n  private final byte SSH_AGENT_RSA_IDENTITIES_ANSWER = 2;\n  private final byte SSH_AGENTC_RSA_CHALLENGE = 3;\n  private final byte SSH_AGENT_RSA_RESPONSE = 4;\n  private final byte SSH_AGENT_FAILURE = 5;\n  private final byte SSH_AGENT_SUCCESS = 6;\n  private final byte SSH_AGENTC_ADD_RSA_IDENTITY\t= 7;\n  private final byte SSH_AGENTC_REMOVE_RSA_IDENTITY = 8;\n  private final byte SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES = 9;\n\n  private final byte SSH2_AGENTC_REQUEST_IDENTITIES=11;\n  private final byte SSH2_AGENT_IDENTITIES_ANSWER=12;\n  private final byte SSH2_AGENTC_SIGN_REQUEST=13;\n  private final byte SSH2_AGENT_SIGN_RESPONSE=14;\n  private final byte SSH2_AGENTC_ADD_IDENTITY=17;\n  private final byte SSH2_AGENTC_REMOVE_IDENTITY=18;\n  private final byte SSH2_AGENTC_REMOVE_ALL_IDENTITIES=19;\n  private final byte SSH2_AGENT_FAILURE=30;\n\n  boolean init=true;\n\n  private Buffer rbuf=null;\n  private Buffer wbuf=null;\n  private Packet packet=null;\n  private Buffer mbuf=null;\n\n  ChannelAgentForwarding(){\n    super();\n\n    setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX);\n    setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX);\n    setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE);\n\n    type=Util.str2byte(\"auth-agent@openssh.com\");\n    rbuf=new Buffer();\n    rbuf.reset();\n    //wbuf=new Buffer(rmpsize);\n    //packet=new Packet(wbuf);\n    mbuf=new Buffer();\n    connected=true;\n  }\n\n  public void run(){\n    try{\n      sendOpenConfirmation();\n    }\n    catch(Exception e){\n      close=true;\n      disconnect();\n    }\n  }\n\n  void write(byte[] foo, int s, int l) throws java.io.IOException {\n\n    if(packet==null){\n      wbuf=new Buffer(rmpsize);\n      packet=new Packet(wbuf);\n    }\n\n    rbuf.shift();\n    if(rbuf.buffer.length<rbuf.index+l){\n      byte[] newbuf=new byte[rbuf.s+l];\n      System.arraycopy(rbuf.buffer, 0, newbuf, 0, rbuf.buffer.length);\n      rbuf.buffer=newbuf;\n    }\n\n    rbuf.putByte(foo, s, l);\n\n    int mlen=rbuf.getInt();\n    if(mlen>rbuf.getLength()){\n      rbuf.s-=4;\n      return;\n    }\n\n    int typ=rbuf.getByte();\n\n    Session _session=null;\n    try{\n      _session=getSession();\n    }\n    catch(JSchException e){\n      throw new java.io.IOException(e.toString());\n    }\n\n    IdentityRepository irepo = _session.getIdentityRepository();\n    UserInfo userinfo=_session.getUserInfo();\n\n    mbuf.reset();\n\n    if(typ==SSH2_AGENTC_REQUEST_IDENTITIES){ \n      mbuf.putByte(SSH2_AGENT_IDENTITIES_ANSWER);\n      Vector identities = irepo.getIdentities();\n      synchronized(identities){\n        int count=0;\n        for(int i=0; i<identities.size(); i++){\n          Identity identity=(Identity)(identities.elementAt(i));\n          if(identity.getPublicKeyBlob()!=null)\n            count++;\n        }\n        mbuf.putInt(count);\n        for(int i=0; i<identities.size(); i++){\n          Identity identity=(Identity)(identities.elementAt(i));\n          byte[] pubkeyblob=identity.getPublicKeyBlob();\n          if(pubkeyblob==null)\n            continue;\n          mbuf.putString(pubkeyblob);\n          mbuf.putString(Util.empty);\n        }\n      }\n    }\n    else if(typ==SSH_AGENTC_REQUEST_RSA_IDENTITIES) {\n      mbuf.putByte(SSH_AGENT_RSA_IDENTITIES_ANSWER);\n      mbuf.putInt(0);\n    }\n    else if(typ==SSH2_AGENTC_SIGN_REQUEST){\n      byte[] blob=rbuf.getString();\n      byte[] data=rbuf.getString();\n      int flags=rbuf.getInt();\n\n//      if((flags & 1)!=0){ //SSH_AGENT_OLD_SIGNATURE // old OpenSSH 2.0, 2.1\n//        datafellows = SSH_BUG_SIGBLOB;\n//      }\n\n      Vector identities = irepo.getIdentities();\n      Identity identity = null;\n      synchronized(identities){\n        for(int i=0; i<identities.size(); i++){\n          Identity _identity=(Identity)(identities.elementAt(i));\n          if(_identity.getPublicKeyBlob()==null)\n            continue;\n          if(!Util.array_equals(blob, _identity.getPublicKeyBlob())){\n            continue;\n          }\n          if(_identity.isEncrypted()){\n            if(userinfo==null)\n              continue;\n            while(_identity.isEncrypted()){\n              if(!userinfo.promptPassphrase(\"Passphrase for \"+_identity.getName())){\n                break;\n              }\n\n              String _passphrase=userinfo.getPassphrase();\n              if(_passphrase==null){\n                break;\n              }\n\n              byte[] passphrase=Util.str2byte(_passphrase);\n              try{\n                if(_identity.setPassphrase(passphrase)){\n                  break;\n                }\n              }\n              catch(JSchException e){\n                break;\n              }\n            }\n          }\n\n          if(!_identity.isEncrypted()){\n            identity=_identity;\n            break;\n          }\n        }\n      }\n\n      byte[] signature=null;\n\n      if(identity!=null){\n        signature=identity.getSignature(data);\n      }\n\n      if(signature==null){\n        mbuf.putByte(SSH2_AGENT_FAILURE);\n      }\n      else{\n        mbuf.putByte(SSH2_AGENT_SIGN_RESPONSE);\n        mbuf.putString(signature);\n      }\n    }\n    else if(typ==SSH2_AGENTC_REMOVE_IDENTITY){\n      byte[] blob=rbuf.getString();\n      irepo.remove(blob);\n      mbuf.putByte(SSH_AGENT_SUCCESS);\n    }\n    else if(typ==SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES){\n      mbuf.putByte(SSH_AGENT_SUCCESS);\n    }\n    else if(typ==SSH2_AGENTC_REMOVE_ALL_IDENTITIES){\n      irepo.removeAll();\n      mbuf.putByte(SSH_AGENT_SUCCESS);\n    }\n    else if(typ==SSH2_AGENTC_ADD_IDENTITY){\n      int fooo = rbuf.getLength();\n      byte[] tmp = new byte[fooo];\n      rbuf.getByte(tmp);\n      boolean result = irepo.add(tmp);\n      mbuf.putByte(result ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);\n    }\n    else {\n      rbuf.skip(rbuf.getLength()-1);\n      mbuf.putByte(SSH_AGENT_FAILURE);\n    }\n\n    byte[] response = new byte[mbuf.getLength()];\n    mbuf.getByte(response);\n    send(response);\n  }\n\n  private void send(byte[] message){\n    packet.reset();\n    wbuf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);\n    wbuf.putInt(recipient);\n    wbuf.putInt(4+message.length);\n    wbuf.putString(message);\n\n    try{\n      getSession().write(packet, this, 4+message.length);\n    }\n    catch(Exception e){\n    }\n  }\n\n  void eof_remote(){\n    super.eof_remote();\n    eof();\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ChannelDirectTCPIP.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.*;\n\npublic class ChannelDirectTCPIP extends Channel{\n\n  static private final int LOCAL_WINDOW_SIZE_MAX=0x20000;\n  static private final int LOCAL_MAXIMUM_PACKET_SIZE=0x4000;\n  static private final byte[] _type = Util.str2byte(\"direct-tcpip\");\n  String host;\n  int port;\n\n  String originator_IP_address=\"127.0.0.1\";\n  int originator_port=0;\n\n  ChannelDirectTCPIP(){\n    super();\n    type = _type;\n    setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX);\n    setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX);\n    setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE);\n  }\n\n  void init (){\n    io=new IO();\n  }\n\n  public void connect(int connectTimeout) throws JSchException{\n    this.connectTimeout=connectTimeout;\n    try{\n      Session _session=getSession();\n      if(!_session.isConnected()){\n        throw new JSchException(\"session is down\");\n      }\n\n      if(io.in!=null){\n        thread=new Thread(this);\n        thread.setName(\"DirectTCPIP thread \"+_session.getHost());\n        if(_session.daemon_thread){\n          thread.setDaemon(_session.daemon_thread);\n        }\n        thread.start();\n      }\n      else {\n        sendChannelOpen();\n      }\n    }\n    catch(Exception e){\n      io.close();\n      io=null;\n      Channel.del(this);\n      if (e instanceof JSchException) {\n        throw (JSchException) e;\n      }\n    }\n  }\n\n  public void run(){\n\n    try{\n      sendChannelOpen();\n\n      Buffer buf=new Buffer(rmpsize);\n      Packet packet=new Packet(buf);\n      Session _session=getSession();\n      int i=0;\n\n      while(isConnected() &&\n            thread!=null && \n            io!=null && \n            io.in!=null){\n        i=io.in.read(buf.buffer, \n                     14, \n                     buf.buffer.length-14\n                     -Session.buffer_margin\n                     );\n        if(i<=0){\n          eof();\n          break;\n        }\n        packet.reset();\n        buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);\n        buf.putInt(recipient);\n        buf.putInt(i);\n        buf.skip(i);\n        synchronized(this){\n          if(close)\n            break;\n          _session.write(packet, this, i);\n        }\n      }\n    }\n    catch(Exception e){\n      // Whenever an exception is thrown by sendChannelOpen(),\n      // 'connected' is false.\n      if(!connected){\n        connected=true;\n      }\n      disconnect();\n      return;\n    }\n\n    eof();\n    disconnect();\n  }\n\n  public void setInputStream(InputStream in){\n    io.setInputStream(in);\n  }\n  public void setOutputStream(OutputStream out){\n    io.setOutputStream(out);\n  }\n\n  public void setHost(String host){this.host=host;}\n  public void setPort(int port){this.port=port;}\n  public void setOrgIPAddress(String foo){this.originator_IP_address=foo;}\n  public void setOrgPort(int foo){this.originator_port=foo;}\n\n  protected Packet genChannelOpenPacket(){\n    Buffer buf = new Buffer(50 + // 6 + 4*8 + 12\n                            host.length() + originator_IP_address.length() +\n                            Session.buffer_margin);\n    Packet packet = new Packet(buf);\n    // byte   SSH_MSG_CHANNEL_OPEN(90)\n    // string channel type         //\n    // uint32 sender channel       // 0\n    // uint32 initial window size  // 0x100000(65536)\n    // uint32 maxmum packet size   // 0x4000(16384)\n    packet.reset();\n    buf.putByte((byte)90);\n    buf.putString(this.type);\n    buf.putInt(id);\n    buf.putInt(lwsize);\n    buf.putInt(lmpsize);\n    buf.putString(Util.str2byte(host));\n    buf.putInt(port);\n    buf.putString(Util.str2byte(originator_IP_address));\n    buf.putInt(originator_port);\n    return packet;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ChannelExec.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.util.*;\n\npublic class ChannelExec extends ChannelSession{\n\n  byte[] command=new byte[0];\n\n  public void start() throws JSchException{\n    Session _session=getSession();\n    try{\n      sendRequests();\n      Request request=new RequestExec(command);\n      request.request(_session, this);\n    }\n    catch(Exception e){\n      if(e instanceof JSchException) throw (JSchException)e;\n      if(e instanceof Throwable)\n        throw new JSchException(\"ChannelExec\", (Throwable)e);\n      throw new JSchException(\"ChannelExec\");\n    }\n\n    if(io.in!=null){\n      thread=new Thread(this);\n      thread.setName(\"Exec thread \"+_session.getHost());\n      if(_session.daemon_thread){\n        thread.setDaemon(_session.daemon_thread);\n      }\n      thread.start();\n    }\n  }\n\n  public void setCommand(String command){ \n    this.command=Util.str2byte(command);\n  }\n  public void setCommand(byte[] command){ \n    this.command=command;\n  }\n\n  void init() throws JSchException {\n    io.setInputStream(getSession().in);\n    io.setOutputStream(getSession().out);\n  }\n\n  public void setErrStream(java.io.OutputStream out){\n    setExtOutputStream(out);\n  }\n  public void setErrStream(java.io.OutputStream out, boolean dontclose){\n    setExtOutputStream(out, dontclose);\n  }\n  public java.io.InputStream getErrStream() throws java.io.IOException {\n    return getExtInputStream();\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ChannelForwardedTCPIP.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.net.*;\nimport java.io.*;\nimport java.util.Vector;\n\npublic class ChannelForwardedTCPIP extends Channel{\n\n  private static Vector pool = new Vector();\n\n  static private final int LOCAL_WINDOW_SIZE_MAX=0x20000;\n//static private final int LOCAL_WINDOW_SIZE_MAX=0x100000;\n  static private final int LOCAL_MAXIMUM_PACKET_SIZE=0x4000;\n\n  static private final int TIMEOUT=10*1000;\n\n  private Socket socket=null;\n  private ForwardedTCPIPDaemon daemon=null;\n  private Config config = null;\n\n  ChannelForwardedTCPIP(){\n    super();\n    setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX);\n    setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX);\n    setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE);\n    io=new IO();\n    connected=true;\n  }\n\n  public void run(){\n    try{ \n      if(config instanceof ConfigDaemon){\n        ConfigDaemon _config = (ConfigDaemon)config;\n        Class c=Class.forName(_config.target);\n        daemon=(ForwardedTCPIPDaemon)c.newInstance();\n\n        PipedOutputStream out=new PipedOutputStream();\n        io.setInputStream(new PassiveInputStream(out\n                                                 , 32*1024\n                                                 ), false);\n\n        daemon.setChannel(this, getInputStream(), out);\n        daemon.setArg(_config.arg);\n        new Thread(daemon).start();\n      }\n      else{\n        ConfigLHost _config = (ConfigLHost)config;\n        socket=(_config.factory==null) ? \n           Util.createSocket(_config.target, _config.lport, TIMEOUT) : \n          _config.factory.createSocket(_config.target, _config.lport);\n        socket.setTcpNoDelay(true);\n        io.setInputStream(socket.getInputStream());\n        io.setOutputStream(socket.getOutputStream());\n      }\n      sendOpenConfirmation();\n    }\n    catch(Exception e){\n      sendOpenFailure(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED);\n      close=true;\n      disconnect();\n      return; \n    }\n\n    thread=Thread.currentThread();\n    Buffer buf=new Buffer(rmpsize);\n    Packet packet=new Packet(buf);\n    int i=0;\n    try{\n      Session _session = getSession();\n      while(thread!=null && \n            io!=null && \n            io.in!=null){\n        i=io.in.read(buf.buffer, \n                     14, \n                     buf.buffer.length-14\n                     -Session.buffer_margin\n                     );\n        if(i<=0){\n          eof();\n          break;\n        }\n        packet.reset();\n        buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);\n        buf.putInt(recipient);\n        buf.putInt(i);\n        buf.skip(i);\n        synchronized(this){\n          if(close)\n            break;\n          _session.write(packet, this, i);\n        }\n      }\n    }\n    catch(Exception e){\n      //System.err.println(e);\n    }\n    //thread=null;\n    //eof();\n    disconnect();\n  }\n\n  void getData(Buffer buf){\n    setRecipient(buf.getInt());\n    setRemoteWindowSize(buf.getUInt());\n    setRemotePacketSize(buf.getInt());\n    byte[] addr=buf.getString();\n    int port=buf.getInt();\n    byte[] orgaddr=buf.getString();\n    int orgport=buf.getInt();\n\n    /*\n    System.err.println(\"addr: \"+Util.byte2str(addr));\n    System.err.println(\"port: \"+port);\n    System.err.println(\"orgaddr: \"+Util.byte2str(orgaddr));\n    System.err.println(\"orgport: \"+orgport);\n    */\n\n    Session _session=null;\n    try{\n      _session=getSession();\n    }\n    catch(JSchException e){\n      // session has been already down.\n    }\n\n    this.config = getPort(_session, Util.byte2str(addr), port);\n    if(this.config == null)\n      this.config = getPort(_session, null, port);\n\n    if(this.config == null){\n      if(JSch.getLogger().isEnabled(Logger.ERROR)){\n        JSch.getLogger().log(Logger.ERROR, \n                             \"ChannelForwardedTCPIP: \"+Util.byte2str(addr)+\":\"+port+\" is not registered.\");\n      }\n    }\n  }\n\n  private static Config getPort(Session session, String address_to_bind, int rport){\n    synchronized(pool){\n      for(int i=0; i<pool.size(); i++){\n        Config bar = (Config)(pool.elementAt(i));\n        if(bar.session != session) continue;\n        if(bar.rport != rport) {\n          if(bar.rport != 0 || bar.allocated_rport != rport)\n            continue;\n        }\n        if(address_to_bind != null &&\n           !bar.address_to_bind.equals(address_to_bind)) continue;\n        return bar;\n      }\n      return null;\n    }\n  }\n\n  static String[] getPortForwarding(Session session){\n    Vector foo = new Vector();\n    synchronized(pool){\n      for(int i=0; i<pool.size(); i++){\n        Config config = (Config)(pool.elementAt(i));\n        if(config instanceof ConfigDaemon)\n          foo.addElement(config.allocated_rport+\":\"+config.target+\":\");\n        else\n          foo.addElement(config.allocated_rport+\":\"+config.target+\":\"+((ConfigLHost)config).lport);\n      }\n    }\n    String[] bar=new String[foo.size()];\n    for(int i=0; i<foo.size(); i++){\n      bar[i]=(String)(foo.elementAt(i));\n    }\n    return bar;\n  }\n\n  static String normalize(String address){\n    if(address==null){ return \"localhost\"; }\n    else if(address.length()==0 || address.equals(\"*\")){ return \"\"; }\n    else{ return address; }\n  }\n\n  static void addPort(Session session, String _address_to_bind,\n                      int port, int allocated_port, String target, int lport, SocketFactory factory) throws JSchException{\n    String address_to_bind=normalize(_address_to_bind);\n    synchronized(pool){\n      if(getPort(session, address_to_bind, port)!=null){\n        throw new JSchException(\"PortForwardingR: remote port \"+port+\" is already registered.\");\n      }\n      ConfigLHost config = new ConfigLHost();\n      config.session = session;\n      config.rport = port;\n      config.allocated_rport = allocated_port;\n      config.target = target;\n      config.lport =lport;\n      config.address_to_bind = address_to_bind;\n      config.factory = factory;\n      pool.addElement(config);\n    }\n  }\n  static void addPort(Session session, String _address_to_bind,\n                      int port, int allocated_port, String daemon, Object[] arg) throws JSchException{\n    String address_to_bind=normalize(_address_to_bind);\n    synchronized(pool){\n      if(getPort(session, address_to_bind, port)!=null){\n        throw new JSchException(\"PortForwardingR: remote port \"+port+\" is already registered.\");\n      }\n      ConfigDaemon config = new ConfigDaemon();\n      config.session = session;\n      config.rport = port;\n      config.allocated_rport = port;\n      config.target = daemon;\n      config.arg = arg;\n      config.address_to_bind = address_to_bind;\n      pool.addElement(config);\n    }\n  }\n  static void delPort(ChannelForwardedTCPIP c){\n    Session _session=null;\n    try{\n      _session=c.getSession();\n    }\n    catch(JSchException e){\n      // session has been already down.\n    }\n    if(_session!=null && c.config!=null)\n      delPort(_session, c.config.rport);\n  }\n  static void delPort(Session session, int rport){\n    delPort(session, null, rport);\n  }\n  static void delPort(Session session, String address_to_bind, int rport){\n    synchronized(pool){\n      Config foo = getPort(session, normalize(address_to_bind), rport);\n      if(foo == null)\n        foo = getPort(session, null, rport);\n      if(foo==null) return;\n      pool.removeElement(foo);\n      if(address_to_bind==null){\n        address_to_bind=foo.address_to_bind;\n      }\t\n      if(address_to_bind==null){\n        address_to_bind=\"0.0.0.0\";\n      }\n    }\n\n    Buffer buf=new Buffer(100); // ??\n    Packet packet=new Packet(buf);\n\n    try{\n      // byte SSH_MSG_GLOBAL_REQUEST 80\n      // string \"cancel-tcpip-forward\"\n      // boolean want_reply\n      // string  address_to_bind (e.g. \"127.0.0.1\")\n      // uint32  port number to bind\n      packet.reset();\n      buf.putByte((byte) 80/*SSH_MSG_GLOBAL_REQUEST*/);\n      buf.putString(Util.str2byte(\"cancel-tcpip-forward\"));\n      buf.putByte((byte)0);\n      buf.putString(Util.str2byte(address_to_bind));\n      buf.putInt(rport);\n      session.write(packet);\n    }\n    catch(Exception e){\n//    throw new JSchException(e.toString());\n    }\n  }\n  static void delPort(Session session){\n    int[] rport=null;\n    int count=0;\n    synchronized(pool){\n      rport=new int[pool.size()];\n      for(int i=0; i<pool.size(); i++){\n        Config config = (Config)(pool.elementAt(i));\n        if(config.session == session) {\n          rport[count++]=config.rport; // ((Integer)bar[1]).intValue();\n        }\n      }\n    }\n    for(int i=0; i<count; i++){\n      delPort(session, rport[i]);\n    }\n  }\n\n  public int getRemotePort(){return (config!=null ? config.rport: 0);}\n  private void setSocketFactory(SocketFactory factory){\n    if(config!=null && (config instanceof ConfigLHost) )\n      ((ConfigLHost)config).factory = factory;\n  }\n  static abstract class Config {\n    Session session;\n    int rport;\n    int allocated_rport;\n    String address_to_bind;\n    String target;\n  }\n\n  static class ConfigDaemon extends Config {\n    Object[] arg;\n  }\n\n  static class ConfigLHost extends Config {\n    int lport;\n    SocketFactory factory;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ChannelSession.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.util.*;\n\nclass ChannelSession extends Channel{\n  private static byte[] _session=Util.str2byte(\"session\");\n\n  protected boolean agent_forwarding=false;\n  protected boolean xforwading=false;\n  protected Hashtable env=null;\n\n  protected boolean pty=false;\n\n  protected String ttype=\"vt100\";\n  protected int tcol=80;\n  protected int trow=24;\n  protected int twp=640;\n  protected int thp=480;\n  protected byte[] terminal_mode=null;\n\n  ChannelSession(){\n    super();\n    type=_session;\n    io=new IO();\n  }\n\n  /**\n   * Enable the agent forwarding.\n   *\n   * @param enable\n   */\n  public void setAgentForwarding(boolean enable){ \n    agent_forwarding=enable;\n  }\n\n  /**\n   * Enable the X11 forwarding.\n   * Refer to RFC4254 6.3.1. Requesting X11 Forwarding.\n   *\n   * @param enable\n   */\n  public void setXForwarding(boolean enable){\n    xforwading=enable; \n  }\n\n  /**\n   * @deprecated Use {@link #setEnv(String, String)} or {@link #setEnv(byte[], byte[])} instead.\n   * @see #setEnv(String, String)\n   * @see #setEnv(byte[], byte[])\n   */\n  public void setEnv(Hashtable env){ \n    synchronized(this){\n      this.env=env; \n    }\n  }\n\n  /**\n   * Set the environment variable. \n   * If <code>name</code> and <code>value</code> are needed to be passed \n   * to the remote in your favorite encoding,\n   * use {@link #setEnv(byte[], byte[])}.\n   * Refer to RFC4254 6.4 Environment Variable Passing.\n   *\n   * @param name A name for environment variable.\n   * @param value A value for environment variable.\n   */\n  public void setEnv(String name, String value){\n    setEnv(Util.str2byte(name), Util.str2byte(value));\n  }\n\n  /**\n   * Set the environment variable.\n   * Refer to RFC4254 6.4 Environment Variable Passing.\n   *\n   * @param name A name of environment variable.\n   * @param value A value of environment variable.\n   * @see #setEnv(String, String)\n   */\n  public void setEnv(byte[] name, byte[] value){\n    synchronized(this){\n      getEnv().put(name, value);\n    }\n  }\n\n  private Hashtable getEnv(){\n    if(env==null)\n      env=new Hashtable();\n    return env;\n  }\n\n  /**\n   * Allocate a Pseudo-Terminal.\n   * Refer to RFC4254 6.2. Requesting a Pseudo-Terminal.\n   *\n   * @param enable\n   */\n  public void setPty(boolean enable){ \n    pty=enable; \n  }\n\n  /**\n   * Set the terminal mode.\n   * \n   * @param terminal_mode\n   */\n  public void setTerminalMode(byte[] terminal_mode){\n    this.terminal_mode=terminal_mode;\n  }\n\n  /**\n   * Change the window dimension interactively.\n   * Refer to RFC4254 6.7. Window Dimension Change Message.\n   *\n   * @param col terminal width, columns\n   * @param row terminal height, rows\n   * @param wp terminal width, pixels\n   * @param hp terminal height, pixels\n   */\n  public void setPtySize(int col, int row, int wp, int hp){\n    setPtyType(this.ttype, col, row, wp, hp);\n    if(!pty || !isConnected()){\n      return;\n    }\n    try{\n      RequestWindowChange request=new RequestWindowChange();\n      request.setSize(col, row, wp, hp);\n      request.request(getSession(), this);\n    }\n    catch(Exception e){\n      //System.err.println(\"ChannelSessio.setPtySize: \"+e);\n    }\n  }\n\n  /**\n   * Set the terminal type.\n   * This method is not effective after Channel#connect().\n   *\n   * @param ttype terminal type(for example, \"vt100\")\n   * @see #setPtyType(String, int, int, int, int)\n   */\n  public void setPtyType(String ttype){\n    setPtyType(ttype, 80, 24, 640, 480);\n  }\n\n  /**\n   * Set the terminal type.\n   * This method is not effective after Channel#connect().\n   *\n   * @param ttype terminal type(for example, \"vt100\")\n   * @param col terminal width, columns\n   * @param row terminal height, rows\n   * @param wp terminal width, pixels\n   * @param hp terminal height, pixels\n   */\n  public void setPtyType(String ttype, int col, int row, int wp, int hp){\n    this.ttype=ttype;\n    this.tcol=col;\n    this.trow=row;\n    this.twp=wp;\n    this.thp=hp;\n  }\n\n  protected void sendRequests() throws Exception{\n    Session _session=getSession();\n    Request request;\n    if(agent_forwarding){\n      request=new RequestAgentForwarding();\n      request.request(_session, this);\n    }\n\n    if(xforwading){\n      request=new RequestX11();\n      request.request(_session, this);\n    }\n\n    if(pty){\n      request=new RequestPtyReq();\n      ((RequestPtyReq)request).setTType(ttype);\n      ((RequestPtyReq)request).setTSize(tcol, trow, twp, thp);\n      if(terminal_mode!=null){\n        ((RequestPtyReq)request).setTerminalMode(terminal_mode);\n      }\n      request.request(_session, this);\n    }\n\n    if(env!=null){\n      for(Enumeration _env=env.keys(); _env.hasMoreElements();){\n        Object name=_env.nextElement();\n        Object value=env.get(name);\n        request=new RequestEnv();\n        ((RequestEnv)request).setEnv(toByteArray(name), \n                                     toByteArray(value));\n        request.request(_session, this);\n      }\n    }\n  }\n\n  private byte[] toByteArray(Object o){\n    if(o instanceof String){\n      return Util.str2byte((String)o);\n    }\n    return (byte[])o;\n  }\n\n  public void run(){\n    //System.err.println(this+\":run >\");\n\n    Buffer buf=new Buffer(rmpsize);\n    Packet packet=new Packet(buf);\n    int i=-1;\n    try{\n      while(isConnected() &&\n\t    thread!=null && \n            io!=null && \n            io.in!=null){\n        i=io.in.read(buf.buffer, \n                     14,    \n                     buf.buffer.length-14\n                     -Session.buffer_margin\n\t\t     );\n\tif(i==0)continue;\n\tif(i==-1){\n\t  eof();\n\t  break;\n\t}\n\tif(close)break;\n        //System.out.println(\"write: \"+i);\n        packet.reset();\n        buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);\n        buf.putInt(recipient);\n        buf.putInt(i);\n        buf.skip(i);\n\tgetSession().write(packet, this, i);\n      }\n    }\n    catch(Exception e){\n      //System.err.println(\"# ChannelExec.run\");\n      //e.printStackTrace();\n    }\n    Thread _thread=thread; \n    if(_thread!=null){\n      synchronized(_thread){ _thread.notifyAll(); }\n    }\n    thread=null;\n    //System.err.println(this+\":run <\");\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ChannelSftp.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.*;\n\nimport java.util.Vector;\n\npublic class ChannelSftp extends ChannelSession{\n\n  static private final int LOCAL_MAXIMUM_PACKET_SIZE=32*1024;\n  static private final int LOCAL_WINDOW_SIZE_MAX=(64*LOCAL_MAXIMUM_PACKET_SIZE);\n\n  private static final byte SSH_FXP_INIT=               1;\n  private static final byte SSH_FXP_VERSION=            2;\n  private static final byte SSH_FXP_OPEN=               3;\n  private static final byte SSH_FXP_CLOSE=              4;\n  private static final byte SSH_FXP_READ=               5;\n  private static final byte SSH_FXP_WRITE=              6;\n  private static final byte SSH_FXP_LSTAT=              7;\n  private static final byte SSH_FXP_FSTAT=              8;\n  private static final byte SSH_FXP_SETSTAT=            9;\n  private static final byte SSH_FXP_FSETSTAT=          10;\n  private static final byte SSH_FXP_OPENDIR=           11;\n  private static final byte SSH_FXP_READDIR=           12;\n  private static final byte SSH_FXP_REMOVE=            13;\n  private static final byte SSH_FXP_MKDIR=             14;\n  private static final byte SSH_FXP_RMDIR=             15;\n  private static final byte SSH_FXP_REALPATH=          16;\n  private static final byte SSH_FXP_STAT=              17;\n  private static final byte SSH_FXP_RENAME=            18;\n  private static final byte SSH_FXP_READLINK=          19;\n  private static final byte SSH_FXP_SYMLINK=           20;\n  private static final byte SSH_FXP_STATUS=           101;\n  private static final byte SSH_FXP_HANDLE=           102;\n  private static final byte SSH_FXP_DATA=             103;\n  private static final byte SSH_FXP_NAME=             104;\n  private static final byte SSH_FXP_ATTRS=            105;\n  private static final byte SSH_FXP_EXTENDED=         (byte)200;\n  private static final byte SSH_FXP_EXTENDED_REPLY=   (byte)201;\n\n  // pflags\n  private static final int SSH_FXF_READ=           0x00000001;\n  private static final int SSH_FXF_WRITE=          0x00000002;\n  private static final int SSH_FXF_APPEND=         0x00000004;\n  private static final int SSH_FXF_CREAT=          0x00000008;\n  private static final int SSH_FXF_TRUNC=          0x00000010;\n  private static final int SSH_FXF_EXCL=           0x00000020;\n\n  private static final int SSH_FILEXFER_ATTR_SIZE=         0x00000001;\n  private static final int SSH_FILEXFER_ATTR_UIDGID=       0x00000002;\n  private static final int SSH_FILEXFER_ATTR_PERMISSIONS=  0x00000004;\n  private static final int SSH_FILEXFER_ATTR_ACMODTIME=    0x00000008;\n  private static final int SSH_FILEXFER_ATTR_EXTENDED=     0x80000000;\n\n  public static final int SSH_FX_OK=                            0;\n  public static final int SSH_FX_EOF=                           1;\n  public static final int SSH_FX_NO_SUCH_FILE=                  2;\n  public static final int SSH_FX_PERMISSION_DENIED=             3;\n  public static final int SSH_FX_FAILURE=                       4;\n  public static final int SSH_FX_BAD_MESSAGE=                   5;\n  public static final int SSH_FX_NO_CONNECTION=                 6;\n  public static final int SSH_FX_CONNECTION_LOST=               7;\n  public static final int SSH_FX_OP_UNSUPPORTED=                8;\n/*\n   SSH_FX_OK\n      Indicates successful completion of the operation.\n   SSH_FX_EOF\n     indicates end-of-file condition; for SSH_FX_READ it means that no\n       more data is available in the file, and for SSH_FX_READDIR it\n      indicates that no more files are contained in the directory.\n   SSH_FX_NO_SUCH_FILE\n      is returned when a reference is made to a file which should exist\n      but doesn't.\n   SSH_FX_PERMISSION_DENIED\n      is returned when the authenticated user does not have sufficient\n      permissions to perform the operation.\n   SSH_FX_FAILURE\n      is a generic catch-all error message; it should be returned if an\n      error occurs for which there is no more specific error code\n      defined.\n   SSH_FX_BAD_MESSAGE\n      may be returned if a badly formatted packet or protocol\n      incompatibility is detected.\n   SSH_FX_NO_CONNECTION\n      is a pseudo-error which indicates that the client has no\n      connection to the server (it can only be generated locally by the\n      client, and MUST NOT be returned by servers).\n   SSH_FX_CONNECTION_LOST\n      is a pseudo-error which indicates that the connection to the\n      server has been lost (it can only be generated locally by the\n      client, and MUST NOT be returned by servers).\n   SSH_FX_OP_UNSUPPORTED\n      indicates that an attempt was made to perform an operation which\n      is not supported for the server (it may be generated locally by\n      the client if e.g.  the version number exchange indicates that a\n      required feature is not supported by the server, or it may be\n      returned by the server if the server does not implement an\n      operation).\n*/\n  private static final int MAX_MSG_LENGTH = 256* 1024;\n\n  public static final int OVERWRITE=0;\n  public static final int RESUME=1;\n  public static final int APPEND=2;\n\n  private boolean interactive=false;\n  private int seq=1;\n  private int[] ackid=new int[1];\n\n  private Buffer buf;\n  private Packet packet;\n\n  // The followings will be used in file uploading.\n  private Buffer obuf;\n  private Packet opacket;\n\n  private int client_version=3;\n  private int server_version=3;\n  private String version=String.valueOf(client_version);\n\n  private java.util.Hashtable extensions=null;\n  private InputStream io_in=null;\n\n  private boolean extension_posix_rename = false;\n  private boolean extension_statvfs = false;\n  // private boolean extension_fstatvfs = false;\n  private boolean extension_hardlink = false;\n\n/*\n10. Changes from previous protocol versions\n  The SSH File Transfer Protocol has changed over time, before it's\n   standardization.  The following is a description of the incompatible\n   changes between different versions.\n10.1 Changes between versions 3 and 2\n   o  The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.\n   o  The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were added.\n   o  The SSH_FXP_STATUS message was changed to include fields `error\n      message' and `language tag'.\n10.2 Changes between versions 2 and 1\n   o  The SSH_FXP_RENAME message was added.\n10.3 Changes between versions 1 and 0\n   o  Implementation changes, no actual protocol changes.\n*/\n\n  private static final String file_separator=java.io.File.separator;\n  private static final char file_separatorc=java.io.File.separatorChar;\n  private static boolean fs_is_bs=(byte)java.io.File.separatorChar == '\\\\';\n\n  private String cwd;\n  private String home;\n  private String lcwd;\n\n  private static final String UTF8=\"UTF-8\";\n  private String fEncoding=UTF8;\n  private boolean fEncoding_is_utf8=true;\n\n  private RequestQueue rq = new RequestQueue(16);\n\n  /**\n   * Specify how many requests may be sent at any one time.\n   * Increasing this value may slightly improve file transfer speed but will\n   * increase memory usage.  The default is 16 requests.\n   *\n   * @param bulk_requests how many requests may be outstanding at any one time.\n   */\n  public void setBulkRequests(int bulk_requests) throws JSchException {\n    if(bulk_requests>0) \n      rq = new RequestQueue(bulk_requests);\n    else \n      throw new JSchException(\"setBulkRequests: \"+ \n                              bulk_requests+\" must be greater than 0.\");\n  }\n\n  /**\n   * This method will return the value how many requests may be\n   * sent at any one time.\n   *\n   * @return how many requests may be sent at any one time.\n   */\n  public int getBulkRequests(){\n    return rq.size();\n  }\n\n  public ChannelSftp(){\n    super();\n    setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX);\n    setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX);\n    setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE);\n  }\n\n  void init(){\n  }\n\n  public void start() throws JSchException{\n    try{\n\n      PipedOutputStream pos=new PipedOutputStream();\n      io.setOutputStream(pos);\n      PipedInputStream pis=new MyPipedInputStream(pos, rmpsize);\n      io.setInputStream(pis);\n\n      io_in=io.in;\n\n      if(io_in==null){\n        throw new JSchException(\"channel is down\");\n      }\n\n      Request request=new RequestSftp();\n      request.request(getSession(), this);\n\n      /*\n      System.err.println(\"lmpsize: \"+lmpsize);\n      System.err.println(\"lwsize: \"+lwsize);\n      System.err.println(\"rmpsize: \"+rmpsize);\n      System.err.println(\"rwsize: \"+rwsize);\n      */\n\n      buf=new Buffer(lmpsize);\n      packet=new Packet(buf);\n\n      obuf=new Buffer(rmpsize);\n      opacket=new Packet(obuf);\n\n      int i=0;\n      int length;\n      int type;\n      byte[] str;\n\n      // send SSH_FXP_INIT\n      sendINIT();\n\n      // receive SSH_FXP_VERSION\n      Header header=new Header();\n      header=header(buf, header);\n      length=header.length;\n      if(length > MAX_MSG_LENGTH){\n        throw new SftpException(SSH_FX_FAILURE, \n                                \"Received message is too long: \" + length);\n      }\n      type=header.type;             // 2 -> SSH_FXP_VERSION\n      server_version=header.rid;\n      //System.err.println(\"SFTP protocol server-version=\"+server_version);\n      extensions=new java.util.Hashtable();\n      if(length>0){\n        // extension data\n        fill(buf, length);\n        byte[] extension_name=null;\n        byte[] extension_data=null;\n        while(length>0){\n          extension_name=buf.getString();\n          length-=(4+extension_name.length);\n          extension_data=buf.getString();\n          length-=(4+extension_data.length);\n          extensions.put(Util.byte2str(extension_name),\n                         Util.byte2str(extension_data));\n        }\n      }\n\n      if(extensions.get(\"posix-rename@openssh.com\")!=null &&\n         extensions.get(\"posix-rename@openssh.com\").equals(\"1\")){\n        extension_posix_rename = true;\n      } \n\n      if(extensions.get(\"statvfs@openssh.com\")!=null &&\n         extensions.get(\"statvfs@openssh.com\").equals(\"2\")){\n        extension_statvfs = true;\n      } \n\n      /*\n      if(extensions.get(\"fstatvfs@openssh.com\")!=null &&\n         extensions.get(\"fstatvfs@openssh.com\").equals(\"2\")){\n        extension_fstatvfs = true;\n      } \n      */\n\n      if(extensions.get(\"hardlink@openssh.com\")!=null &&\n         extensions.get(\"hardlink@openssh.com\").equals(\"1\")){\n        extension_hardlink = true;\n      } \n\n      lcwd=new File(\".\").getCanonicalPath();\n    }\n    catch(Exception e){\n      //System.err.println(e);\n      if(e instanceof JSchException) throw (JSchException)e;\n      if(e instanceof Throwable)\n        throw new JSchException(e.toString(), (Throwable)e);\n      throw new JSchException(e.toString());\n    }\n  }\n\n  public void quit(){ disconnect();}\n  public void exit(){ disconnect();}\n  public void lcd(String path) throws SftpException{\n    path=localAbsolutePath(path);\n    if((new File(path)).isDirectory()){\n      try{\n\tpath=(new File(path)).getCanonicalPath();\n      }\n      catch(Exception e){}\n      lcwd=path;\n      return;\n    }\n    throw new SftpException(SSH_FX_NO_SUCH_FILE, \"No such directory\");\n  }\n\n  public void cd(String path) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n      path=isUnique(path);\n\n      byte[] str=_realpath(path);\n      SftpATTRS attr=_stat(str);\n\n      if((attr.getFlags()&SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS)==0){\n        throw new SftpException(SSH_FX_FAILURE, \n                                \"Can't change directory: \"+path);\n      }\n      if(!attr.isDir()){\n        throw new SftpException(SSH_FX_FAILURE, \n                                \"Can't change directory: \"+path);\n      }\n\n      setCwd(Util.byte2str(str, fEncoding));\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  public void put(String src, String dst) throws SftpException{\n    put(src, dst, null, OVERWRITE);\n  }\n  public void put(String src, String dst, int mode) throws SftpException{\n    put(src, dst, null, mode);\n  }\n  public void put(String src, String dst, \n\t\t  SftpProgressMonitor monitor) throws SftpException{\n    put(src, dst, monitor, OVERWRITE);\n  }\n\n  /**\n   * Sends data from <code>src</code> file to <code>dst</code> file.\n   * The <code>mode</code> should be <code>OVERWRITE</code>,\n   * <code>RESUME</code> or <code>APPEND</code>.\n   *\n   * @param src source file\n   * @param dst destination file\n   * @param monitor progress monitor\n   * @param mode how data should be added to dst\n   */\n  public void put(String src, String dst, \n\t\t  SftpProgressMonitor monitor, int mode) throws SftpException{\n\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      src=localAbsolutePath(src);\n      dst=remoteAbsolutePath(dst);\n\n      Vector v=glob_remote(dst);\n      int vsize=v.size();\n      if(vsize!=1){\n        if(vsize==0){\n          if(isPattern(dst))\n            throw new SftpException(SSH_FX_FAILURE, dst);\n          else\n            dst=Util.unquote(dst);\n        }\n        throw new SftpException(SSH_FX_FAILURE, v.toString());\n      }\n      else{\n        dst=(String)(v.elementAt(0));\n      }\n\n      boolean isRemoteDir=isRemoteDir(dst);\n\n      v=glob_local(src);\n      vsize=v.size();\n\n      StringBuffer dstsb=null;\n      if(isRemoteDir){\n        if(!dst.endsWith(\"/\")){\n\t    dst+=\"/\";\n        }\n        dstsb=new StringBuffer(dst);\n      }\n      else if(vsize>1){\n        throw new SftpException(SSH_FX_FAILURE, \n                                \"Copying multiple files, but the destination is missing or a file.\");\n      }\n\n      for(int j=0; j<vsize; j++){\n\tString _src=(String)(v.elementAt(j));\n\tString _dst=null;\n\tif(isRemoteDir){\n\t  int i=_src.lastIndexOf(file_separatorc);\n          if(fs_is_bs){\n            int ii=_src.lastIndexOf('/');\n            if(ii!=-1 && ii>i)\n              i=ii; \n          }\n\t  if(i==-1) dstsb.append(_src);\n\t  else dstsb.append(_src.substring(i + 1));\n          _dst=dstsb.toString();\n          dstsb.delete(dst.length(), _dst.length());\n\t}\n        else{\n          _dst=dst;\n        }\n        //System.err.println(\"_dst \"+_dst);\n\n\tlong size_of_dst=0;\n\tif(mode==RESUME){\n\t  try{\n\t    SftpATTRS attr=_stat(_dst);\n\t    size_of_dst=attr.getSize();\n\t  }\n\t  catch(Exception eee){\n\t    //System.err.println(eee);\n\t  }\n\t  long size_of_src=new File(_src).length();\n\t  if(size_of_src<size_of_dst){\n\t    throw new SftpException(SSH_FX_FAILURE, \n                                    \"failed to resume for \"+_dst);\n\t  }\n\t  if(size_of_src==size_of_dst){\n\t    return;\n\t  }\n\t}\n\n        if(monitor!=null){\n \t  monitor.init(SftpProgressMonitor.PUT, _src, _dst,\n\t\t       (new File(_src)).length());\n\t  if(mode==RESUME){\n\t    monitor.count(size_of_dst);\n\t  }\n        }\n\tFileInputStream fis=null;\n\ttry{\n\t  fis=new FileInputStream(_src);\n\t  _put(fis, _dst, monitor, mode);\n\t}\n\tfinally{\n\t  if(fis!=null) {\n\t    fis.close();\n\t  }\n\t}\n      }\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, e.toString());\n    }\n  }\n  public void put(InputStream src, String dst) throws SftpException{\n    put(src, dst, null, OVERWRITE);\n  }\n  public void put(InputStream src, String dst, int mode) throws SftpException{\n    put(src, dst, null, mode);\n  }\n  public void put(InputStream src, String dst, \n\t\t  SftpProgressMonitor monitor) throws SftpException{\n    put(src, dst, monitor, OVERWRITE);\n  }\n\n  /**\n   * Sends data from the input stream <code>src</code> to <code>dst</code> file.\n   * The <code>mode</code> should be <code>OVERWRITE</code>,\n   * <code>RESUME</code> or <code>APPEND</code>.\n   *\n   * @param src input stream\n   * @param dst destination file\n   * @param monitor progress monitor\n   * @param mode how data should be added to dst\n   */\n  public void put(InputStream src, String dst, \n\t\t  SftpProgressMonitor monitor, int mode) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      dst=remoteAbsolutePath(dst);\n\n      Vector v=glob_remote(dst);\n      int vsize=v.size();\n      if(vsize!=1){\n        if(vsize==0){\n          if(isPattern(dst))\n            throw new SftpException(SSH_FX_FAILURE, dst);\n          else\n            dst=Util.unquote(dst);\n        }\n        throw new SftpException(SSH_FX_FAILURE, v.toString());\n      }\n      else{\n        dst=(String)(v.elementAt(0));\n      }\n\n      if(monitor!=null){\n        monitor.init(SftpProgressMonitor.PUT, \n                     \"-\", dst,\n                     SftpProgressMonitor.UNKNOWN_SIZE);\n      }\n\n      _put(src, dst, monitor, mode);\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) {\n        if(((SftpException)e).id == SSH_FX_FAILURE &&\n           isRemoteDir(dst)) {\n          throw new SftpException(SSH_FX_FAILURE, dst+\" is a directory\");\n        }\n        throw (SftpException)e;\n      }\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, e.toString());\n    }\n  }\n\n  public void _put(InputStream src, String dst, \n                   SftpProgressMonitor monitor, int mode) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      byte[] dstb=Util.str2byte(dst, fEncoding);\n      long skip=0;\n      if(mode==RESUME || mode==APPEND){\n\ttry{\n\t  SftpATTRS attr=_stat(dstb);\n\t  skip=attr.getSize();\n\t}\n\tcatch(Exception eee){\n\t  //System.err.println(eee);\n\t}\n      }\n      if(mode==RESUME && skip>0){\n\tlong skipped=src.skip(skip);\n\tif(skipped<skip){\n\t  throw new SftpException(SSH_FX_FAILURE, \"failed to resume for \"+dst);\n\t}\n      }\n\n      if(mode==OVERWRITE){ sendOPENW(dstb); }\n      else{ sendOPENA(dstb); }\n\n      Header header=new Header();\n      header=header(buf, header);\n      int length=header.length;\n      int type=header.type;\n\n      fill(buf, length);\n\n      if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){\n\tthrow new SftpException(SSH_FX_FAILURE, \"invalid type=\"+type);\n      }\n      if(type==SSH_FXP_STATUS){\n        int i=buf.getInt();\n        throwStatusError(buf, i);\n      }\n      byte[] handle=buf.getString();         // handle\n      byte[] data=null;\n\n      boolean dontcopy=true;\n\n      if(!dontcopy){  // This case will not work anymore.\n        data=new byte[obuf.buffer.length\n                      -(5+13+21+handle.length+Session.buffer_margin\n                        )\n        ];\n      }\n\n      long offset=0;\n      if(mode==RESUME || mode==APPEND){\n\toffset+=skip;\n      }\n\n      int startid=seq;\n      int ackcount=0;\n      int _s=0;\n      int _datalen=0;\n\n      if(!dontcopy){  // This case will not work anymore.\n        _datalen=data.length;\n      }\n      else{\n        data=obuf.buffer;\n        _s=5+13+21+handle.length;\n        _datalen=obuf.buffer.length-_s-Session.buffer_margin;\n      }\n\n      int bulk_requests = rq.size();\n\n      while(true){\n        int nread=0;\n        int count=0;\n        int s=_s;\n        int datalen=_datalen;\n\n        do{\n          nread=src.read(data, s, datalen);\n          if(nread>0){\n            s+=nread;\n            datalen-=nread;\n            count+=nread;\n          }\n        }\n        while(datalen>0 && nread>0); \n        if(count<=0)break;\n\n        int foo=count;\n        while(foo>0){\n          if((seq-1)==startid ||\n             ((seq-startid)-ackcount)>=bulk_requests){\n            while(((seq-startid)-ackcount)>=bulk_requests){\n              if(checkStatus(ackid, header)){\n                int _ackid = ackid[0];\n                if(startid>_ackid || _ackid>seq-1){\n                  if(_ackid==seq){\n                    System.err.println(\"ack error: startid=\"+startid+\" seq=\"+seq+\" _ackid=\"+_ackid);\n                  } \n                  else{\n                    throw new SftpException(SSH_FX_FAILURE, \"ack error: startid=\"+startid+\" seq=\"+seq+\" _ackid=\"+_ackid);\n                  }\n                }\n                ackcount++;\n              }\n              else{\n                break;\n              }\n            }\n          }\n          foo-=sendWRITE(handle, offset, data, 0, foo);\n        }\n        offset+=count;\n\tif(monitor!=null && !monitor.count(count)){\n          break;\n\t}\n      }\n      int _ackcount=seq-startid;\n      while(_ackcount>ackcount){\n        if(!checkStatus(null, header)){\n          break;\n        }\n        ackcount++;\n      }\n      if(monitor!=null)monitor.end();\n      _sendCLOSE(handle, header);\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, e.toString());\n    }\n  }\n\n  public OutputStream put(String dst) throws SftpException{\n    return put(dst, (SftpProgressMonitor)null, OVERWRITE);\n  }\n  public OutputStream put(String dst, final int mode) throws SftpException{\n    return put(dst, (SftpProgressMonitor)null, mode);\n  }\n  public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode) throws SftpException{\n    return put(dst, monitor, mode, 0);\n  }\n\n  /**\n   * Sends data from the output stream to <code>dst</code> file.\n   * The <code>mode</code> should be <code>OVERWRITE</code>,\n   * <code>RESUME</code> or <code>APPEND</code>.\n   *\n   * @param dst destination file\n   * @param monitor progress monitor\n   * @param mode how data should be added to dst\n   * @param offset data will be added at offset\n   * @return output stream, which accepts data to be transferred.\n   */\n  public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode, long offset) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      dst=remoteAbsolutePath(dst);\n      dst=isUnique(dst);\n\n      if(isRemoteDir(dst)){\n\tthrow new SftpException(SSH_FX_FAILURE, dst+\" is a directory\");\n      }\n\n      byte[] dstb=Util.str2byte(dst, fEncoding);\n\n      long skip=0;\n      if(mode==RESUME || mode==APPEND){\n\ttry{\n\t  SftpATTRS attr=_stat(dstb);\n\t  skip=attr.getSize();\n\t}\n\tcatch(Exception eee){\n\t  //System.err.println(eee);\n\t}\n      }\n\n      if(mode==OVERWRITE){ sendOPENW(dstb); }\n      else{ sendOPENA(dstb); }\n\n      Header header=new Header();\n      header=header(buf, header);\n      int length=header.length;\n      int type=header.type;\n\n      fill(buf, length);\n\n      if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){\n\tthrow new SftpException(SSH_FX_FAILURE, \"\");\n      }\n      if(type==SSH_FXP_STATUS){\n        int i=buf.getInt();\n        throwStatusError(buf, i);\n      }\n      final byte[] handle=buf.getString();         // handle\n\n      if(mode==RESUME || mode==APPEND){\n\toffset+=skip;\n      }\n\n      final long[] _offset=new long[1];\n      _offset[0]=offset;\n      OutputStream out = new OutputStream(){\n        private boolean init=true;\n        private boolean isClosed=false;\n        private int[] ackid=new int[1];\n        private int startid=0;\n        private int _ackid=0;\n        private int ackcount=0;\n        private int writecount=0;\n        private Header header=new Header();          \n\n        public void write(byte[] d) throws java.io.IOException{\n          write(d, 0, d.length);\n        }\n\n        public void write(byte[] d, int s, int len) throws java.io.IOException{\n          if(init){\n            startid=seq;\n            _ackid=seq;\n            init=false;\n          }\n\n          if(isClosed){\n            throw new IOException(\"stream already closed\");\n          }\n\n          try{\n            int _len=len;\n            while(_len>0){\n              int sent=sendWRITE(handle, _offset[0], d, s, _len);\n              writecount++;\n              _offset[0]+=sent;\n              s+=sent;\n              _len-=sent;\n              if((seq-1)==startid ||\n                 io_in.available()>=1024){\n                while(io_in.available()>0){\n                  if(checkStatus(ackid, header)){\n                    _ackid=ackid[0];\n                    if(startid>_ackid || _ackid>seq-1){\n                      throw new SftpException(SSH_FX_FAILURE, \"\");\n                    }\n                    ackcount++;\n                  }\n                  else{\n                    break;\n                  }\n                }\n              }\n            }\n    \t    if(monitor!=null && !monitor.count(len)){\n              close();\n              throw new IOException(\"canceled\");\n\t    }\n          }\n          catch(IOException e){ throw e; }\n          catch(Exception e){ throw new IOException(e.toString());  }\n        }\n\n        byte[] _data=new byte[1];\n        public void write(int foo) throws java.io.IOException{\n          _data[0]=(byte)foo;\n          write(_data, 0, 1);\n        }\n\n        public void flush() throws java.io.IOException{\n\n          if(isClosed){\n            throw new IOException(\"stream already closed\");\n          }\n\n          if(!init){\n            try{\n              while(writecount>ackcount){\n                if(!checkStatus(null, header)){\n                  break;\n                }\n                ackcount++;\n              }\n            }\n            catch(SftpException e){\n              throw new IOException(e.toString());\n            }\n          }\n        }\n\n        public void close() throws java.io.IOException{\n          if(isClosed){\n            return;\n          }\n          flush();\n          if(monitor!=null)monitor.end();\n          try{ _sendCLOSE(handle, header); }\n          catch(IOException e){ throw e; }\n          catch(Exception e){\n            throw new IOException(e.toString());\n          }\n          isClosed=true;\n        }\n      };\n      return out;\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  public void get(String src, String dst) throws SftpException{\n    get(src, dst, null, OVERWRITE);\n  }\n  public void get(String src, String dst,\n\t\t  SftpProgressMonitor monitor) throws SftpException{\n    get(src, dst, monitor, OVERWRITE);\n  }\n  public void get(String src, String dst,\n\t\t  SftpProgressMonitor monitor, int mode) throws SftpException{\n    // System.out.println(\"get: \"+src+\" \"+dst);\n\n    boolean _dstExist = false;\n    String _dst=null;\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      src=remoteAbsolutePath(src);\n      dst=localAbsolutePath(dst);\n\n      Vector v=glob_remote(src);\n      int vsize=v.size();\n      if(vsize==0){\n        throw new SftpException(SSH_FX_NO_SUCH_FILE, \"No such file\");\n      }\n\n      File dstFile=new File(dst);\n      boolean isDstDir=dstFile.isDirectory();\n      StringBuffer dstsb=null;\n      if(isDstDir){\n        if(!dst.endsWith(file_separator)){\n          dst+=file_separator;\n        }\n        dstsb=new StringBuffer(dst);\n      }\n      else if(vsize>1){\n        throw new SftpException(SSH_FX_FAILURE, \n                                \"Copying multiple files, but destination is missing or a file.\");\n      }\n\n      for(int j=0; j<vsize; j++){\n\tString _src=(String)(v.elementAt(j));\n\tSftpATTRS attr=_stat(_src);\n        if(attr.isDir()){\n          throw new SftpException(SSH_FX_FAILURE, \n                                  \"not supported to get directory \"+_src);\n        } \n\n\t_dst=null;\n\tif(isDstDir){\n\t  int i=_src.lastIndexOf('/');\n\t  if(i==-1) dstsb.append(_src);\n\t  else dstsb.append(_src.substring(i + 1));\n          _dst=dstsb.toString();\n          dstsb.delete(dst.length(), _dst.length());\n\t}\n        else{\n          _dst=dst;\n        }\n\n        File _dstFile=new File(_dst);\n\tif(mode==RESUME){\n\t  long size_of_src=attr.getSize();\n\t  long size_of_dst=_dstFile.length();\n\t  if(size_of_dst>size_of_src){\n\t    throw new SftpException(SSH_FX_FAILURE, \n                                    \"failed to resume for \"+_dst);\n\t  }\n\t  if(size_of_dst==size_of_src){\n\t    return;\n\t  }\n\t}\n\n\tif(monitor!=null){\n\t  monitor.init(SftpProgressMonitor.GET, _src, _dst, attr.getSize());\n\t  if(mode==RESUME){\n\t    monitor.count(_dstFile.length());\n\t  }\n\t}\n\n        FileOutputStream fos=null;\n        _dstExist = _dstFile.exists();\n        try{\n          if(mode==OVERWRITE){\n            fos=new FileOutputStream(_dst);\n          }\n          else{\n            fos=new FileOutputStream(_dst, true); // append\n          }\n          // System.err.println(\"_get: \"+_src+\", \"+_dst);\n          _get(_src, fos, monitor, mode, new File(_dst).length());\n        }\n        finally{\n          if(fos!=null){\n            fos.close();\n          }\n        }\n      }\n    }\n    catch(Exception e){\n      if(!_dstExist && _dst!=null){\n        File _dstFile = new File(_dst);\n        if(_dstFile.exists() && _dstFile.length()==0){\n          _dstFile.delete();\n        }\n      }\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n  public void get(String src, OutputStream dst) throws SftpException{\n    get(src, dst, null, OVERWRITE, 0);\n  }\n  public void get(String src, OutputStream dst,\n\t\t  SftpProgressMonitor monitor) throws SftpException{\n    get(src, dst, monitor, OVERWRITE, 0);\n  }\n  public void get(String src, OutputStream dst,\n\t\t   SftpProgressMonitor monitor, int mode, long skip) throws SftpException{\n//System.err.println(\"get: \"+src+\", \"+dst);\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      src=remoteAbsolutePath(src);\n      src=isUnique(src);\n\n      if(monitor!=null){\n\tSftpATTRS attr=_stat(src);\n        monitor.init(SftpProgressMonitor.GET, src, \"??\", attr.getSize());\n        if(mode==RESUME){\n          monitor.count(skip);\n        }\n      }\n      _get(src, dst, monitor, mode, skip);\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  private void _get(String src, OutputStream dst,\n                    SftpProgressMonitor monitor, int mode, long skip) throws SftpException{\n    //System.err.println(\"_get: \"+src+\", \"+dst);\n\n    byte[] srcb=Util.str2byte(src, fEncoding);\n    try{\n      sendOPENR(srcb);\n\n      Header header=new Header();\n      header=header(buf, header);\n      int length=header.length;\n      int type=header.type;\n\n      fill(buf, length);\n\n      if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){\n\tthrow new SftpException(SSH_FX_FAILURE, \"\");\n      }\n\n      if(type==SSH_FXP_STATUS){\n        int i=buf.getInt();\n        throwStatusError(buf, i);\n      }\n\n      byte[] handle=buf.getString();         // filename\n\n      long offset=0;\n      if(mode==RESUME){\n\toffset+=skip;\n      }\n\n      int request_max=1;\n      rq.init();\n      long request_offset=offset;\n\n      int request_len = buf.buffer.length-13;\n      if(server_version==0){ request_len=1024; }\n\n      loop:\n      while(true){\n\n        while(rq.count() < request_max){\n          sendREAD(handle, request_offset, request_len, rq);\n          request_offset += request_len;\n        }\n\n        header=header(buf, header);\n        length=header.length;\n        type=header.type;\n\n        RequestQueue.Request rr = null;\n        try{\n          rr = rq.get(header.rid);\n        }\n        catch(RequestQueue.OutOfOrderException e){\n          request_offset = e.offset;\n          skip(header.length);\n          rq.cancel(header, buf);\n          continue;\n        }\n\n        if(type==SSH_FXP_STATUS){\n          fill(buf, length);\n          int i=buf.getInt();    \n          if(i==SSH_FX_EOF){\n            break loop;\n          }\n          throwStatusError(buf, i);\n        }\n\n        if(type!=SSH_FXP_DATA){ \n\t  break loop;\n        }\n\n        buf.rewind();\n        fill(buf.buffer, 0, 4); length-=4;\n        int length_of_data = buf.getInt();   // length of data \n\n        /**\n         Since sftp protocol version 6, \"end-of-file\" has been defined,\n\n           byte   SSH_FXP_DATA\n           uint32 request-id\n           string data\n           bool   end-of-file [optional]\n\n         but some sftpd server will send such a field in the sftp protocol 3 ;-(\n         */\n        int optional_data = length - length_of_data;\n\n        int foo = length_of_data;\n        while(foo>0){\n          int bar=foo;\n          if(bar>buf.buffer.length){\n            bar=buf.buffer.length;\n          }\n          int data_len = io_in.read(buf.buffer, 0, bar);\n          if(data_len<0){\n            break loop;\n\t  }\n          \n          dst.write(buf.buffer, 0, data_len);\n\n          offset+=data_len;\n          foo-=data_len;\n\n          if(monitor!=null){\n            if(!monitor.count(data_len)){\n              skip(foo); \n              if(optional_data>0){\n                skip(optional_data);\n              }\n              break loop;\n            }\n          }\n\n        }\n\t//System.err.println(\"length: \"+length);  // length should be 0\n\n        if(optional_data>0){\n          skip(optional_data);\n        }\n\n        if(length_of_data<rr.length){  //\n          rq.cancel(header, buf);\n          sendREAD(handle, rr.offset+length_of_data, (int)(rr.length-length_of_data), rq);\n          request_offset=rr.offset+rr.length;\n        }\n\n        if(request_max < rq.size()){\n          request_max++;\n        }\n      }\n      dst.flush();\n\n      if(monitor!=null)monitor.end();\n\n      rq.cancel(header, buf);\n\n      _sendCLOSE(handle, header);\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n\n  private class RequestQueue {\n    class OutOfOrderException extends Exception {\n      long offset;\n      OutOfOrderException(long offset){\n        this.offset=offset;\n      }\n    }\n    class Request {\n      int id;\n      long offset;\n      long length;\n    }\n\n    Request[] rrq=null;\n    int head, count;\n    RequestQueue(int size){\n      rrq = new Request[size];\n      for(int i=0; i<rrq.length; i++){\n        rrq[i]=new Request();\n      }\n      init();\n    }\n\n    void init(){\n      head=count=0;\n    }\n\n    void add(int id, long offset, int length){\n      if(count == 0) head = 0;\n      int tail = head + count;\n      if(tail>=rrq.length) tail -= rrq.length;\n      rrq[tail].id=id;\n      rrq[tail].offset=offset;\n      rrq[tail].length=length;\n      count++;\n    }\n\n    Request get(int id) throws OutOfOrderException, SftpException {\n      count -= 1;\n      int i = head;\n      head++; \n      if(head==rrq.length) head=0;\n      if(rrq[i].id != id){\n        long offset = getOffset();\n        boolean find = false;\n        for(int j = 0; j<rrq.length; j++){\n          if(rrq[j].id == id){\n            find = true;\n            rrq[j].id = 0;\n            break;\n          }\n        }\n        if(find)\n          throw new OutOfOrderException(offset);\n        throw new SftpException(SSH_FX_FAILURE, \n                                \"RequestQueue: unknown request id \"+id);\n      }\n      rrq[i].id = 0;\n      return rrq[i];\n    }\n\n    int count() {\n      return count;\n    }\n\n    int size() {\n      return rrq.length;\n    } \n\n    void cancel(Header header, Buffer buf) throws IOException {\n      int _count = count;\n      for(int i=0; i<_count; i++){\n        header=header(buf, header);\n        int length=header.length;\n        for(int j=0; j<rrq.length; j++){\n          if(rrq[j].id == header.rid){\n            rrq[j].id=0;\n            break;\n          }\n        }\n        skip(length); \n      }\n      init();\n    }\n\n    long getOffset(){\n      long result = Long.MAX_VALUE;\n\n      for(int i=0; i<rrq.length; i++){\n        if(rrq[i].id == 0)\n          continue;\n        if(result>rrq[i].offset)\n          result=rrq[i].offset;\n      }\n\n      return result;\n    } \n  }\n\n  public InputStream get(String src) throws SftpException{\n    return get(src, null, 0L);\n  }\n  public InputStream get(String src, SftpProgressMonitor monitor) throws SftpException{\n    return get(src, monitor, 0L);\n  }\n\n  /**\n   * @deprecated  This method will be deleted in the future.\n   */\n  public InputStream get(String src, int mode) throws SftpException{\n    return get(src, null, 0L);\n  }\n  /**\n   * @deprecated  This method will be deleted in the future.\n   */\n  public InputStream get(String src, final SftpProgressMonitor monitor, final int mode) throws SftpException{\n    return get(src, monitor, 0L);\n  }\n  public InputStream get(String src, final SftpProgressMonitor monitor, final long skip) throws SftpException{\n\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      src=remoteAbsolutePath(src);\n      src=isUnique(src);\n\n      byte[] srcb=Util.str2byte(src, fEncoding);\n\n      SftpATTRS attr=_stat(srcb);\n      if(monitor!=null){\n        monitor.init(SftpProgressMonitor.GET, src, \"??\", attr.getSize());\n      }\n\n      sendOPENR(srcb);\n\n      Header header=new Header();\n      header=header(buf, header);\n      int length=header.length;\n      int type=header.type;\n\n      fill(buf, length);\n\n      if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){\n\tthrow new SftpException(SSH_FX_FAILURE, \"\");\n      }\n      if(type==SSH_FXP_STATUS){\n        int i=buf.getInt();\n        throwStatusError(buf, i);\n      }\n\n      final byte[] handle=buf.getString();         // handle\n\n      rq.init();\n\n      java.io.InputStream in=new java.io.InputStream(){\n           long offset=skip;\n           boolean closed=false;\n           int rest_length=0;\n           byte[] _data=new byte[1];\n           byte[] rest_byte=new byte[1024];\n           Header header=new Header();\n           int request_max=1;\n           long request_offset=offset;\n\n           public int read() throws java.io.IOException{\n             if(closed)return -1;\n             int i=read(_data, 0, 1);\n             if (i==-1) { return -1; }\n             else {\n               return _data[0]&0xff;\n             }\n           }\n           public int read(byte[] d) throws java.io.IOException{\n             if(closed)return -1;\n             return read(d, 0, d.length);\n           }\n           public int read(byte[] d, int s, int len) throws java.io.IOException{\n             if(closed)return -1;\n             if(d==null){throw new NullPointerException();}\n             if(s<0 || len <0 || s+len>d.length){\n               throw new IndexOutOfBoundsException();\n             } \n             if(len==0){ return 0; }\n\n             if(rest_length>0){\n               int foo=rest_length;\n               if(foo>len) foo=len;\n               System.arraycopy(rest_byte, 0, d, s, foo);\n               if(foo!=rest_length){\n                 System.arraycopy(rest_byte, foo, \n                                  rest_byte, 0, rest_length-foo);\n               }\n\n               if(monitor!=null){\n                 if(!monitor.count(foo)){\n                   close();\n                   return -1;\n                 }\n               }\n\n               rest_length-=foo;\n               return foo;\n             }\n\n             if(buf.buffer.length-13<len){\n               len=buf.buffer.length-13;\n             }\n             if(server_version==0 && len>1024){\n               len=1024; \n             }\n\n             if(rq.count()==0) {\n               int request_len = buf.buffer.length-13;\n               if(server_version==0){ request_len=1024; }\n\n               while(rq.count() < request_max){\n                 try{\n                   sendREAD(handle, request_offset, request_len, rq);\n                 }\n                 catch(Exception e){ throw new IOException(\"Error\"); }\n                 request_offset += request_len;\n               }\n             }\n\n             header=header(buf, header);\n             rest_length=header.length;\n             int type=header.type;\n             int id=header.rid;\n\n             RequestQueue.Request rr = null;\n             try{\n               rr = rq.get(header.rid);\n             }\n             catch(RequestQueue.OutOfOrderException e){\n               request_offset = e.offset;\n               skip(header.length);\n               rq.cancel(header, buf);\n               return 0;\n             }\n             catch(SftpException e){\n               throw new IOException(\"Error: \"+e.toString());\n             }\n\n             if(type!=SSH_FXP_STATUS && type!=SSH_FXP_DATA){ \n               throw new IOException(\"Error\");\n             }\n             if(type==SSH_FXP_STATUS){\n               fill(buf, rest_length);\n               int i=buf.getInt();    \n               rest_length=0;\n               if(i==SSH_FX_EOF){\n                 close();\n                 return -1;\n               }\n               //throwStatusError(buf, i);\n               throw new IOException(\"Error\");\n             }\n\n             buf.rewind();\n             fill(buf.buffer, 0, 4);\n             int length_of_data = buf.getInt(); rest_length-=4;\n\n             /**\n              Since sftp protocol version 6, \"end-of-file\" has been defined,\n     \n                byte   SSH_FXP_DATA\n                uint32 request-id\n                string data\n                bool   end-of-file [optional]\n     \n              but some sftpd server will send such a field in the sftp protocol 3 ;-(\n              */\n             int optional_data = rest_length - length_of_data;\n\n             offset += length_of_data;\n             int foo = length_of_data;\n             if(foo>0){\n               int bar=foo;\n               if(bar>len){\n                 bar=len;\n               }\n               int i=io_in.read(d, s, bar);\n               if(i<0){\n                 return -1;\n               }\n               foo-=i;\n               rest_length=foo;\n\n               if(foo>0){\n                 if(rest_byte.length<foo){\n                   rest_byte=new byte[foo];\n                 }\n                 int _s=0;\n                 int _len=foo;\n                 int j;\n                 while(_len>0){\n                   j=io_in.read(rest_byte, _s, _len);\n                   if(j<=0)break;\n                   _s+=j;\n                   _len-=j;\n                 }\n               }\n\n               if(optional_data>0){\n                 io_in.skip(optional_data);\n               }\n\n               if(length_of_data<rr.length){  //\n                 rq.cancel(header, buf);\n                 try {\n                   sendREAD(handle,\n                            rr.offset+length_of_data,\n                            (int)(rr.length-length_of_data), rq);\n                 }\n                 catch(Exception e){ throw new IOException(\"Error\"); }\n                 request_offset=rr.offset+rr.length;\n               }\n\n               if(request_max < rq.size()){\n                 request_max++;\n               }\n\n               if(monitor!=null){\n                 if(!monitor.count(i)){\n                   close();\n                   return -1;\n                 }\n               }\n\n               return i;\n             }\n             return 0; // ??\n           }\n           public void close() throws IOException{\n             if(closed)return;\n             closed=true;\n             if(monitor!=null)monitor.end();\n             rq.cancel(header, buf);\n             try{_sendCLOSE(handle, header);}\n             catch(Exception e){throw new IOException(\"Error\");}\n           }\n         };\n       return in;\n     }\n     catch(Exception e){\n       if(e instanceof SftpException) throw (SftpException)e;\n       if(e instanceof Throwable)\n         throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n       throw new SftpException(SSH_FX_FAILURE, \"\");\n     }\n   }\n\n   public java.util.Vector ls(String path) throws SftpException{\n     final java.util.Vector v = new Vector();\n     LsEntrySelector selector = new LsEntrySelector(){\n       public int select(LsEntry entry){\n         v.addElement(entry);\n         return CONTINUE;\n       }\n     };\n     ls(path, selector);\n     return v;\n   }\n\n  /**\n   * List files specified by the remote <code>path</code>.\n   * Each files and directories will be passed to\n   * <code>LsEntrySelector#select(LsEntry)</code> method, and if that method\n   * returns <code>LsEntrySelector#BREAK</code>, the operation will be\n   * canceled immediately.\n   *\n   * @see ChannelSftp.LsEntrySelector\n   * @since 0.1.47\n   */\n   public void ls(String path, LsEntrySelector selector) throws SftpException{\n     //System.out.println(\"ls: \"+path);\n     try{\n       ((MyPipedInputStream)io_in).updateReadSide();\n\n       path=remoteAbsolutePath(path);\n       byte[] pattern=null;\n       java.util.Vector v=new java.util.Vector();\n\n       int foo=path.lastIndexOf('/');\n       String dir=path.substring(0, ((foo==0)?1:foo));\n       String _pattern=path.substring(foo+1);\n       dir=Util.unquote(dir);\n\n       // If pattern has included '*' or '?', we need to convert\n       // to UTF-8 string before globbing.\n       byte[][] _pattern_utf8=new byte[1][];\n       boolean pattern_has_wildcard=isPattern(_pattern, _pattern_utf8);\n\n       if(pattern_has_wildcard){\n         pattern=_pattern_utf8[0];\n       }\n       else{\n         String upath=Util.unquote(path);\n         //SftpATTRS attr=_lstat(upath);\n         SftpATTRS attr=_stat(upath);\n         if(attr.isDir()){\n           pattern=null;\n           dir=upath;\n         }\n         else{\n           /*\n             // If we can generage longname by ourself,\n             // we don't have to use openDIR.\n           String filename=Util.unquote(_pattern);\n           String longname=...\n           v.addElement(new LsEntry(filename, longname, attr));\n           return v;\n           */\n\n           if(fEncoding_is_utf8){\n             pattern=_pattern_utf8[0];\n             pattern=Util.unquote(pattern);\n           }\n           else{\n             _pattern=Util.unquote(_pattern);\n             pattern=Util.str2byte(_pattern, fEncoding);\n           }\n\n         }\n       }\n\n       sendOPENDIR(Util.str2byte(dir, fEncoding));\n\n       Header header=new Header();\n       header=header(buf, header);\n       int length=header.length;\n       int type=header.type;\n\n       fill(buf, length);\n\n       if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){\n         throw new SftpException(SSH_FX_FAILURE, \"\");\n       }\n       if(type==SSH_FXP_STATUS){\n         int i=buf.getInt();\n         throwStatusError(buf, i);\n       }\n\n       int cancel = LsEntrySelector.CONTINUE;\n       byte[] handle=buf.getString();         // handle\n\n       while(cancel==LsEntrySelector.CONTINUE){\n\n         sendREADDIR(handle);\n\n         header=header(buf, header);\n         length=header.length;\n         type=header.type;\n         if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){\n           throw new SftpException(SSH_FX_FAILURE, \"\");\n         }\n         if(type==SSH_FXP_STATUS){ \n           fill(buf, length);\n           int i=buf.getInt();\n           if(i==SSH_FX_EOF)\n             break;\n           throwStatusError(buf, i);\n         }\n\n         buf.rewind();\n         fill(buf.buffer, 0, 4); length-=4;\n         int count=buf.getInt();\n\n         byte[] str;\n         int flags;\n\n         buf.reset();\n         while(count>0){\n           if(length>0){\n             buf.shift();\n             int j=(buf.buffer.length>(buf.index+length)) ? \n               length : \n               (buf.buffer.length-buf.index);\n             int i=fill(buf.buffer, buf.index, j);\n             buf.index+=i;\n             length-=i;\n           }\n           byte[] filename=buf.getString();\n           byte[] longname=null;\n           if(server_version<=3){\n             longname=buf.getString();\n           }\n           SftpATTRS attrs=SftpATTRS.getATTR(buf);\n\n           if(cancel==LsEntrySelector.BREAK){\n             count--; \n             continue;\n           }\n\n           boolean find=false;\n           String f=null;\n           if(pattern==null){\n             find=true;\n           }\n           else if(!pattern_has_wildcard){\n             find=Util.array_equals(pattern, filename);\n           }\n           else{\n             byte[] _filename=filename;\n             if(!fEncoding_is_utf8){\n               f=Util.byte2str(_filename, fEncoding);\n               _filename=Util.str2byte(f, UTF8);\n             }\n             find=Util.glob(pattern, _filename);\n           }\n\n           if(find){\n             if(f==null){\n               f=Util.byte2str(filename, fEncoding);\n             }\n             String l=null;\n             if(longname==null){\n               // TODO: we need to generate long name from attrs\n               //       for the sftp protocol 4(and later).\n               l=attrs.toString()+\" \"+f;\n             }\n             else{\n               l=Util.byte2str(longname, fEncoding);\n             }\n\n             cancel = selector.select(new LsEntry(f, l, attrs));\n           }\n\n           count--; \n         }\n       }\n       _sendCLOSE(handle, header);\n\n       /*\n       if(v.size()==1 && pattern_has_wildcard){\n         LsEntry le=(LsEntry)v.elementAt(0);\n         if(le.getAttrs().isDir()){\n           String f=le.getFilename();\n           if(isPattern(f)){\n             f=Util.quote(f);\n           }\n           if(!dir.endsWith(\"/\")){\n             dir+=\"/\";\n           }\n           v=null;\n           return ls(dir+f);\n         }\n       }\n       */\n\n     }\n     catch(Exception e){\n       if(e instanceof SftpException) throw (SftpException)e;\n       if(e instanceof Throwable)\n         throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n       throw new SftpException(SSH_FX_FAILURE, \"\");\n     }\n   }\n\n   public String readlink(String path) throws SftpException{\n     try{\n       if(server_version<3){\n         throw new SftpException(SSH_FX_OP_UNSUPPORTED, \n                                 \"The remote sshd is too old to support symlink operation.\");\n       }\n\n       ((MyPipedInputStream)io_in).updateReadSide();\n\n       path=remoteAbsolutePath(path);\n\n       path=isUnique(path);\n\n       sendREADLINK(Util.str2byte(path, fEncoding));\n\n       Header header=new Header();\n       header=header(buf, header);\n       int length=header.length;\n       int type=header.type;\n\n       fill(buf, length);\n\n       if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){\n         throw new SftpException(SSH_FX_FAILURE, \"\");\n       }\n       if(type==SSH_FXP_NAME){\n         int count=buf.getInt();       // count\n         byte[] filename=null;\n         for(int i=0; i<count; i++){\n           filename=buf.getString();\n           if(server_version<=3){\n             byte[] longname=buf.getString();\n           }\n           SftpATTRS.getATTR(buf);\n         }\n         return Util.byte2str(filename, fEncoding);\n       }\n\n       int i=buf.getInt();\n       throwStatusError(buf, i);\n     }\n     catch(Exception e){\n       if(e instanceof SftpException) throw (SftpException)e;\n       if(e instanceof Throwable)\n         throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n       throw new SftpException(SSH_FX_FAILURE, \"\");\n     }\n     return null;\n   }\n\n   public void symlink(String oldpath, String newpath) throws SftpException{\n     if(server_version<3){\n       throw new SftpException(SSH_FX_OP_UNSUPPORTED, \n                               \"The remote sshd is too old to support symlink operation.\");\n     }\n\n     try{\n       ((MyPipedInputStream)io_in).updateReadSide();\n\n       String _oldpath=remoteAbsolutePath(oldpath);\n       newpath=remoteAbsolutePath(newpath);\n\n       _oldpath=isUnique(_oldpath);\n       if(oldpath.charAt(0)!='/'){ // relative path\n         String cwd=getCwd();\n         oldpath=_oldpath.substring(cwd.length()+(cwd.endsWith(\"/\")?0:1));\n       }\n       else {\n         oldpath=_oldpath;\n       }\n\n       if(isPattern(newpath)){\n         throw new SftpException(SSH_FX_FAILURE, newpath);\n       }\n       newpath=Util.unquote(newpath);\n\n       sendSYMLINK(Util.str2byte(oldpath, fEncoding),\n                   Util.str2byte(newpath, fEncoding));\n\n       Header header=new Header();\n       header=header(buf, header);\n       int length=header.length;\n       int type=header.type;\n\n       fill(buf, length);\n\n       if(type!=SSH_FXP_STATUS){\n         throw new SftpException(SSH_FX_FAILURE, \"\");\n       }\n\n       int i=buf.getInt();\n       if(i==SSH_FX_OK) return;\n       throwStatusError(buf, i);\n     }\n     catch(Exception e){\n       if(e instanceof SftpException) throw (SftpException)e;\n       if(e instanceof Throwable)\n         throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n       throw new SftpException(SSH_FX_FAILURE, \"\");\n     }\n   }\n\n   public void hardlink(String oldpath, String newpath) throws SftpException{\n     if(!extension_hardlink){\n       throw new SftpException(SSH_FX_OP_UNSUPPORTED, \n                               \"hardlink@openssh.com is not supported\");\n     }\n\n     try{\n       ((MyPipedInputStream)io_in).updateReadSide();\n\n       String _oldpath=remoteAbsolutePath(oldpath);\n       newpath=remoteAbsolutePath(newpath);\n\n       _oldpath=isUnique(_oldpath);\n       if(oldpath.charAt(0)!='/'){ // relative path\n         String cwd=getCwd();\n         oldpath=_oldpath.substring(cwd.length()+(cwd.endsWith(\"/\")?0:1));\n       }\n       else {\n         oldpath=_oldpath;\n       }\n\n       if(isPattern(newpath)){\n         throw new SftpException(SSH_FX_FAILURE, newpath);\n       }\n       newpath=Util.unquote(newpath);\n\n       sendHARDLINK(Util.str2byte(oldpath, fEncoding),\n                   Util.str2byte(newpath, fEncoding));\n\n       Header header=new Header();\n       header=header(buf, header);\n       int length=header.length;\n       int type=header.type;\n\n       fill(buf, length);\n\n       if(type!=SSH_FXP_STATUS){\n         throw new SftpException(SSH_FX_FAILURE, \"\");\n       }\n\n       int i=buf.getInt();\n       if(i==SSH_FX_OK) return;\n       throwStatusError(buf, i);\n     }\n     catch(Exception e){\n       if(e instanceof SftpException) throw (SftpException)e;\n       if(e instanceof Throwable)\n         throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n       throw new SftpException(SSH_FX_FAILURE, \"\");\n     }\n   }\n\n   public void rename(String oldpath, String newpath) throws SftpException{\n     if(server_version<2){\n       throw new SftpException(SSH_FX_OP_UNSUPPORTED, \n                               \"The remote sshd is too old to support rename operation.\");\n     }\n\n     try{\n       ((MyPipedInputStream)io_in).updateReadSide();\n\n       oldpath=remoteAbsolutePath(oldpath);\n       newpath=remoteAbsolutePath(newpath);\n\n       oldpath=isUnique(oldpath);\n\n       Vector v=glob_remote(newpath);\n       int vsize=v.size();\n       if(vsize>=2){\n         throw new SftpException(SSH_FX_FAILURE, v.toString());\n       }\n       if(vsize==1){\n         newpath=(String)(v.elementAt(0));\n       }\n       else{  // vsize==0\n         if(isPattern(newpath))\n           throw new SftpException(SSH_FX_FAILURE, newpath);\n         newpath=Util.unquote(newpath);\n       }\n\n       sendRENAME(Util.str2byte(oldpath, fEncoding),\n                  Util.str2byte(newpath, fEncoding));\n\n       Header header=new Header();\n       header=header(buf, header);\n       int length=header.length;\n       int type=header.type;\n\n       fill(buf, length);\n\n       if(type!=SSH_FXP_STATUS){\n         throw new SftpException(SSH_FX_FAILURE, \"\");\n       }\n\n       int i=buf.getInt();\n       if(i==SSH_FX_OK) return;\n       throwStatusError(buf, i);\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n  public void rm(String path) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n\n      Vector v=glob_remote(path);\n      int vsize=v.size();\n\n      Header header=new Header();\n\n      for(int j=0; j<vsize; j++){\n\tpath=(String)(v.elementAt(j));\n        sendREMOVE(Util.str2byte(path, fEncoding));\n\n        header=header(buf, header);\n        int length=header.length;\n        int type=header.type;\n\n        fill(buf, length);\n\n        if(type!=SSH_FXP_STATUS){\n\t  throw new SftpException(SSH_FX_FAILURE, \"\");\n        }\n        int i=buf.getInt();\n\tif(i!=SSH_FX_OK){\n\t  throwStatusError(buf, i);\n\t}\n      }\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  private boolean isRemoteDir(String path){\n    try{\n      sendSTAT(Util.str2byte(path, fEncoding));\n\n      Header header=new Header();\n      header=header(buf, header);\n      int length=header.length;\n      int type=header.type;\n\n      fill(buf, length);\n\n      if(type!=SSH_FXP_ATTRS){\n        return false; \n      }\n      SftpATTRS attr=SftpATTRS.getATTR(buf);\n      return attr.isDir();\n    }\n    catch(Exception e){}\n    return false;\n  }\n\n  public void chgrp(int gid, String path) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n\n      Vector v=glob_remote(path);\n      int vsize=v.size();\n      for(int j=0; j<vsize; j++){\n\tpath=(String)(v.elementAt(j));\n\n        SftpATTRS attr=_stat(path);\n\n\tattr.setFLAGS(0);\n\tattr.setUIDGID(attr.uid, gid); \n\t_setStat(path, attr);\n      }\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  public void chown(int uid, String path) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n\n      Vector v=glob_remote(path);\n      int vsize=v.size();\n      for(int j=0; j<vsize; j++){\n\tpath=(String)(v.elementAt(j));\n\n        SftpATTRS attr=_stat(path);\n\n\tattr.setFLAGS(0);\n\tattr.setUIDGID(uid, attr.gid); \n\t_setStat(path, attr);\n      }\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  public void chmod(int permissions, String path) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n\n      Vector v=glob_remote(path);\n      int vsize=v.size();\n      for(int j=0; j<vsize; j++){\n\tpath=(String)(v.elementAt(j));\n\n\tSftpATTRS attr=_stat(path);\n\n\tattr.setFLAGS(0);\n\tattr.setPERMISSIONS(permissions); \n\t_setStat(path, attr);\n      }\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  public void setMtime(String path, int mtime) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n\n      Vector v=glob_remote(path);\n      int vsize=v.size();\n      for(int j=0; j<vsize; j++){\n\tpath=(String)(v.elementAt(j));\n\n        SftpATTRS attr=_stat(path);\n\n\tattr.setFLAGS(0);\n\tattr.setACMODTIME(attr.getATime(), mtime);\n\t_setStat(path, attr);\n      }\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  public void rmdir(String path) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n\n      Vector v=glob_remote(path);\n      int vsize=v.size();\n\n      Header header=new Header();\n\n      for(int j=0; j<vsize; j++){\n\tpath=(String)(v.elementAt(j));\n\tsendRMDIR(Util.str2byte(path, fEncoding));\n\n        header=header(buf, header);\n        int length=header.length;\n        int type=header.type;\n\n        fill(buf, length);\n\n\tif(type!=SSH_FXP_STATUS){\n\t  throw new SftpException(SSH_FX_FAILURE, \"\");\n\t}\n\n\tint i=buf.getInt();\n\tif(i!=SSH_FX_OK){\n\t  throwStatusError(buf, i);\n\t}\n      }\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  public void mkdir(String path) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n\n      sendMKDIR(Util.str2byte(path, fEncoding), null);\n\n      Header header=new Header();      \n      header=header(buf, header);\n      int length=header.length;\n      int type=header.type;\n\n      fill(buf, length);\n\n      if(type!=SSH_FXP_STATUS){\n\tthrow new SftpException(SSH_FX_FAILURE, \"\");\n      }\n\n      int i=buf.getInt();\n      if(i==SSH_FX_OK) return;\n      throwStatusError(buf, i);\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  public SftpATTRS stat(String path) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n      path=isUnique(path);\n\n      return _stat(path);\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n    //return null;\n  }\n\n  private SftpATTRS _stat(byte[] path) throws SftpException{\n    try{\n\n      sendSTAT(path);\n\n      Header header=new Header();\n      header=header(buf, header);\n      int length=header.length;\n      int type=header.type;\n\n      fill(buf, length);\n\n      if(type!=SSH_FXP_ATTRS){\n\tif(type==SSH_FXP_STATUS){\n\t  int i=buf.getInt();\n\t  throwStatusError(buf, i);\n\t}\n\tthrow new SftpException(SSH_FX_FAILURE, \"\");\n      }\n      SftpATTRS attr=SftpATTRS.getATTR(buf);\n      return attr;\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n    //return null;\n  }\n\n  private SftpATTRS _stat(String path) throws SftpException{\n    return _stat(Util.str2byte(path, fEncoding));\n  }\n\n  public SftpStatVFS statVFS(String path) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n      path=isUnique(path);\n\n      return _statVFS(path);\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n    //return null;\n  }\n\n  private SftpStatVFS _statVFS(byte[] path) throws SftpException{\n    if(!extension_statvfs){\n      throw new SftpException(SSH_FX_OP_UNSUPPORTED, \n                              \"statvfs@openssh.com is not supported\");\n    }\n\n    try{\n\n      sendSTATVFS(path);\n\n      Header header=new Header();\n      header=header(buf, header);\n      int length=header.length;\n      int type=header.type;\n\n      fill(buf, length);\n\n      if(type != (SSH_FXP_EXTENDED_REPLY&0xff)){\n        if(type==SSH_FXP_STATUS){\n          int i=buf.getInt();\n          throwStatusError(buf, i);\n        }\n        throw new SftpException(SSH_FX_FAILURE, \"\");\n      }\n      else {\n        SftpStatVFS stat = SftpStatVFS.getStatVFS(buf);\n        return stat;\n      }\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n    //return null;\n  }\n\n  private SftpStatVFS _statVFS(String path) throws SftpException{\n    return _statVFS(Util.str2byte(path, fEncoding));\n  }\n\n  public SftpATTRS lstat(String path) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n      path=isUnique(path);\n\n      return _lstat(path);\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  private SftpATTRS _lstat(String path) throws SftpException{\n    try{\n      sendLSTAT(Util.str2byte(path, fEncoding));\n\n      Header header=new Header();\n      header=header(buf, header);\n      int length=header.length;\n      int type=header.type;\n\n      fill(buf, length);\n\n      if(type!=SSH_FXP_ATTRS){\n\tif(type==SSH_FXP_STATUS){\n\t  int i=buf.getInt();\n\t  throwStatusError(buf, i);\n\t}\n\tthrow new SftpException(SSH_FX_FAILURE, \"\");\n      }\n      SftpATTRS attr=SftpATTRS.getATTR(buf);\n      return attr;\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  private byte[] _realpath(String path) throws SftpException, IOException, Exception{\n    sendREALPATH(Util.str2byte(path, fEncoding));\n\n    Header header=new Header();\n    header=header(buf, header);\n    int length=header.length;\n    int type=header.type;\n\n    fill(buf, length);\n\n    if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n    int i;\n    if(type==SSH_FXP_STATUS){\n      i=buf.getInt();\n      throwStatusError(buf, i);\n    }\n    i=buf.getInt();   // count\n\n    byte[] str=null;\n    while(i-->0){\n      str=buf.getString();  // absolute path;\n      if(server_version<=3){\n        byte[] lname=buf.getString();  // long filename\n      }\n      SftpATTRS attr=SftpATTRS.getATTR(buf);  // dummy attribute\n    }\n    return str;\n  }\n\n  public void setStat(String path, SftpATTRS attr) throws SftpException{\n    try{\n      ((MyPipedInputStream)io_in).updateReadSide();\n\n      path=remoteAbsolutePath(path);\n\n      Vector v=glob_remote(path);\n      int vsize=v.size();\n      for(int j=0; j<vsize; j++){\n\tpath=(String)(v.elementAt(j));\n\t_setStat(path, attr);\n      }\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n  private void _setStat(String path, SftpATTRS attr) throws SftpException{\n    try{\n      sendSETSTAT(Util.str2byte(path, fEncoding), attr);\n\n      Header header=new Header();\n      header=header(buf, header);\n      int length=header.length;\n      int type=header.type;\n\n      fill(buf, length);\n\n      if(type!=SSH_FXP_STATUS){\n\tthrow new SftpException(SSH_FX_FAILURE, \"\");\n      }\n      int i=buf.getInt();\n      if(i!=SSH_FX_OK){\n\tthrowStatusError(buf, i);\n      }\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  public String pwd() throws SftpException{ return getCwd(); }\n  public String lpwd(){ return lcwd; }\n  public String version(){ return version; }\n  public String getHome() throws SftpException {\n    if(home==null){\n      try{\n        ((MyPipedInputStream)io_in).updateReadSide();\n\n        byte[] _home=_realpath(\"\");\n        home=Util.byte2str(_home, fEncoding);\n      }\n      catch(Exception e){\n        if(e instanceof SftpException) throw (SftpException)e;\n        if(e instanceof Throwable)\n          throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n        throw new SftpException(SSH_FX_FAILURE, \"\");\n      }\n    }\n    return home; \n  }\n\n  private String getCwd() throws SftpException{\n    if(cwd==null)\n      cwd=getHome();\n    return cwd;\n  }\n\n  private void setCwd(String cwd){\n    this.cwd=cwd;\n  }\n\n  private void read(byte[] buf, int s, int l) throws IOException, SftpException{\n    int i=0;\n    while(l>0){\n      i=io_in.read(buf, s, l);\n      if(i<=0){\n        throw new SftpException(SSH_FX_FAILURE, \"\");\n      }\n      s+=i;\n      l-=i;\n    }\n  }\n\n  private boolean checkStatus(int[] ackid, Header header) throws IOException, SftpException{\n    header=header(buf, header);\n    int length=header.length;\n    int type=header.type;\n    if(ackid!=null)\n      ackid[0]=header.rid;\n\n    fill(buf, length);\n\n    if(type!=SSH_FXP_STATUS){ \n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n    int i=buf.getInt();\n    if(i!=SSH_FX_OK){\n      throwStatusError(buf, i);\n    }\n    return true;\n  }\n  private boolean _sendCLOSE(byte[] handle, Header header) throws Exception{\n    sendCLOSE(handle);\n    return checkStatus(null, header);\n  }\n\n  private void sendINIT() throws Exception{\n    packet.reset();\n    putHEAD(SSH_FXP_INIT, 5);\n    buf.putInt(3);                // version 3\n    getSession().write(packet, this, 5+4);\n  }\n\n  private void sendREALPATH(byte[] path) throws Exception{\n    sendPacketPath(SSH_FXP_REALPATH, path);\n  }\n  private void sendSTAT(byte[] path) throws Exception{\n    sendPacketPath(SSH_FXP_STAT, path);\n  }\n  private void sendSTATVFS(byte[] path) throws Exception{\n    sendPacketPath((byte)0, path, \"statvfs@openssh.com\");\n  }\n  /*\n  private void sendFSTATVFS(byte[] handle) throws Exception{\n    sendPacketPath((byte)0, handle, \"fstatvfs@openssh.com\");\n  }\n  */\n  private void sendLSTAT(byte[] path) throws Exception{\n    sendPacketPath(SSH_FXP_LSTAT, path);\n  }\n  private void sendFSTAT(byte[] handle) throws Exception{\n    sendPacketPath(SSH_FXP_FSTAT, handle);\n  }\n  private void sendSETSTAT(byte[] path, SftpATTRS attr) throws Exception{\n    packet.reset();\n    putHEAD(SSH_FXP_SETSTAT, 9+path.length+attr.length());\n    buf.putInt(seq++);\n    buf.putString(path);             // path\n    attr.dump(buf);\n    getSession().write(packet, this, 9+path.length+attr.length()+4);\n  }\n  private void sendREMOVE(byte[] path) throws Exception{\n    sendPacketPath(SSH_FXP_REMOVE, path);\n  }\n  private void sendMKDIR(byte[] path, SftpATTRS attr) throws Exception{\n    packet.reset();\n    putHEAD(SSH_FXP_MKDIR, 9+path.length+(attr!=null?attr.length():4));\n    buf.putInt(seq++);\n    buf.putString(path);             // path\n    if(attr!=null) attr.dump(buf);\n    else buf.putInt(0);\n    getSession().write(packet, this, 9+path.length+(attr!=null?attr.length():4)+4);\n  }\n  private void sendRMDIR(byte[] path) throws Exception{\n    sendPacketPath(SSH_FXP_RMDIR, path);\n  }\n  private void sendSYMLINK(byte[] p1, byte[] p2) throws Exception{\n    sendPacketPath(SSH_FXP_SYMLINK, p1, p2);\n  }\n  private void sendHARDLINK(byte[] p1, byte[] p2) throws Exception{\n    sendPacketPath((byte)0, p1, p2, \"hardlink@openssh.com\");\n  }\n  private void sendREADLINK(byte[] path) throws Exception{\n    sendPacketPath(SSH_FXP_READLINK, path);\n  }\n  private void sendOPENDIR(byte[] path) throws Exception{\n    sendPacketPath(SSH_FXP_OPENDIR, path);\n  }\n  private void sendREADDIR(byte[] path) throws Exception{\n    sendPacketPath(SSH_FXP_READDIR, path);\n  }\n  private void sendRENAME(byte[] p1, byte[] p2) throws Exception{\n    sendPacketPath(SSH_FXP_RENAME, p1, p2,\n                   extension_posix_rename ? \"posix-rename@openssh.com\" : null);\n  }\n  private void sendCLOSE(byte[] path) throws Exception{\n    sendPacketPath(SSH_FXP_CLOSE, path);\n  }\n  private void sendOPENR(byte[] path) throws Exception{\n    sendOPEN(path, SSH_FXF_READ);\n  }\n  private void sendOPENW(byte[] path) throws Exception{\n    sendOPEN(path, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_TRUNC);\n  }\n  private void sendOPENA(byte[] path) throws Exception{\n    sendOPEN(path, SSH_FXF_WRITE|/*SSH_FXF_APPEND|*/SSH_FXF_CREAT);\n  }\n  private void sendOPEN(byte[] path, int mode) throws Exception{\n    packet.reset();\n    putHEAD(SSH_FXP_OPEN, 17+path.length);\n    buf.putInt(seq++);\n    buf.putString(path);\n    buf.putInt(mode);\n    buf.putInt(0);           // attrs\n    getSession().write(packet, this, 17+path.length+4);\n  }\n  private void sendPacketPath(byte fxp, byte[] path) throws Exception{\n    sendPacketPath(fxp, path, (String)null);\n  }\n  private void sendPacketPath(byte fxp, byte[] path, String extension) throws Exception{\n    packet.reset();\n    int len = 9+path.length;\n    if(extension == null) {\n      putHEAD(fxp, len);\n      buf.putInt(seq++);\n    }\n    else {\n      len+=(4+extension.length());\n      putHEAD(SSH_FXP_EXTENDED, len);\n      buf.putInt(seq++);\n      buf.putString(Util.str2byte(extension));\n    }\n    buf.putString(path);             // path\n    getSession().write(packet, this, len+4);\n  }\n\n  private void sendPacketPath(byte fxp, byte[] p1, byte[] p2) throws Exception{\n    sendPacketPath(fxp, p1, p2, null);\n  }\n  private void sendPacketPath(byte fxp, byte[] p1, byte[] p2, String extension) throws Exception{\n    packet.reset();\n    int len = 13+p1.length+p2.length;\n    if(extension==null){\n      putHEAD(fxp, len);\n      buf.putInt(seq++);\n    }\n    else {\n      len+=(4+extension.length());\n      putHEAD(SSH_FXP_EXTENDED, len);\n      buf.putInt(seq++);\n      buf.putString(Util.str2byte(extension));\n    }\n    buf.putString(p1);\n    buf.putString(p2);\n    getSession().write(packet, this, len+4);\n  }\n\n  private int sendWRITE(byte[] handle, long offset, \n                        byte[] data, int start, int length) throws Exception{\n    int _length=length;\n    opacket.reset();\n    if(obuf.buffer.length<obuf.index+13+21+handle.length+length+Session.buffer_margin){\n      _length=obuf.buffer.length-(obuf.index+13+21+handle.length+Session.buffer_margin);\n      // System.err.println(\"_length=\"+_length+\" length=\"+length);\n    }\n\n    putHEAD(obuf, SSH_FXP_WRITE, 21+handle.length+_length);       // 14\n    obuf.putInt(seq++);                                      //  4\n    obuf.putString(handle);                                  //  4+handle.length\n    obuf.putLong(offset);                                    //  8\n    if(obuf.buffer!=data){\n      obuf.putString(data, start, _length);                    //  4+_length\n    }\n    else{\n      obuf.putInt(_length);\n      obuf.skip(_length);\n    }\n    getSession().write(opacket, this, 21+handle.length+_length+4);\n    return _length;\n  }\n  private void sendREAD(byte[] handle, long offset, int length) throws Exception{\n    sendREAD(handle, offset, length, null);\n  }\n  private void sendREAD(byte[] handle, long offset, int length,\n                        RequestQueue rrq) throws Exception{\n    packet.reset();\n    putHEAD(SSH_FXP_READ, 21+handle.length);\n    buf.putInt(seq++);\n    buf.putString(handle);\n    buf.putLong(offset);\n    buf.putInt(length);\n    getSession().write(packet, this, 21+handle.length+4);\n    if(rrq!=null){\n      rrq.add(seq-1, offset, length);\n    }\n  }\n\n  private void putHEAD(Buffer buf, byte type, int length) throws Exception{\n    buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);\n    buf.putInt(recipient);\n    buf.putInt(length+4);\n    buf.putInt(length);\n    buf.putByte(type);\n  }\n\n  private void putHEAD(byte type, int length) throws Exception{\n    putHEAD(buf, type, length);\n  }\n\n  private Vector glob_remote(String _path) throws Exception{\n    Vector v=new Vector();\n    int i=0;\n\n    int foo=_path.lastIndexOf('/');\n    if(foo<0){  // it is not absolute path.\n      v.addElement(Util.unquote(_path)); \n      return v;\n    }\n\n    String dir=_path.substring(0, ((foo==0)?1:foo));\n    String _pattern=_path.substring(foo+1);\n\n    dir=Util.unquote(dir);\n\n    byte[] pattern=null;\n    byte[][] _pattern_utf8=new byte[1][];\n    boolean pattern_has_wildcard=isPattern(_pattern, _pattern_utf8);\n\n    if(!pattern_has_wildcard){\n      if(!dir.equals(\"/\"))\n        dir+=\"/\";\n      v.addElement(dir+Util.unquote(_pattern));\n      return v;\n    }\n\n    pattern=_pattern_utf8[0];\n\n    sendOPENDIR(Util.str2byte(dir, fEncoding));\n\n    Header header=new Header();\n    header=header(buf, header);\n    int length=header.length;\n    int type=header.type;\n\n    fill(buf, length);\n\n    if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n    if(type==SSH_FXP_STATUS){\n      i=buf.getInt();\n      throwStatusError(buf, i);\n    }\n\n    byte[] handle=buf.getString();         // filename\n    String pdir=null;                      // parent directory\n\n    while(true){\n      sendREADDIR(handle);\n      header=header(buf, header);\n      length=header.length;\n      type=header.type;\n\n      if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){\n\tthrow new SftpException(SSH_FX_FAILURE, \"\");\n      }\n      if(type==SSH_FXP_STATUS){ \n        fill(buf, length);\n\tbreak;\n      }\n\n      buf.rewind();\n      fill(buf.buffer, 0, 4); length-=4;\n      int count=buf.getInt();\n\n      byte[] str;\n      int flags;\n\n      buf.reset();\n      while(count>0){\n\tif(length>0){\n\t  buf.shift();\n          int j=(buf.buffer.length>(buf.index+length)) ? length : (buf.buffer.length-buf.index);\n\t  i=io_in.read(buf.buffer, buf.index, j);\n\t  if(i<=0)break;\n\t  buf.index+=i;\n\t  length-=i;\n\t}\n\n\tbyte[] filename=buf.getString();\n\t//System.err.println(\"filename: \"+new String(filename));\n        if(server_version<=3){\n          str=buf.getString();  // longname\n        }\n\tSftpATTRS attrs=SftpATTRS.getATTR(buf);\n\n        byte[] _filename=filename;\n        String f=null;\n        boolean found=false;\n\n        if(!fEncoding_is_utf8){\n          f=Util.byte2str(filename, fEncoding);\n          _filename=Util.str2byte(f, UTF8);\n        }\n        found=Util.glob(pattern, _filename);\n\n\tif(found){\n          if(f==null){\n            f=Util.byte2str(filename, fEncoding);\n          }\n          if(pdir==null){\n            pdir=dir;\n            if(!pdir.endsWith(\"/\")){\n              pdir+=\"/\";\n            }\n          }\n\t  v.addElement(pdir+f);\n\t}\n\tcount--; \n      }\n    }\n    if(_sendCLOSE(handle, header)) \n      return v;\n    return null;\n  }\n\n  private boolean isPattern(byte[] path){\n    int length=path.length;\n    int i=0;\n    while(i<length){\n      if(path[i]=='*' || path[i]=='?')\n        return true;\n      if(path[i]=='\\\\' && (i+1)<length)\n        i++;\n      i++;\n    }\n    return false;\n  }\n\n  private Vector glob_local(String _path) throws Exception{\n//System.err.println(\"glob_local: \"+_path);\n    Vector v=new Vector();\n    byte[] path=Util.str2byte(_path, UTF8);\n    int i=path.length-1;\n    while(i>=0){\n      if(path[i]!='*' && path[i]!='?'){\n        i--;\n        continue;\n      }\n      if(!fs_is_bs &&\n         i>0 && path[i-1]=='\\\\'){\n        i--;\n        if(i>0 && path[i-1]=='\\\\'){\n          i--;\n          i--;\n          continue;\n        }\n      }\n      break;\n    }\n\n    if(i<0){ v.addElement(fs_is_bs ? _path : Util.unquote(_path)); return v;}\n\n    while(i>=0){\n      if(path[i]==file_separatorc ||\n         (fs_is_bs && path[i]=='/')){ // On Windows, '/' is also the separator.\n        break;\n      }\n      i--;\n    }\n\n    if(i<0){ v.addElement(fs_is_bs ? _path : Util.unquote(_path)); return v;}\n\n    byte[] dir;\n    if(i==0){dir=new byte[]{(byte)file_separatorc};}\n    else{ \n      dir=new byte[i];\n      System.arraycopy(path, 0, dir, 0, i);\n    }\n\n    byte[] pattern=new byte[path.length-i-1];\n    System.arraycopy(path, i+1, pattern, 0, pattern.length);\n\n//System.err.println(\"dir: \"+new String(dir)+\" pattern: \"+new String(pattern));\n    try{\n      String[] children=(new File(Util.byte2str(dir, UTF8))).list();\n      String pdir=Util.byte2str(dir)+file_separator;\n      for(int j=0; j<children.length; j++){\n//System.err.println(\"children: \"+children[j]);\n\tif(Util.glob(pattern, Util.str2byte(children[j], UTF8))){\n\t  v.addElement(pdir+children[j]);\n\t}\n      }\n    }\n    catch(Exception e){\n    }\n    return v;\n  }\n\n  private void throwStatusError(Buffer buf, int i) throws SftpException{\n    if(server_version>=3 &&   // WindRiver's sftp will send invalid \n       buf.getLength()>=4){   // SSH_FXP_STATUS packet.\n      byte[] str=buf.getString();\n      //byte[] tag=buf.getString();\n      throw new SftpException(i, Util.byte2str(str, UTF8));\n    }\n    else{\n      throw new SftpException(i, \"Failure\");\n    }\n  }\n\n  private static boolean isLocalAbsolutePath(String path){\n    return (new File(path)).isAbsolute();\n  }\n\n  public void disconnect(){\n    super.disconnect();\n  }\n\n  private boolean isPattern(String path, byte[][] utf8){\n    byte[] _path=Util.str2byte(path, UTF8);\n    if(utf8!=null)\n      utf8[0]=_path;\n    return isPattern(_path);\n  }\n\n  private boolean isPattern(String path){\n    return isPattern(path, null);\n  }\n\n  private void fill(Buffer buf, int len)  throws IOException{\n    buf.reset();\n    fill(buf.buffer, 0, len);\n    buf.skip(len);\n  }\n\n  private int fill(byte[] buf, int s, int len) throws IOException{\n    int i=0;\n    int foo=s;\n    while(len>0){\n      i=io_in.read(buf, s, len);\n      if(i<=0){\n        throw new IOException(\"inputstream is closed\");\n        //return (s-foo)==0 ? i : s-foo;\n      }\n      s+=i;\n      len-=i;\n    }\n    return s-foo;\n  }\n  private void skip(long foo) throws IOException{\n    while(foo>0){\n      long bar=io_in.skip(foo);\n      if(bar<=0) \n        break;\n      foo-=bar;\n    }\n  }\n\n  class Header{\n    int length;\n    int type;\n    int rid;\n  }\n  private Header header(Buffer buf, Header header) throws IOException{\n    buf.rewind();\n    int i=fill(buf.buffer, 0, 9);\n    header.length=buf.getInt()-5;\n    header.type=buf.getByte()&0xff;\n    header.rid=buf.getInt();  \n    return header;\n  }\n\n  private String remoteAbsolutePath(String path) throws SftpException{\n    if(path.charAt(0)=='/') return path;\n    String cwd=getCwd();\n//    if(cwd.equals(getHome())) return path;\n    if(cwd.endsWith(\"/\")) return cwd+path;\n    return cwd+\"/\"+path;\n  }\n\n  private String localAbsolutePath(String path){\n    if(isLocalAbsolutePath(path)) return path;\n    if(lcwd.endsWith(file_separator)) return lcwd+path;\n    return lcwd+file_separator+path;\n  }\n\n  /**\n   * This method will check if the given string can be expanded to the\n   * unique string.  If it can be expanded to mutiple files, SftpException\n   * will be thrown.\n   * @return the returned string is unquoted.\n   */\n  private String isUnique(String path) throws SftpException, Exception{\n    Vector v=glob_remote(path);\n    if(v.size()!=1){\n      throw new SftpException(SSH_FX_FAILURE, path+\" is not unique: \"+v.toString());\n    }\n    return (String)(v.elementAt(0));\n  }\n\n  public int getServerVersion() throws SftpException{\n    if(!isConnected()){\n      throw new SftpException(SSH_FX_FAILURE, \"The channel is not connected.\");\n    }\n    return server_version;\n  }\n\n  public void setFilenameEncoding(String encoding) throws SftpException{\n    int sversion=getServerVersion();\n    if(3 <= sversion && sversion <= 5 &&\n       !encoding.equals(UTF8)){\n      throw new SftpException(SSH_FX_FAILURE,\n                              \"The encoding can not be changed for this sftp server.\");\n    }\n    if(encoding.equals(UTF8)){\n      encoding=UTF8;\n    }\n    fEncoding=encoding;\n    fEncoding_is_utf8=fEncoding.equals(UTF8);\n  }\n\n  public String getExtension(String key){\n    if(extensions==null)\n      return null;\n    return (String)extensions.get(key);\n  }\n\n  public String realpath(String path) throws SftpException{\n    try{\n      byte[] _path=_realpath(remoteAbsolutePath(path));\n      return Util.byte2str(_path, fEncoding);\n    }\n    catch(Exception e){\n      if(e instanceof SftpException) throw (SftpException)e;\n      if(e instanceof Throwable)\n        throw new SftpException(SSH_FX_FAILURE, \"\", (Throwable)e);\n      throw new SftpException(SSH_FX_FAILURE, \"\");\n    }\n  }\n\n  public class LsEntry implements Comparable{\n    private  String filename;\n    private  String longname;\n    private  SftpATTRS attrs;\n    LsEntry(String filename, String longname, SftpATTRS attrs){\n      setFilename(filename);\n      setLongname(longname);\n      setAttrs(attrs);\n    }\n    public String getFilename(){return filename;};\n    void setFilename(String filename){this.filename = filename;};\n    public String getLongname(){return longname;};\n    void setLongname(String longname){this.longname = longname;};\n    public SftpATTRS getAttrs(){return attrs;};\n    void setAttrs(SftpATTRS attrs) {this.attrs = attrs;};\n    public String toString(){ return longname; }\n    public int compareTo(Object o) throws ClassCastException{\n      if(o instanceof LsEntry){\n        return filename.compareTo(((LsEntry)o).getFilename());\n      }\n      throw new ClassCastException(\"a decendent of LsEntry must be given.\");\n    }\n  }\n\n  /**\n   * This interface will be passed as an argument for <code>ls</code> method.\n   *\n   * @see ChannelSftp.LsEntry\n   * @see #ls(String, ChannelSftp.LsEntrySelector)\n   * @since 0.1.47\n   */\n  public interface LsEntrySelector {\n    public final int CONTINUE = 0;\n    public final int BREAK = 1;\n\n    /**\n     * <p> The <code>select</code> method will be invoked in <code>ls</code>\n     * method for each file entry. If this method returns BREAK,\n     * <code>ls</code> will be canceled.\n     * \n     * @param entry one of entry from ls\n     * @return if BREAK is returned, the 'ls' operation will be canceled.\n     */\n    public int select(LsEntry entry);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ChannelShell.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.util.*;\n\npublic class ChannelShell extends ChannelSession{\n\n  ChannelShell(){\n    super();\n    pty=true;\n  }\n\n  public void start() throws JSchException{\n    Session _session=getSession();\n    try{\n      sendRequests();\n\n      Request request=new RequestShell();\n      request.request(_session, this);\n    }\n    catch(Exception e){\n      if(e instanceof JSchException) throw (JSchException)e;\n      if(e instanceof Throwable)\n        throw new JSchException(\"ChannelShell\", (Throwable)e);\n      throw new JSchException(\"ChannelShell\");\n    }\n\n    if(io.in!=null){\n      thread=new Thread(this);\n      thread.setName(\"Shell for \"+_session.host);\n      if(_session.daemon_thread){\n        thread.setDaemon(_session.daemon_thread);\n      }\n      thread.start();\n    }\n  }\n\n  void init() throws JSchException {\n    io.setInputStream(getSession().in);\n    io.setOutputStream(getSession().out);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ChannelSubsystem.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2005-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class ChannelSubsystem extends ChannelSession{\n  boolean xforwading=false;\n  boolean pty=false;\n  boolean want_reply=true;\n  String subsystem=\"\";\n  public void setXForwarding(boolean foo){ xforwading=foo; }\n  public void setPty(boolean foo){ pty=foo; }\n  public void setWantReply(boolean foo){ want_reply=foo; }\n  public void setSubsystem(String foo){ subsystem=foo; }\n  public void start() throws JSchException{\n    Session _session=getSession();\n    try{\n      Request request;\n      if(xforwading){\n        request=new RequestX11();\n        request.request(_session, this);\n      }\n      if(pty){\n\trequest=new RequestPtyReq();\n\trequest.request(_session, this);\n      }\n      request=new RequestSubsystem();\n      ((RequestSubsystem)request).request(_session, this, subsystem, want_reply);\n    }\n    catch(Exception e){\n      if(e instanceof JSchException){ throw (JSchException)e; }\n      if(e instanceof Throwable)\n        throw new JSchException(\"ChannelSubsystem\", (Throwable)e);\n      throw new JSchException(\"ChannelSubsystem\");\n    }\n    if(io.in!=null){\n      thread=new Thread(this);\n      thread.setName(\"Subsystem for \"+_session.host);\n      if(_session.daemon_thread){\n        thread.setDaemon(_session.daemon_thread);\n      }\n      thread.start();\n    }\n  }\n\n  void init() throws JSchException {\n    io.setInputStream(getSession().in);\n    io.setOutputStream(getSession().out);\n  }\n\n  public void setErrStream(java.io.OutputStream out){\n    setExtOutputStream(out);\n  }\n  public java.io.InputStream getErrStream() throws java.io.IOException {\n    return getExtInputStream();\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ChannelX11.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.net.*;\n\nclass ChannelX11 extends Channel{\n\n  static private final int LOCAL_WINDOW_SIZE_MAX=0x20000;\n  static private final int LOCAL_MAXIMUM_PACKET_SIZE=0x4000;\n\n  static private final int TIMEOUT=10*1000;\n\n  private static String host=\"127.0.0.1\";\n  private static int port=6000;\n\n  private boolean init=true;\n\n  static byte[] cookie=null;\n  private static byte[] cookie_hex=null;\n\n  private static java.util.Hashtable faked_cookie_pool=new java.util.Hashtable();\n  private static java.util.Hashtable faked_cookie_hex_pool=new java.util.Hashtable();\n\n  private static byte[] table={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,\n                               0x61,0x62,0x63,0x64,0x65,0x66};\n\n  private Socket socket = null;\n\n  static int revtable(byte foo){\n    for(int i=0; i<table.length; i++){\n      if(table[i]==foo)return i;\n    }\n    return 0;\n  }\n  static void setCookie(String foo){\n    cookie_hex=Util.str2byte(foo); \n    cookie=new byte[16];\n    for(int i=0; i<16; i++){\n\tcookie[i]=(byte)(((revtable(cookie_hex[i*2])<<4)&0xf0) |\n\t\t\t ((revtable(cookie_hex[i*2+1]))&0xf));\n    }\n  }\n  static void setHost(String foo){ host=foo; }\n  static void setPort(int foo){ port=foo; }\n  static byte[] getFakedCookie(Session session){\n    synchronized(faked_cookie_hex_pool){\n      byte[] foo=(byte[])faked_cookie_hex_pool.get(session);\n      if(foo==null){\n\tRandom random=Session.random;\n\tfoo=new byte[16];\n\tsynchronized(random){\n\t  random.fill(foo, 0, 16);\n\t}\n/*\nSystem.err.print(\"faked_cookie: \");\nfor(int i=0; i<foo.length; i++){\n    System.err.print(Integer.toHexString(foo[i]&0xff)+\":\");\n}\nSystem.err.println(\"\");\n*/\n\tfaked_cookie_pool.put(session, foo);\n\tbyte[] bar=new byte[32];\n\tfor(int i=0; i<16; i++){\n\t  bar[2*i]=table[(foo[i]>>>4)&0xf];\n\t  bar[2*i+1]=table[(foo[i])&0xf];\n\t}\n\tfaked_cookie_hex_pool.put(session, bar);\n\tfoo=bar;\n      }\n      return foo;\n    }\n  }\n\n  static void removeFakedCookie(Session session){\n    synchronized(faked_cookie_hex_pool){\n      faked_cookie_hex_pool.remove(session);\n      faked_cookie_pool.remove(session);\n    }\n  }\n\n  ChannelX11(){\n    super();\n\n    setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX);\n    setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX);\n    setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE);\n\n    type=Util.str2byte(\"x11\");\n\n    connected=true;\n    /*\n    try{ \n      socket=Util.createSocket(host, port, TIMEOUT);\n      socket.setTcpNoDelay(true);\n      io=new IO();\n      io.setInputStream(socket.getInputStream());\n      io.setOutputStream(socket.getOutputStream());\n    }\n    catch(Exception e){\n      //System.err.println(e);\n    }\n    */\n  }\n\n  public void run(){\n\n    try{ \n      socket=Util.createSocket(host, port, TIMEOUT);\n      socket.setTcpNoDelay(true);\n      io=new IO();\n      io.setInputStream(socket.getInputStream());\n      io.setOutputStream(socket.getOutputStream());\n      sendOpenConfirmation();\n    }\n    catch(Exception e){\n      sendOpenFailure(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED);\n      close=true;\n      disconnect();\n      return;\n    }\n\n    thread=Thread.currentThread();\n    Buffer buf=new Buffer(rmpsize);\n    Packet packet=new Packet(buf);\n    int i=0;\n    try{\n      while(thread!=null &&\n            io!=null &&\n            io.in!=null){\n        i=io.in.read(buf.buffer, \n\t\t     14, \n\t\t     buf.buffer.length-14-Session.buffer_margin);\n\tif(i<=0){\n\t  eof();\n          break;\n\t}\n\tif(close)break;\n        packet.reset();\n        buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);\n        buf.putInt(recipient);\n        buf.putInt(i);\n        buf.skip(i);\n\tgetSession().write(packet, this, i);\n      }\n    }\n    catch(Exception e){\n      //System.err.println(e);\n    }\n    disconnect();\n  }\n\n  private byte[] cache=new byte[0];\n  private byte[] addCache(byte[] foo, int s, int l){\n    byte[] bar=new byte[cache.length+l];\n    System.arraycopy(foo, s, bar, cache.length, l);\n    if(cache.length>0)\n      System.arraycopy(cache, 0, bar, 0, cache.length);\n    cache=bar;\n    return cache;\n  }\n\n  void write(byte[] foo, int s, int l) throws java.io.IOException {\n    //if(eof_local)return;\n\n    if(init){\n\n      Session _session=null;\n      try{\n        _session=getSession();\n      }\n      catch(JSchException e){\n        throw new java.io.IOException(e.toString());\n      }\n\n      foo=addCache(foo, s, l);\n      s=0; \n      l=foo.length;\n\n      if(l<9)\n        return;\n\n      int plen=(foo[s+6]&0xff)*256+(foo[s+7]&0xff);\n      int dlen=(foo[s+8]&0xff)*256+(foo[s+9]&0xff);\n\n      if((foo[s]&0xff)==0x42){\n      }\n      else if((foo[s]&0xff)==0x6c){\n         plen=((plen>>>8)&0xff)|((plen<<8)&0xff00);\n         dlen=((dlen>>>8)&0xff)|((dlen<<8)&0xff00);\n      }\n      else{\n\t  // ??\n      }\n\n      if(l<12+plen+((-plen)&3)+dlen)\n        return;\n\n      byte[] bar=new byte[dlen];\n      System.arraycopy(foo, s+12+plen+((-plen)&3), bar, 0, dlen);\n      byte[] faked_cookie=null;\n\n      synchronized(faked_cookie_pool){\n\tfaked_cookie=(byte[])faked_cookie_pool.get(_session);\n      }\n\n      /*\nSystem.err.print(\"faked_cookie: \");\nfor(int i=0; i<faked_cookie.length; i++){\n    System.err.print(Integer.toHexString(faked_cookie[i]&0xff)+\":\");\n}\nSystem.err.println(\"\");\nSystem.err.print(\"bar: \");\nfor(int i=0; i<bar.length; i++){\n    System.err.print(Integer.toHexString(bar[i]&0xff)+\":\");\n}\nSystem.err.println(\"\");\n      */\n\n      if(equals(bar, faked_cookie)){\n        if(cookie!=null)\n          System.arraycopy(cookie, 0, foo, s+12+plen+((-plen)&3), dlen);\n      }\n      else{\n\t  //System.err.println(\"wrong cookie\");\n          thread=null;\n          eof();\n          io.close();\n          disconnect();\n      }\n      init=false;\n      io.put(foo, s, l);\n      cache=null;\n      return;\n    }\n    io.put(foo, s, l);\n  }\n\n  private static boolean equals(byte[] foo, byte[] bar){\n    if(foo.length!=bar.length)return false;\n    for(int i=0; i<foo.length; i++){\n      if(foo[i]!=bar[i])return false;\n    }\n    return true;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/Cipher.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface Cipher{\n  static int ENCRYPT_MODE=0;\n  static int DECRYPT_MODE=1;\n  int getIVSize(); \n  int getBlockSize(); \n  void init(int mode, byte[] key, byte[] iv) throws Exception; \n  void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception;\n  boolean isCBC();\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/CipherNone.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class CipherNone implements Cipher{\n  private static final int ivsize=8;\n  private static final int bsize=16;\n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n  }\n  public boolean isCBC(){return false; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/Compression.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface Compression{\n  static public final int INFLATER=0;\n  static public final int DEFLATER=1;\n  void init(int type, int level);\n  byte[] compress(byte[] buf, int start, int[] len);\n  byte[] uncompress(byte[] buf, int start, int[] len);\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ConfigRepository.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2013-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface ConfigRepository {\n\n  public Config getConfig(String host);\n\n  public interface Config {\n    public String getHostname();\n    public String getUser();\n    public int getPort();\n    public String getValue(String key);\n    public String[] getValues(String key);\n  }\n\n  static final Config defaultConfig = new Config() {\n    public String getHostname() {return null;}\n    public String getUser() {return null;}\n    public int getPort() {return -1;}\n    public String getValue(String key) {return null;}\n    public String[] getValues(String key) {return null;}\n  };\n\n  static final ConfigRepository nullConfig = new ConfigRepository(){\n    public Config getConfig(String host) { return defaultConfig; }\n  };\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/DH.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface DH{\n  void init() throws Exception;\n  void setP(byte[] p);\n  void setG(byte[] g);\n  byte[] getE() throws Exception;\n  void setF(byte[] f);\n  byte[] getK() throws Exception;\n\n  // checkRange() will check if e and f are in [1,p-1]\n  // as defined at https://tools.ietf.org/html/rfc4253#section-8\n  void checkRange() throws Exception;\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/DHEC256.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class DHEC256 extends DHECN {\n  public DHEC256(){\n    sha_name=\"sha-256\";\n    key_size=256;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/DHEC384.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class DHEC384 extends DHECN {\n  public DHEC384(){\n    sha_name=\"sha-384\";\n    key_size=384;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/DHEC521.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class DHEC521 extends DHECN {\n  public DHEC521(){\n    sha_name=\"sha-512\";\n    key_size=521;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/DHECN.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic abstract class DHECN extends KeyExchange{\n\n  private static final int SSH_MSG_KEX_ECDH_INIT =                 30;\n  private static final int SSH_MSG_KEX_ECDH_REPLY=                 31;\n  private int state;\n\n  byte[] Q_C;\n\n  byte[] V_S;\n  byte[] V_C;\n  byte[] I_S;\n  byte[] I_C;\n\n  byte[] e;\n\n  private Buffer buf;\n  private Packet packet;\n\n  private ECDH ecdh;\n\n  protected String sha_name; \n  protected int key_size;\n\n  public void init(Session session,\n\t\t   byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{\n    this.session=session;\n    this.V_S=V_S;      \n    this.V_C=V_C;      \n    this.I_S=I_S;      \n    this.I_C=I_C;      \n\n    try{\n      Class c=Class.forName(session.getConfig(sha_name));\n      sha=(HASH)(c.newInstance());\n      sha.init();\n    }\n    catch(Exception e){\n      System.err.println(e);\n    }\n\n    buf=new Buffer();\n    packet=new Packet(buf);\n\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_KEX_ECDH_INIT);\n\n    try{\n      Class c=Class.forName(session.getConfig(\"ecdh-sha2-nistp\"));\n      ecdh=(ECDH)(c.newInstance());\n      ecdh.init(key_size);\n\n      Q_C = ecdh.getQ();\n      buf.putString(Q_C);\n    }\n    catch(Exception e){\n      if(e instanceof Throwable)\n        throw new JSchException(e.toString(), (Throwable)e);\n      throw new JSchException(e.toString());\n    }\n\n    if(V_S==null){  // This is a really ugly hack for Session.checkKexes ;-(\n      return;\n    }\n\n    session.write(packet);\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"SSH_MSG_KEX_ECDH_INIT sent\");\n      JSch.getLogger().log(Logger.INFO, \n                           \"expecting SSH_MSG_KEX_ECDH_REPLY\");\n    }\n\n    state=SSH_MSG_KEX_ECDH_REPLY;\n  }\n\n  public boolean next(Buffer _buf) throws Exception{\n    int i,j;\n    switch(state){\n    case SSH_MSG_KEX_ECDH_REPLY:\n      // The server responds with:\n      // byte     SSH_MSG_KEX_ECDH_REPLY\n      // string   K_S, server's public host key\n      // string   Q_S, server's ephemeral public key octet string\n      // string   the signature on the exchange hash\n      j=_buf.getInt();\n      j=_buf.getByte();\n      j=_buf.getByte();\n      if(j!=31){\n\tSystem.err.println(\"type: must be 31 \"+j);\n\treturn false;\n      }\n\n      K_S=_buf.getString();\n\n      byte[] Q_S=_buf.getString();\n\n      byte[][] r_s = KeyPairECDSA.fromPoint(Q_S);\n\n      // RFC 5656,\n      // 4. ECDH Key Exchange\n      //   All elliptic curve public keys MUST be validated after they are\n      //   received.  An example of a validation algorithm can be found in\n      //   Section 3.2.2 of [SEC1].  If a key fails validation,\n      //   the key exchange MUST fail.\n      if(!ecdh.validate(r_s[0], r_s[1])){\n\treturn false;\n      }\n\n      K = ecdh.getSecret(r_s[0], r_s[1]);\n      K=normalize(K);\n\n      byte[] sig_of_H=_buf.getString();\n\n      //The hash H is computed as the HASH hash of the concatenation of the\n      //following:\n      // string   V_C, client's identification string (CR and LF excluded)\n      // string   V_S, server's identification string (CR and LF excluded)\n      // string   I_C, payload of the client's SSH_MSG_KEXINIT\n      // string   I_S, payload of the server's SSH_MSG_KEXINIT\n      // string   K_S, server's public host key\n      // string   Q_C, client's ephemeral public key octet string\n      // string   Q_S, server's ephemeral public key octet string\n      // mpint    K,   shared secret\n\n      // This value is called the exchange hash, and it is used to authenti-\n      // cate the key exchange.\n      buf.reset();\n      buf.putString(V_C); buf.putString(V_S);\n      buf.putString(I_C); buf.putString(I_S);\n      buf.putString(K_S);\n      buf.putString(Q_C); buf.putString(Q_S);\n      buf.putMPInt(K);\n      byte[] foo=new byte[buf.getLength()];\n      buf.getByte(foo);\n\n      sha.update(foo, 0, foo.length);\n      H=sha.digest();\n\n      i=0;\n      j=0;\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n\t((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      String alg=Util.byte2str(K_S, i, j);\n      i+=j;\n\n      boolean result = verify(alg, K_S, i, sig_of_H);\n\n      state=STATE_END;\n      return result;\n    }\n    return false;\n  }\n\n  public int getState(){return state; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/DHG1.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class DHG1 extends KeyExchange{\n\n  static final byte[] g={ 2 };\n  static final byte[] p={\n(byte)0x00,\n(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF, \n(byte)0xC9,(byte)0x0F,(byte)0xDA,(byte)0xA2,(byte)0x21,(byte)0x68,(byte)0xC2,(byte)0x34,\n(byte)0xC4,(byte)0xC6,(byte)0x62,(byte)0x8B,(byte)0x80,(byte)0xDC,(byte)0x1C,(byte)0xD1,\n(byte)0x29,(byte)0x02,(byte)0x4E,(byte)0x08,(byte)0x8A,(byte)0x67,(byte)0xCC,(byte)0x74,\n(byte)0x02,(byte)0x0B,(byte)0xBE,(byte)0xA6,(byte)0x3B,(byte)0x13,(byte)0x9B,(byte)0x22,\n(byte)0x51,(byte)0x4A,(byte)0x08,(byte)0x79,(byte)0x8E,(byte)0x34,(byte)0x04,(byte)0xDD,\n(byte)0xEF,(byte)0x95,(byte)0x19,(byte)0xB3,(byte)0xCD,(byte)0x3A,(byte)0x43,(byte)0x1B,\n(byte)0x30,(byte)0x2B,(byte)0x0A,(byte)0x6D,(byte)0xF2,(byte)0x5F,(byte)0x14,(byte)0x37,\n(byte)0x4F,(byte)0xE1,(byte)0x35,(byte)0x6D,(byte)0x6D,(byte)0x51,(byte)0xC2,(byte)0x45,\n(byte)0xE4,(byte)0x85,(byte)0xB5,(byte)0x76,(byte)0x62,(byte)0x5E,(byte)0x7E,(byte)0xC6,\n(byte)0xF4,(byte)0x4C,(byte)0x42,(byte)0xE9,(byte)0xA6,(byte)0x37,(byte)0xED,(byte)0x6B,\n(byte)0x0B,(byte)0xFF,(byte)0x5C,(byte)0xB6,(byte)0xF4,(byte)0x06,(byte)0xB7,(byte)0xED,\n(byte)0xEE,(byte)0x38,(byte)0x6B,(byte)0xFB,(byte)0x5A,(byte)0x89,(byte)0x9F,(byte)0xA5,\n(byte)0xAE,(byte)0x9F,(byte)0x24,(byte)0x11,(byte)0x7C,(byte)0x4B,(byte)0x1F,(byte)0xE6,\n(byte)0x49,(byte)0x28,(byte)0x66,(byte)0x51,(byte)0xEC,(byte)0xE6,(byte)0x53,(byte)0x81,\n(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF\n};\n\n  private static final int SSH_MSG_KEXDH_INIT=                     30;\n  private static final int SSH_MSG_KEXDH_REPLY=                    31;\n\n  private int state;\n\n  DH dh;\n\n  byte[] V_S;\n  byte[] V_C;\n  byte[] I_S;\n  byte[] I_C;\n\n  byte[] e;\n\n  private Buffer buf;\n  private Packet packet;\n\n  public void init(Session session,\n\t\t   byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{\n    this.session=session;\n    this.V_S=V_S;      \n    this.V_C=V_C;      \n    this.I_S=I_S;      \n    this.I_C=I_C;      \n\n    try{\n      Class c=Class.forName(session.getConfig(\"sha-1\"));\n      sha=(HASH)(c.newInstance());\n      sha.init();\n    }\n    catch(Exception e){\n      System.err.println(e);\n    }\n\n    buf=new Buffer();\n    packet=new Packet(buf);\n\n    try{\n      Class c=Class.forName(session.getConfig(\"dh\"));\n      dh=(DH)(c.newInstance());\n      dh.init();\n    }\n    catch(Exception e){\n      //System.err.println(e);\n      throw e;\n    }\n\n    dh.setP(p);\n    dh.setG(g);\n\n    // The client responds with:\n    // byte  SSH_MSG_KEXDH_INIT(30)\n    // mpint e <- g^x mod p\n    //         x is a random number (1 < x < (p-1)/2)\n\n    e=dh.getE();\n\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_KEXDH_INIT);\n    buf.putMPInt(e);\n    session.write(packet);\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"SSH_MSG_KEXDH_INIT sent\");\n      JSch.getLogger().log(Logger.INFO, \n                           \"expecting SSH_MSG_KEXDH_REPLY\");\n    }\n\n    state=SSH_MSG_KEXDH_REPLY;\n  }\n\n  public boolean next(Buffer _buf) throws Exception{\n    int i,j;\n\n    switch(state){\n    case SSH_MSG_KEXDH_REPLY:\n      // The server responds with:\n      // byte      SSH_MSG_KEXDH_REPLY(31)\n      // string    server public host key and certificates (K_S)\n      // mpint     f\n      // string    signature of H\n      j=_buf.getInt();\n      j=_buf.getByte();\n      j=_buf.getByte();\n      if(j!=31){\n\tSystem.err.println(\"type: must be 31 \"+j);\n\treturn false;\n      }\n\n      K_S=_buf.getString();\n\n      byte[] f=_buf.getMPInt();\n      byte[] sig_of_H=_buf.getString();\n\n      dh.setF(f);\n\n      dh.checkRange();\n\n      K=normalize(dh.getK());\n\n      //The hash H is computed as the HASH hash of the concatenation of the\n      //following:\n      // string    V_C, the client's version string (CR and NL excluded)\n      // string    V_S, the server's version string (CR and NL excluded)\n      // string    I_C, the payload of the client's SSH_MSG_KEXINIT\n      // string    I_S, the payload of the server's SSH_MSG_KEXINIT\n      // string    K_S, the host key\n      // mpint     e, exchange value sent by the client\n      // mpint     f, exchange value sent by the server\n      // mpint     K, the shared secret\n      // This value is called the exchange hash, and it is used to authenti-\n      // cate the key exchange.\n      buf.reset();\n      buf.putString(V_C); buf.putString(V_S);\n      buf.putString(I_C); buf.putString(I_S);\n      buf.putString(K_S);\n      buf.putMPInt(e); buf.putMPInt(f);\n      buf.putMPInt(K);\n      byte[] foo=new byte[buf.getLength()];\n      buf.getByte(foo);\n      sha.update(foo, 0, foo.length);\n      H=sha.digest();\n      //System.err.print(\"H -> \"); //dump(H, 0, H.length);\n\n      i=0;\n      j=0;\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n\t((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      String alg=Util.byte2str(K_S, i, j);\n      i+=j;\n\n      boolean result = verify(alg, K_S, i, sig_of_H);\n\n      state=STATE_END;\n      return result;\n    }\n    return false;\n  }\n\n  public int getState(){return state; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/DHG14.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class DHG14 extends KeyExchange{\n\n  static final byte[] g={ 2 };\n  static final byte[] p={\n(byte)0x00,\n(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,\n(byte)0xC9,(byte)0x0F,(byte)0xDA,(byte)0xA2,(byte)0x21,(byte)0x68,(byte)0xC2,(byte)0x34,\n(byte)0xC4,(byte)0xC6,(byte)0x62,(byte)0x8B,(byte)0x80,(byte)0xDC,(byte)0x1C,(byte)0xD1,\n(byte)0x29,(byte)0x02,(byte)0x4E,(byte)0x08,(byte)0x8A,(byte)0x67,(byte)0xCC,(byte)0x74,\n(byte)0x02,(byte)0x0B,(byte)0xBE,(byte)0xA6,(byte)0x3B,(byte)0x13,(byte)0x9B,(byte)0x22,\n(byte)0x51,(byte)0x4A,(byte)0x08,(byte)0x79,(byte)0x8E,(byte)0x34,(byte)0x04,(byte)0xDD,\n(byte)0xEF,(byte)0x95,(byte)0x19,(byte)0xB3,(byte)0xCD,(byte)0x3A,(byte)0x43,(byte)0x1B,\n(byte)0x30,(byte)0x2B,(byte)0x0A,(byte)0x6D,(byte)0xF2,(byte)0x5F,(byte)0x14,(byte)0x37,\n(byte)0x4F,(byte)0xE1,(byte)0x35,(byte)0x6D,(byte)0x6D,(byte)0x51,(byte)0xC2,(byte)0x45,\n(byte)0xE4,(byte)0x85,(byte)0xB5,(byte)0x76,(byte)0x62,(byte)0x5E,(byte)0x7E,(byte)0xC6,\n(byte)0xF4,(byte)0x4C,(byte)0x42,(byte)0xE9,(byte)0xA6,(byte)0x37,(byte)0xED,(byte)0x6B,\n(byte)0x0B,(byte)0xFF,(byte)0x5C,(byte)0xB6,(byte)0xF4,(byte)0x06,(byte)0xB7,(byte)0xED,\n(byte)0xEE,(byte)0x38,(byte)0x6B,(byte)0xFB,(byte)0x5A,(byte)0x89,(byte)0x9F,(byte)0xA5,\n(byte)0xAE,(byte)0x9F,(byte)0x24,(byte)0x11,(byte)0x7C,(byte)0x4B,(byte)0x1F,(byte)0xE6,\n(byte)0x49,(byte)0x28,(byte)0x66,(byte)0x51,(byte)0xEC,(byte)0xE4,(byte)0x5B,(byte)0x3D,\n(byte)0xC2,(byte)0x00,(byte)0x7C,(byte)0xB8,(byte)0xA1,(byte)0x63,(byte)0xBF,(byte)0x05,\n(byte)0x98,(byte)0xDA,(byte)0x48,(byte)0x36,(byte)0x1C,(byte)0x55,(byte)0xD3,(byte)0x9A,\n(byte)0x69,(byte)0x16,(byte)0x3F,(byte)0xA8,(byte)0xFD,(byte)0x24,(byte)0xCF,(byte)0x5F,\n(byte)0x83,(byte)0x65,(byte)0x5D,(byte)0x23,(byte)0xDC,(byte)0xA3,(byte)0xAD,(byte)0x96,\n(byte)0x1C,(byte)0x62,(byte)0xF3,(byte)0x56,(byte)0x20,(byte)0x85,(byte)0x52,(byte)0xBB,\n(byte)0x9E,(byte)0xD5,(byte)0x29,(byte)0x07,(byte)0x70,(byte)0x96,(byte)0x96,(byte)0x6D,\n(byte)0x67,(byte)0x0C,(byte)0x35,(byte)0x4E,(byte)0x4A,(byte)0xBC,(byte)0x98,(byte)0x04,\n(byte)0xF1,(byte)0x74,(byte)0x6C,(byte)0x08,(byte)0xCA,(byte)0x18,(byte)0x21,(byte)0x7C,\n(byte)0x32,(byte)0x90,(byte)0x5E,(byte)0x46,(byte)0x2E,(byte)0x36,(byte)0xCE,(byte)0x3B,\n(byte)0xE3,(byte)0x9E,(byte)0x77,(byte)0x2C,(byte)0x18,(byte)0x0E,(byte)0x86,(byte)0x03,\n(byte)0x9B,(byte)0x27,(byte)0x83,(byte)0xA2,(byte)0xEC,(byte)0x07,(byte)0xA2,(byte)0x8F,\n(byte)0xB5,(byte)0xC5,(byte)0x5D,(byte)0xF0,(byte)0x6F,(byte)0x4C,(byte)0x52,(byte)0xC9,\n(byte)0xDE,(byte)0x2B,(byte)0xCB,(byte)0xF6,(byte)0x95,(byte)0x58,(byte)0x17,(byte)0x18,\n(byte)0x39,(byte)0x95,(byte)0x49,(byte)0x7C,(byte)0xEA,(byte)0x95,(byte)0x6A,(byte)0xE5,\n(byte)0x15,(byte)0xD2,(byte)0x26,(byte)0x18,(byte)0x98,(byte)0xFA,(byte)0x05,(byte)0x10,\n(byte)0x15,(byte)0x72,(byte)0x8E,(byte)0x5A,(byte)0x8A,(byte)0xAC,(byte)0xAA,(byte)0x68,\n(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF\n};\n\n  private static final int SSH_MSG_KEXDH_INIT=                     30;\n  private static final int SSH_MSG_KEXDH_REPLY=                    31;\n\n  private int state;\n\n  DH dh;\n\n  byte[] V_S;\n  byte[] V_C;\n  byte[] I_S;\n  byte[] I_C;\n\n  byte[] e;\n\n  private Buffer buf;\n  private Packet packet;\n\n  public void init(Session session,\n\t\t   byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{\n    this.session=session;\n    this.V_S=V_S;      \n    this.V_C=V_C;      \n    this.I_S=I_S;      \n    this.I_C=I_C;      \n\n    try{\n      Class c=Class.forName(session.getConfig(\"sha-1\"));\n      sha=(HASH)(c.newInstance());\n      sha.init();\n    }\n    catch(Exception e){\n      System.err.println(e);\n    }\n\n    buf=new Buffer();\n    packet=new Packet(buf);\n\n    try{\n      Class c=Class.forName(session.getConfig(\"dh\"));\n      dh=(DH)(c.newInstance());\n      dh.init();\n    }\n    catch(Exception e){\n      //System.err.println(e);\n      throw e;\n    }\n\n    dh.setP(p);\n    dh.setG(g);\n    // The client responds with:\n    // byte  SSH_MSG_KEXDH_INIT(30)\n    // mpint e <- g^x mod p\n    //         x is a random number (1 < x < (p-1)/2)\n\n    e=dh.getE();\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_KEXDH_INIT);\n    buf.putMPInt(e);\n\n    if(V_S==null){  // This is a really ugly hack for Session.checkKexes ;-(\n      return;\n    }\n\n    session.write(packet);\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"SSH_MSG_KEXDH_INIT sent\");\n      JSch.getLogger().log(Logger.INFO, \n                           \"expecting SSH_MSG_KEXDH_REPLY\");\n    }\n\n    state=SSH_MSG_KEXDH_REPLY;\n  }\n\n  public boolean next(Buffer _buf) throws Exception{\n    int i,j;\n\n    switch(state){\n    case SSH_MSG_KEXDH_REPLY:\n      // The server responds with:\n      // byte      SSH_MSG_KEXDH_REPLY(31)\n      // string    server public host key and certificates (K_S)\n      // mpint     f\n      // string    signature of H\n      j=_buf.getInt();\n      j=_buf.getByte();\n      j=_buf.getByte();\n      if(j!=31){\n\tSystem.err.println(\"type: must be 31 \"+j);\n\treturn false;\n      }\n\n      K_S=_buf.getString();\n\n      byte[] f=_buf.getMPInt();\n      byte[] sig_of_H=_buf.getString();\n\n      dh.setF(f);\n\n      dh.checkRange();\n\n      K=normalize(dh.getK());\n\n      //The hash H is computed as the HASH hash of the concatenation of the\n      //following:\n      // string    V_C, the client's version string (CR and NL excluded)\n      // string    V_S, the server's version string (CR and NL excluded)\n      // string    I_C, the payload of the client's SSH_MSG_KEXINIT\n      // string    I_S, the payload of the server's SSH_MSG_KEXINIT\n      // string    K_S, the host key\n      // mpint     e, exchange value sent by the client\n      // mpint     f, exchange value sent by the server\n      // mpint     K, the shared secret\n      // This value is called the exchange hash, and it is used to authenti-\n      // cate the key exchange.\n      buf.reset();\n      buf.putString(V_C); buf.putString(V_S);\n      buf.putString(I_C); buf.putString(I_S);\n      buf.putString(K_S);\n      buf.putMPInt(e); buf.putMPInt(f);\n      buf.putMPInt(K);\n      byte[] foo=new byte[buf.getLength()];\n      buf.getByte(foo);\n      sha.update(foo, 0, foo.length);\n      H=sha.digest();\n      //System.err.print(\"H -> \"); //dump(H, 0, H.length);\n\n      i=0;\n      j=0;\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n\t((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      String alg=Util.byte2str(K_S, i, j);\n      i+=j;\n\n      boolean result = verify(alg, K_S, i, sig_of_H);\n\n      state=STATE_END;\n      return result;\n    }\n    return false;\n  }\n\n  public int getState(){return state; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/DHGEX.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class DHGEX extends KeyExchange{\n\n  private static final int SSH_MSG_KEX_DH_GEX_GROUP=               31;\n  private static final int SSH_MSG_KEX_DH_GEX_INIT=                32;\n  private static final int SSH_MSG_KEX_DH_GEX_REPLY=               33;\n  private static final int SSH_MSG_KEX_DH_GEX_REQUEST=             34;\n\n  static int min=1024;\n  static int preferred=1024;\n  int max=1024;\n\n  private int state;\n\n  DH dh;\n\n  byte[] V_S;\n  byte[] V_C;\n  byte[] I_S;\n  byte[] I_C;\n\n  private Buffer buf;\n  private Packet packet;\n\n  private byte[] p;\n  private byte[] g;\n  private byte[] e;\n\n  protected String hash=\"sha-1\";\n\n  public void init(Session session,\n\t\t   byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{\n    this.session=session;\n    this.V_S=V_S;      \n    this.V_C=V_C;      \n    this.I_S=I_S;      \n    this.I_C=I_C;      \n\n    try{\n      Class c=Class.forName(session.getConfig(hash));\n      sha=(HASH)(c.newInstance());\n      sha.init();\n    }\n    catch(Exception e){\n      System.err.println(e);\n    }\n\n    buf=new Buffer();\n    packet=new Packet(buf);\n\n    try{\n      Class c=Class.forName(session.getConfig(\"dh\"));\n      // Since JDK8, SunJCE has lifted the keysize restrictions\n      // from 1024 to 2048 for DH.\n      preferred = max = check2048(c, max); \n      dh=(com.jcraft.jsch.DH)(c.newInstance());\n      dh.init();\n    }\n    catch(Exception e){\n      throw e;\n    }\n\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_KEX_DH_GEX_REQUEST);\n    buf.putInt(min);\n    buf.putInt(preferred);\n    buf.putInt(max);\n    session.write(packet); \n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"SSH_MSG_KEX_DH_GEX_REQUEST(\"+min+\"<\"+preferred+\"<\"+max+\") sent\");\n      JSch.getLogger().log(Logger.INFO, \n                           \"expecting SSH_MSG_KEX_DH_GEX_GROUP\");\n    }\n\n    state=SSH_MSG_KEX_DH_GEX_GROUP;\n  }\n\n  public boolean next(Buffer _buf) throws Exception{\n    int i,j;\n    switch(state){\n    case SSH_MSG_KEX_DH_GEX_GROUP:\n      // byte  SSH_MSG_KEX_DH_GEX_GROUP(31)\n      // mpint p, safe prime\n      // mpint g, generator for subgroup in GF (p)\n      _buf.getInt();\n      _buf.getByte();\n      j=_buf.getByte();\n      if(j!=SSH_MSG_KEX_DH_GEX_GROUP){\n\tSystem.err.println(\"type: must be SSH_MSG_KEX_DH_GEX_GROUP \"+j);\n\treturn false;\n      }\n\n      p=_buf.getMPInt();\n      g=_buf.getMPInt();\n\n      dh.setP(p);\n      dh.setG(g);\n      // The client responds with:\n      // byte  SSH_MSG_KEX_DH_GEX_INIT(32)\n      // mpint e <- g^x mod p\n      //         x is a random number (1 < x < (p-1)/2)\n\n      e=dh.getE();\n\n      packet.reset();\n      buf.putByte((byte)SSH_MSG_KEX_DH_GEX_INIT);\n      buf.putMPInt(e);\n      session.write(packet);\n\n      if(JSch.getLogger().isEnabled(Logger.INFO)){\n        JSch.getLogger().log(Logger.INFO, \n                             \"SSH_MSG_KEX_DH_GEX_INIT sent\");\n        JSch.getLogger().log(Logger.INFO, \n                             \"expecting SSH_MSG_KEX_DH_GEX_REPLY\");\n      }\n\n      state=SSH_MSG_KEX_DH_GEX_REPLY;\n      return true;\n      //break;\n\n    case SSH_MSG_KEX_DH_GEX_REPLY:\n      // The server responds with:\n      // byte      SSH_MSG_KEX_DH_GEX_REPLY(33)\n      // string    server public host key and certificates (K_S)\n      // mpint     f\n      // string    signature of H\n      j=_buf.getInt();\n      j=_buf.getByte();\n      j=_buf.getByte();\n      if(j!=SSH_MSG_KEX_DH_GEX_REPLY){\n\tSystem.err.println(\"type: must be SSH_MSG_KEX_DH_GEX_REPLY \"+j);\n\treturn false;\n      }\n\n      K_S=_buf.getString();\n\n      byte[] f=_buf.getMPInt();\n      byte[] sig_of_H=_buf.getString();\n\n      dh.setF(f);\n\n      dh.checkRange();\n\n      K=normalize(dh.getK());\n\n      //The hash H is computed as the HASH hash of the concatenation of the\n      //following:\n      // string    V_C, the client's version string (CR and NL excluded)\n      // string    V_S, the server's version string (CR and NL excluded)\n      // string    I_C, the payload of the client's SSH_MSG_KEXINIT\n      // string    I_S, the payload of the server's SSH_MSG_KEXINIT\n      // string    K_S, the host key\n      // uint32    min, minimal size in bits of an acceptable group\n      // uint32   n, preferred size in bits of the group the server should send\n      // uint32    max, maximal size in bits of an acceptable group\n      // mpint     p, safe prime\n      // mpint     g, generator for subgroup\n      // mpint     e, exchange value sent by the client\n      // mpint     f, exchange value sent by the server\n      // mpint     K, the shared secret\n      // This value is called the exchange hash, and it is used to authenti-\n      // cate the key exchange.\n\n      buf.reset();\n      buf.putString(V_C); buf.putString(V_S);\n      buf.putString(I_C); buf.putString(I_S);\n      buf.putString(K_S);\n      buf.putInt(min); buf.putInt(preferred); buf.putInt(max);\n      buf.putMPInt(p); buf.putMPInt(g); buf.putMPInt(e); buf.putMPInt(f);\n      buf.putMPInt(K);\n\n      byte[] foo=new byte[buf.getLength()];\n      buf.getByte(foo);\n      sha.update(foo, 0, foo.length);\n\n      H=sha.digest();\n\n      // System.err.print(\"H -> \"); dump(H, 0, H.length);\n\n      i=0;\n      j=0;\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n\t((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      String alg=Util.byte2str(K_S, i, j);\n      i+=j;\n\n      boolean result = verify(alg, K_S, i, sig_of_H);\n\n      state=STATE_END;\n      return result;\n    }\n    return false;\n  }\n\n  public int getState(){return state; }\n\n  protected int check2048(Class c, int _max) throws Exception {\n    DH dh=(com.jcraft.jsch.DH)(c.newInstance());\n    dh.init();\n    byte[] foo = new byte[257];\n    foo[1]=(byte)0xdd;\n    foo[256]=0x73;\n    dh.setP(foo);\n    byte[] bar = {(byte)0x02};\n    dh.setG(bar);\n    try {\n      dh.getE();\n      _max=2048;\n    }\n    catch(Exception e){ }\n    return _max;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/DHGEX256.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class DHGEX256 extends DHGEX {\n  DHGEX256(){\n    hash=\"sha-256\";\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ECDH.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface ECDH {\n  void init(int size) throws Exception;\n  byte[] getSecret(byte[] r, byte[] s) throws Exception;\n  byte[] getQ() throws Exception;\n  boolean validate(byte[] r, byte[] s) throws Exception;\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ForwardedTCPIPDaemon.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\nimport java.io.*;\n\npublic interface ForwardedTCPIPDaemon extends Runnable{\n  void setChannel(ChannelForwardedTCPIP channel, InputStream in, OutputStream out);\n  void setArg(Object[] arg);\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/GSSContext.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2004-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface GSSContext{\n  public void create(String user, String host) throws JSchException;\n  public boolean isEstablished();\n  public byte[] init(byte[] token, int s, int l) throws JSchException;\n  public byte[] getMIC(byte[] message, int s, int l);\n  public void dispose();\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/HASH.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface HASH{\n  void init() throws Exception;\n  int getBlockSize();\n  void update(byte[] foo, int start, int len) throws Exception;\n  byte[] digest() throws Exception;\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/HostKey.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class HostKey{\n\n  private static final byte[][] names = {\n    Util.str2byte(\"ssh-dss\"),\n    Util.str2byte(\"ssh-rsa\"),\n    Util.str2byte(\"ecdsa-sha2-nistp256\"),\n    Util.str2byte(\"ecdsa-sha2-nistp384\"),\n    Util.str2byte(\"ecdsa-sha2-nistp521\")\n  };\n\n  protected static final int GUESS=0;\n  public static final int SSHDSS=1;\n  public static final int SSHRSA=2;\n  public static final int ECDSA256=3;\n  public static final int ECDSA384=4;\n  public static final int ECDSA521=5;\n  static final int UNKNOWN=6;\n\n  protected String marker;\n  protected String host;\n  protected int type;\n  protected byte[] key;\n  protected String comment;\n\n  public HostKey(String host, byte[] key) throws JSchException {\n    this(host, GUESS, key);\n  }\n\n  public HostKey(String host, int type, byte[] key) throws JSchException {\n    this(host, type, key, null);\n  }\n  public HostKey(String host, int type, byte[] key, String comment) throws JSchException {\n    this(\"\", host, type, key, comment);\n  }\n  public HostKey(String marker, String host, int type, byte[] key, String comment) throws JSchException {\n    this.marker=marker;\n    this.host=host; \n    if(type==GUESS){\n      if(key[8]=='d'){ this.type=SSHDSS; }\n      else if(key[8]=='r'){ this.type=SSHRSA; }\n      else if(key[8]=='a' && key[20]=='2'){ this.type=ECDSA256; }\n      else if(key[8]=='a' && key[20]=='3'){ this.type=ECDSA384; }\n      else if(key[8]=='a' && key[20]=='5'){ this.type=ECDSA521; }\n      else { throw new JSchException(\"invalid key type\");}\n    }\n    else{\n      this.type=type; \n    }\n    this.key=key;\n    this.comment=comment;\n  }\n\n  public String getHost(){ return host; }\n  public String getType(){\n    if(type==SSHDSS ||\n       type==SSHRSA ||\n       type==ECDSA256 ||\n       type==ECDSA384 ||\n       type==ECDSA521){\n      return Util.byte2str(names[type-1]);\n    }\n    return \"UNKNOWN\";\n  }\n  protected static int name2type(String name){\n    for(int i = 0; i < names.length; i++){\n      if(Util.byte2str(names[i]).equals(name)){\n        return i + 1;\n      }\n    }\n    return UNKNOWN;\n  }\n  public String getKey(){\n    return Util.byte2str(Util.toBase64(key, 0, key.length));\n  }\n  @SuppressWarnings({\"static\"}) public String getFingerPrint(JSch jsch){\n    HASH hash=null;\n    try{\n      Class c=Class.forName(jsch.getConfig(\"md5\"));\n      hash=(HASH)(c.newInstance());\n    }\n    catch(Exception e){ System.err.println(\"getFingerPrint: \"+e); }\n    return Util.getFingerPrint(hash, key);\n  }\n  public String getComment(){ return comment; }\n  public String getMarker(){ return marker; }\n\n  boolean isMatched(String _host){\n    return isIncluded(_host);\n  }\n\n  private boolean isIncluded(String _host){\n    int i=0;\n    String hosts=this.host; \n    int hostslen=hosts.length();\n    int hostlen=_host.length();\n    int j;\n    while(i<hostslen){\n      j=hosts.indexOf(',', i);\n      if(j==-1){\n       if(hostlen!=hostslen-i) return false;\n       return hosts.regionMatches(true, i, _host, 0, hostlen);\n      }\n      if(hostlen==(j-i)){\n\tif(hosts.regionMatches(true, i, _host, 0, hostlen)) return true;\n      }\n      i=j+1;\n    }\n    return false;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/HostKeyRepository.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2004-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface HostKeyRepository{\n  final int OK=0;\n  final int NOT_INCLUDED=1;\n  final int CHANGED=2;\n\n  /**\n   * Checks if <code>host</code> is included with the <code>key</code>. \n   * \n   * @return #NOT_INCLUDED, #OK or #CHANGED\n   * @see #NOT_INCLUDED\n   * @see #OK\n   * @see #CHANGED\n   */\n  int check(String host, byte[] key);\n\n  /**\n   * Adds a host key <code>hostkey</code>\n   *\n   * @param hostkey a host key to be added\n   * @param ui a user interface for showing messages or promping inputs.\n   * @see UserInfo\n   */\n  void add(HostKey hostkey, UserInfo ui);\n\n  /**\n   * Removes a host key if there exists mached key with\n   * <code>host</code>, <code>type</code>.\n   *\n   * @see #remove(String host, String type, byte[] key)\n   */\n  void remove(String host, String type);\n\n  /**\n   * Removes a host key if there exists a matched key with\n   * <code>host</code>, <code>type</code> and <code>key</code>.\n   */\n  void remove(String host, String type, byte[] key);\n\n  /**\n   * Returns id of this repository.\n   *\n   * @return identity in String\n   */\n  String getKnownHostsRepositoryID();\n\n  /**\n   * Retuns a list for host keys managed in this repository.\n   *\n   * @see #getHostKey(String host, String type)\n   */\n  HostKey[] getHostKey();\n\n  /**\n   * Retuns a list for host keys managed in this repository.\n   *\n   * @param host a hostname used in searching host keys.\n   *        If <code>null</code> is given, every host key will be listed.\n   * @param type a key type used in searching host keys,\n   *        and it should be \"ssh-dss\" or \"ssh-rsa\".\n   *        If <code>null</code> is given, a key type type will not be ignored.\n   */\n  HostKey[] getHostKey(String host, String type);\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/IO.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.*;\n\npublic class IO{\n  InputStream in;\n  OutputStream out;\n  OutputStream out_ext;\n\n  private boolean in_dontclose=false;\n  private boolean out_dontclose=false;\n  private boolean out_ext_dontclose=false;\n\n  void setOutputStream(OutputStream out){ this.out=out; }\n  void setOutputStream(OutputStream out, boolean dontclose){\n    this.out_dontclose=dontclose;\n    setOutputStream(out);\n  }\n  void setExtOutputStream(OutputStream out){ this.out_ext=out; }\n  void setExtOutputStream(OutputStream out, boolean dontclose){\n    this.out_ext_dontclose=dontclose;\n    setExtOutputStream(out);\n  }\n  void setInputStream(InputStream in){ this.in=in; }\n  void setInputStream(InputStream in, boolean dontclose){\n    this.in_dontclose=dontclose;\n    setInputStream(in);\n  }\n\n  public void put(Packet p) throws IOException, java.net.SocketException {\n    out.write(p.buffer.buffer, 0, p.buffer.index);\n    out.flush();\n  }\n  void put(byte[] array, int begin, int length) throws IOException {\n    out.write(array, begin, length);\n    out.flush();\n  }\n  void put_ext(byte[] array, int begin, int length) throws IOException {\n    out_ext.write(array, begin, length);\n    out_ext.flush();\n  }\n\n  int getByte() throws IOException {\n    return in.read();\n  }\n\n  void getByte(byte[] array) throws IOException {\n    getByte(array, 0, array.length);\n  }\n\n  void getByte(byte[] array, int begin, int length) throws IOException {\n    do{\n      int completed = in.read(array, begin, length);\n      if(completed<0){\n\tthrow new IOException(\"End of IO Stream Read\");\n      }\n      begin+=completed;\n      length-=completed;\n    }\n    while (length>0);\n  }\n\n  void out_close(){\n    try{\n      if(out!=null && !out_dontclose) out.close();\n      out=null;\n    }\n    catch(Exception ee){}\n  }\n\n  public void close(){\n    try{\n      if(in!=null && !in_dontclose) in.close();\n      in=null;\n    }\n    catch(Exception ee){}\n\n    out_close();\n\n    try{\n      if(out_ext!=null && !out_ext_dontclose) out_ext.close();\n      out_ext=null;\n    }\n    catch(Exception ee){}\n  }\n\n  /*\n  public void finalize() throws Throwable{\n    try{\n      if(in!=null) in.close();\n    }\n    catch(Exception ee){}\n    try{\n      if(out!=null) out.close();\n    }\n    catch(Exception ee){}\n    try{\n      if(out_ext!=null) out_ext.close();\n    }\n    catch(Exception ee){}\n  }\n  */\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/Identity.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface Identity{\n\n  /**\n   * Decrypts this identity with the specified pass-phrase.\n   * @param passphrase the pass-phrase for this identity.\n   * @return <tt>true</tt> if the decryption is succeeded\n   * or this identity is not cyphered.\n   */\n  public boolean setPassphrase(byte[] passphrase) throws JSchException;\n\n  /**\n   * Returns the public-key blob.\n   * @return the public-key blob\n   */\n  public byte[] getPublicKeyBlob();\n\n  /**\n   * Signs on data with this identity, and returns the result.\n   * @param data data to be signed\n   * @return the signature\n   */\n  public byte[] getSignature(byte[] data);\n\n  /**\n   * @deprecated The decryption should be done automatically in #setPassphase(byte[] passphrase)\n   * @see #setPassphrase(byte[] passphrase)\n   */\n  public boolean decrypt();\n\n  /**\n   * Returns the name of the key algorithm.\n   * @return \"ssh-rsa\" or \"ssh-dss\"\n   */\n  public String getAlgName();\n\n  /**\n   * Returns the name of this identity. \n   * It will be useful to identify this object in the {@link IdentityRepository}.\n   */\n  public String getName();\n\n  /**\n   * Returns <tt>true</tt> if this identity is cyphered.\n   * @return <tt>true</tt> if this identity is cyphered.\n   */\n  public boolean isEncrypted();\n\n  /**\n   * Disposes internally allocated data, like byte array for the private key.\n   */\n  public void clear();\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/IdentityFile.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.*;\n\nclass IdentityFile implements Identity{\n  private JSch jsch;\n  private KeyPair kpair;\n  private String identity;\n\n  static IdentityFile newInstance(String prvfile, String pubfile, JSch jsch) throws JSchException{\n    KeyPair kpair = KeyPair.load(jsch, prvfile, pubfile);\n    return new IdentityFile(jsch, prvfile, kpair);\n  }\n\n  static IdentityFile newInstance(String name, byte[] prvkey, byte[] pubkey, JSch jsch) throws JSchException{\n\n    KeyPair kpair = KeyPair.load(jsch, prvkey, pubkey);\n    return new IdentityFile(jsch, name, kpair);\n  }\n\n  private IdentityFile(JSch jsch, String name, KeyPair kpair) throws JSchException{\n    this.jsch = jsch;\n    this.identity = name;\n    this.kpair = kpair;\n  }\n\n  /**\n   * Decrypts this identity with the specified pass-phrase.\n   * @param passphrase the pass-phrase for this identity.\n   * @return <tt>true</tt> if the decryption is succeeded\n   * or this identity is not cyphered.\n   */\n  public boolean setPassphrase(byte[] passphrase) throws JSchException{\n    return kpair.decrypt(passphrase);\n  }\n\n  /**\n   * Returns the public-key blob.\n   * @return the public-key blob\n   */\n  public byte[] getPublicKeyBlob(){\n    return kpair.getPublicKeyBlob();\n  }\n\n  /**\n   * Signs on data with this identity, and returns the result.\n   * @param data data to be signed\n   * @return the signature\n   */\n  public byte[] getSignature(byte[] data){\n    return kpair.getSignature(data);\n  }\n\n  /**\n   * @deprecated This method should not be invoked.\n   * @see #setPassphrase(byte[] passphrase)\n   */\n  public boolean decrypt(){\n    throw new RuntimeException(\"not implemented\");\n  }\n\n  /**\n   * Returns the name of the key algorithm.\n   * @return \"ssh-rsa\" or \"ssh-dss\"\n   */\n  public String getAlgName(){\n    return new String(kpair.getKeyTypeName());\n  }\n\n  /**\n   * Returns the name of this identity. \n   * It will be useful to identify this object in the {@link IdentityRepository}.\n   */\n  public String getName(){\n    return identity;\n  }\n\n  /**\n   * Returns <tt>true</tt> if this identity is cyphered.\n   * @return <tt>true</tt> if this identity is cyphered.\n   */\n  public boolean isEncrypted(){\n    return kpair.isEncrypted();\n  }\n\n  /**\n   * Disposes internally allocated data, like byte array for the private key.\n   */\n  public void clear(){\n    kpair.dispose();\n    kpair = null;\n  }\n\n  /**\n   * Returns an instance of {@link KeyPair} used in this {@link Identity}.\n   * @return an instance of {@link KeyPair} used in this {@link Identity}.\n   */\n  public KeyPair getKeyPair(){\n    return kpair;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/IdentityRepository.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2012-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.util.Vector;\n\npublic interface IdentityRepository {\n  public static final int UNAVAILABLE=0;\n  public static final int NOTRUNNING=1;\n  public static final int RUNNING=2;\n  public String getName();\n  public int getStatus();\n  public Vector getIdentities();\n  public boolean add(byte[] identity);\n  public boolean remove(byte[] blob);\n  public void removeAll();\n\n  /**\n   * JSch will accept ciphered keys, but some implementations of\n   * IdentityRepository can not.  For example, IdentityRepository for\n   * ssh-agent and pageant only accept plain keys.  The following class has\n   * been introduced to cache ciphered keys for them, and pass them\n   * whenever they are de-ciphered.\n   */\n  static class Wrapper implements IdentityRepository {\n    private IdentityRepository ir;\n    private Vector cache = new Vector();\n    private boolean keep_in_cache = false;\n    Wrapper(IdentityRepository ir){\n      this(ir, false);\n    }\n    Wrapper(IdentityRepository ir, boolean keep_in_cache){\n      this.ir = ir;\n      this.keep_in_cache = keep_in_cache;\n    }\n    public String getName() {\n      return ir.getName();\n    }\n    public int getStatus() {\n      return ir.getStatus();\n    }\n    public boolean add(byte[] identity) {\n      return ir.add(identity);\n    }\n    public boolean remove(byte[] blob) {\n      return ir.remove(blob);\n    }\n    public void removeAll() {\n      cache.removeAllElements();\n      ir.removeAll();\n    }\n    public Vector getIdentities() {\n      Vector result = new Vector();\n      for(int i = 0; i< cache.size(); i++){\n        Identity identity = (Identity)(cache.elementAt(i));\n        result.add(identity);\n      }\n      Vector tmp = ir.getIdentities();\n      for(int i = 0; i< tmp.size(); i++){\n        result.add(tmp.elementAt(i));\n      }\n      return result;\n    }\n    void add(Identity identity) {\n      if(!keep_in_cache && \n         !identity.isEncrypted() && (identity instanceof IdentityFile)) {\n        try {\n          ir.add(((IdentityFile)identity).getKeyPair().forSSHAgent());\n        }\n        catch(JSchException e){\n          // an exception will not be thrown.\n        }\n      }\n      else\n        cache.addElement(identity);\n    }\n    void check() {\n      if(cache.size() > 0){\n        Object[] identities = cache.toArray();\n        for(int i = 0; i < identities.length; i++){\n          Identity identity = (Identity)(identities[i]);\n          cache.removeElement(identity);\n          add(identity);\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/JSch.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.InputStream;\nimport java.util.Vector;\n\npublic class JSch{\n  /**\n   * The version number.\n   */\n  public static final String VERSION  = \"0.1.53\";\n\n  static java.util.Hashtable config=new java.util.Hashtable();\n  static{\n    config.put(\"kex\", \"ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1\");\n    config.put(\"server_host_key\", \"ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521\");\n    config.put(\"cipher.s2c\", \n               \"aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc\");\n    config.put(\"cipher.c2s\",\n               \"aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc\");\n\n    config.put(\"mac.s2c\", \"hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96\");\n    config.put(\"mac.c2s\", \"hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96\");\n    config.put(\"compression.s2c\", \"none\");\n    config.put(\"compression.c2s\", \"none\");\n\n    config.put(\"lang.s2c\", \"\");\n    config.put(\"lang.c2s\", \"\");\n\n    config.put(\"compression_level\", \"6\");\n\n    config.put(\"diffie-hellman-group-exchange-sha1\", \n                                \"com.jcraft.jsch.DHGEX\");\n    config.put(\"diffie-hellman-group1-sha1\", \n\t                        \"com.jcraft.jsch.DHG1\");\n    config.put(\"diffie-hellman-group14-sha1\", \n               \"com.jcraft.jsch.DHG14\");    // available since JDK8.\n    config.put(\"diffie-hellman-group-exchange-sha256\", \n               \"com.jcraft.jsch.DHGEX256\"); // available since JDK1.4.2.\n                                            // On JDK8, 2048bits will be used.\n    config.put(\"ecdsa-sha2-nistp256\", \"com.jcraft.jsch.jce.SignatureECDSA\");\n    config.put(\"ecdsa-sha2-nistp384\", \"com.jcraft.jsch.jce.SignatureECDSA\");\n    config.put(\"ecdsa-sha2-nistp521\", \"com.jcraft.jsch.jce.SignatureECDSA\");\n\n    config.put(\"ecdh-sha2-nistp256\", \"com.jcraft.jsch.DHEC256\");\n    config.put(\"ecdh-sha2-nistp384\", \"com.jcraft.jsch.DHEC384\");\n    config.put(\"ecdh-sha2-nistp521\", \"com.jcraft.jsch.DHEC521\");\n\n    config.put(\"ecdh-sha2-nistp\", \"com.jcraft.jsch.jce.ECDHN\");\n\n    config.put(\"dh\",            \"com.jcraft.jsch.jce.DH\");\n    config.put(\"3des-cbc\",      \"com.jcraft.jsch.jce.TripleDESCBC\");\n    config.put(\"blowfish-cbc\",  \"com.jcraft.jsch.jce.BlowfishCBC\");\n    config.put(\"hmac-sha1\",     \"com.jcraft.jsch.jce.HMACSHA1\");\n    config.put(\"hmac-sha1-96\",  \"com.jcraft.jsch.jce.HMACSHA196\");\n    config.put(\"hmac-sha2-256\",  \"com.jcraft.jsch.jce.HMACSHA256\");\n    // The \"hmac-sha2-512\" will require the key-length 2048 for DH,\n    // but Sun's JCE has not allowed to use such a long key.\n    //config.put(\"hmac-sha2-512\",  \"com.jcraft.jsch.jce.HMACSHA512\");\n    config.put(\"hmac-md5\",      \"com.jcraft.jsch.jce.HMACMD5\");\n    config.put(\"hmac-md5-96\",   \"com.jcraft.jsch.jce.HMACMD596\");\n    config.put(\"sha-1\",         \"com.jcraft.jsch.jce.SHA1\");\n    config.put(\"sha-256\",         \"com.jcraft.jsch.jce.SHA256\");\n    config.put(\"sha-384\",         \"com.jcraft.jsch.jce.SHA384\");\n    config.put(\"sha-512\",         \"com.jcraft.jsch.jce.SHA512\");\n    config.put(\"md5\",           \"com.jcraft.jsch.jce.MD5\");\n    config.put(\"signature.dss\", \"com.jcraft.jsch.jce.SignatureDSA\");\n    config.put(\"signature.rsa\", \"com.jcraft.jsch.jce.SignatureRSA\");\n    config.put(\"signature.ecdsa\", \"com.jcraft.jsch.jce.SignatureECDSA\");\n    config.put(\"keypairgen.dsa\",   \"com.jcraft.jsch.jce.KeyPairGenDSA\");\n    config.put(\"keypairgen.rsa\",   \"com.jcraft.jsch.jce.KeyPairGenRSA\");\n    config.put(\"keypairgen.ecdsa\", \"com.jcraft.jsch.jce.KeyPairGenECDSA\");\n    config.put(\"random\",        \"com.jcraft.jsch.jce.Random\");\n\n    config.put(\"none\",           \"com.jcraft.jsch.CipherNone\");\n\n    config.put(\"aes128-cbc\",    \"com.jcraft.jsch.jce.AES128CBC\");\n    config.put(\"aes192-cbc\",    \"com.jcraft.jsch.jce.AES192CBC\");\n    config.put(\"aes256-cbc\",    \"com.jcraft.jsch.jce.AES256CBC\");\n\n    config.put(\"aes128-ctr\",    \"com.jcraft.jsch.jce.AES128CTR\");\n    config.put(\"aes192-ctr\",    \"com.jcraft.jsch.jce.AES192CTR\");\n    config.put(\"aes256-ctr\",    \"com.jcraft.jsch.jce.AES256CTR\");\n    config.put(\"3des-ctr\",      \"com.jcraft.jsch.jce.TripleDESCTR\");\n    config.put(\"arcfour\",      \"com.jcraft.jsch.jce.ARCFOUR\");\n    config.put(\"arcfour128\",      \"com.jcraft.jsch.jce.ARCFOUR128\");\n    config.put(\"arcfour256\",      \"com.jcraft.jsch.jce.ARCFOUR256\");\n\n    config.put(\"userauth.none\",    \"com.jcraft.jsch.UserAuthNone\");\n    config.put(\"userauth.password\",    \"com.jcraft.jsch.UserAuthPassword\");\n    config.put(\"userauth.keyboard-interactive\",    \"com.jcraft.jsch.UserAuthKeyboardInteractive\");\n    config.put(\"userauth.publickey\",    \"com.jcraft.jsch.UserAuthPublicKey\");\n    config.put(\"userauth.gssapi-with-mic\",    \"com.jcraft.jsch.UserAuthGSSAPIWithMIC\");\n    config.put(\"gssapi-with-mic.krb5\",    \"com.jcraft.jsch.jgss.GSSContextKrb5\");\n\n    config.put(\"zlib\",             \"com.jcraft.jsch.jcraft.Compression\");\n    config.put(\"zlib@openssh.com\", \"com.jcraft.jsch.jcraft.Compression\");\n\n    config.put(\"pbkdf\", \"com.jcraft.jsch.jce.PBKDF\");\n\n    config.put(\"StrictHostKeyChecking\",  \"ask\");\n    config.put(\"HashKnownHosts\",  \"no\");\n\n    config.put(\"PreferredAuthentications\", \"gssapi-with-mic,publickey,keyboard-interactive,password\");\n\n    config.put(\"CheckCiphers\", \"aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256\");\n    config.put(\"CheckKexes\", \"diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521\");\n    config.put(\"CheckSignatures\", \"ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521\");\n\n    config.put(\"MaxAuthTries\", \"6\");\n    config.put(\"ClearAllForwardings\", \"no\");\n  }\n\n  private java.util.Vector sessionPool = new java.util.Vector();\n\n  private IdentityRepository defaultIdentityRepository =\n    new LocalIdentityRepository(this);\n\n  private IdentityRepository identityRepository = defaultIdentityRepository;\n\n  private ConfigRepository configRepository = null;\n\n  /**\n   * Sets the <code>identityRepository</code>, which will be referred\n   * in the public key authentication.\n   *\n   * @param identityRepository if <code>null</code> is given,\n   * the default repository, which usually refers to ~/.ssh/, will be used.\n   *\n   * @see #getIdentityRepository()\n   */\n  public synchronized void setIdentityRepository(IdentityRepository identityRepository){\n    if(identityRepository == null){\n      this.identityRepository = defaultIdentityRepository;\n    }\n    else{\n      this.identityRepository = identityRepository;\n    }\n  }\n\n  public synchronized IdentityRepository getIdentityRepository(){\n    return this.identityRepository;\n  }\n\n  public ConfigRepository getConfigRepository() {\n    return this.configRepository;\n  }\n\n  public void setConfigRepository(ConfigRepository configRepository) {\n    this.configRepository = configRepository;\n  }\n\n  private HostKeyRepository known_hosts=null;\n\n  private static final Logger DEVNULL=new Logger(){\n      public boolean isEnabled(int level){return false;}\n      public void log(int level, String message){}\n    };\n  static Logger logger=DEVNULL;\n\n  public JSch(){\n    /*\n    // The JCE of Sun's Java5 on Mac OS X has the resource leak bug\n    // in calculating HMAC, so we need to use our own implementations.\n    try{\n      String osname=(String)(System.getProperties().get(\"os.name\"));\n      if(osname!=null && osname.equals(\"Mac OS X\")){\n        config.put(\"hmac-sha1\",     \"com.jcraft.jsch.jcraft.HMACSHA1\"); \n        config.put(\"hmac-md5\",      \"com.jcraft.jsch.jcraft.HMACMD5\"); \n        config.put(\"hmac-md5-96\",   \"com.jcraft.jsch.jcraft.HMACMD596\"); \n        config.put(\"hmac-sha1-96\",  \"com.jcraft.jsch.jcraft.HMACSHA196\"); \n      }\n    }\n    catch(Exception e){\n    }\n    */\n  }\n\n  /**\n   * Instantiates the <code>Session</code> object with\n   * <code>host</code>.  The user name and port number will be retrieved from\n   * ConfigRepository.  If user name is not given,\n   * the system property \"user.name\" will be referred. \n   *\n   * @param host hostname\n   *\n   * @throws JSchException\n   *         if <code>username</code> or <code>host</code> are invalid.\n   *\n   * @return the instance of <code>Session</code> class.\n   *\n   * @see #getSession(String username, String host, int port)\n   * @see com.jcraft.jsch.Session\n   * @see com.jcraft.jsch.ConfigRepository\n   */\n  public Session getSession(String host)\n     throws JSchException {\n    return getSession(null, host, 22);\n  }\n\n  /**\n   * Instantiates the <code>Session</code> object with\n   * <code>username</code> and <code>host</code>.\n   * The TCP port 22 will be used in making the connection.\n   * Note that the TCP connection must not be established\n   * until Session#connect().\n   *\n   * @param username user name\n   * @param host hostname\n   *\n   * @throws JSchException\n   *         if <code>username</code> or <code>host</code> are invalid.\n   *\n   * @return the instance of <code>Session</code> class.\n   *\n   * @see #getSession(String username, String host, int port)\n   * @see com.jcraft.jsch.Session\n   */\n  public Session getSession(String username, String host)\n     throws JSchException {\n    return getSession(username, host, 22);\n  }\n\n  /**\n   * Instantiates the <code>Session</code> object with given\n   * <code>username</code>, <code>host</code> and <code>port</code>.\n   * Note that the TCP connection must not be established\n   * until Session#connect().\n   *\n   * @param username user name\n   * @param host hostname\n   * @param port port number\n   *\n   * @throws JSchException\n   *         if <code>username</code> or <code>host</code> are invalid.\n   *\n   * @return the instance of <code>Session</code> class.\n   *\n   * @see #getSession(String username, String host, int port)\n   * @see com.jcraft.jsch.Session\n   */\n  public Session getSession(String username, String host, int port) throws JSchException {\n    if(host==null){\n      throw new JSchException(\"host must not be null.\");\n    }\n    Session s = new Session(this, username, host, port); \n    return s;\n  }\n\n  protected void addSession(Session session){\n    synchronized(sessionPool){\n      sessionPool.addElement(session);\n    }\n  }\n\n  protected boolean removeSession(Session session){\n    synchronized(sessionPool){\n      return sessionPool.remove(session);\n    }\n  }\n\n  /**\n   * Sets the hostkey repository.\n   *\n   * @param hkrepo\n   *\n   * @see com.jcraft.jsch.HostKeyRepository\n   * @see com.jcraft.jsch.KnownHosts\n   */\n  public void setHostKeyRepository(HostKeyRepository hkrepo){\n    known_hosts=hkrepo;\n  }\n\n  /**\n   * Sets the instance of <code>KnownHosts</code>, which refers\n   * to <code>filename</code>.\n   *\n   * @param filename filename of known_hosts file.\n   *\n   * @throws JSchException\n   *         if the given filename is invalid.\n   *\n   * @see com.jcraft.jsch.KnownHosts\n   */\n  public void setKnownHosts(String filename) throws JSchException{\n    if(known_hosts==null) known_hosts=new KnownHosts(this);\n    if(known_hosts instanceof KnownHosts){\n      synchronized(known_hosts){\n\t((KnownHosts)known_hosts).setKnownHosts(filename); \n      }\n    }\n  }\n\n  /**\n   * Sets the instance of <code>KnownHosts</code> generated with\n   * <code>stream</code>.\n   *\n   * @param stream the instance of InputStream from known_hosts file.\n   *\n   * @throws JSchException\n   *         if an I/O error occurs.\n   *\n   * @see com.jcraft.jsch.KnownHosts\n   */\n  public void setKnownHosts(InputStream stream) throws JSchException{ \n    if(known_hosts==null) known_hosts=new KnownHosts(this);\n    if(known_hosts instanceof KnownHosts){\n      synchronized(known_hosts){\n\t((KnownHosts)known_hosts).setKnownHosts(stream); \n      }\n    }\n  }\n\n  /**\n   * Returns the current hostkey repository.\n   * By the default, this method will the instance of <code>KnownHosts</code>.\n   *\n   * @return current hostkey repository.\n   *\n   * @see com.jcraft.jsch.HostKeyRepository\n   * @see com.jcraft.jsch.KnownHosts\n   */\n  public HostKeyRepository getHostKeyRepository(){ \n    if(known_hosts==null) known_hosts=new KnownHosts(this);\n    return known_hosts; \n  }\n\n  /**\n   * Sets the private key, which will be referred in\n   * the public key authentication.\n   *\n   * @param prvkey filename of the private key.\n   *\n   * @throws JSchException if <code>prvkey</code> is invalid.\n   *\n   * @see #addIdentity(String prvkey, String passphrase)\n   */\n  public void addIdentity(String prvkey) throws JSchException{\n    addIdentity(prvkey, (byte[])null);\n  }\n\n  /**\n   * Sets the private key, which will be referred in\n   * the public key authentication.\n   * Before registering it into identityRepository,\n   * it will be deciphered with <code>passphrase</code>.\n   *\n   * @param prvkey filename of the private key.\n   * @param passphrase passphrase for <code>prvkey</code>.\n   *\n   * @throws JSchException if <code>passphrase</code> is not right.\n   *\n   * @see #addIdentity(String prvkey, byte[] passphrase)\n   */\n  public void addIdentity(String prvkey, String passphrase) throws JSchException{\n    byte[] _passphrase=null;\n    if(passphrase!=null){\n      _passphrase=Util.str2byte(passphrase);\n    }\n    addIdentity(prvkey, _passphrase);\n    if(_passphrase!=null)\n      Util.bzero(_passphrase);\n  }\n\n  /**\n   * Sets the private key, which will be referred in\n   * the public key authentication.\n   * Before registering it into identityRepository,\n   * it will be deciphered with <code>passphrase</code>.\n   *\n   * @param prvkey filename of the private key.\n   * @param passphrase passphrase for <code>prvkey</code>.\n   *\n   * @throws JSchException if <code>passphrase</code> is not right.\n   *\n   * @see #addIdentity(String prvkey, String pubkey, byte[] passphrase)\n   */\n  public void addIdentity(String prvkey, byte[] passphrase) throws JSchException{\n    Identity identity=IdentityFile.newInstance(prvkey, null, this);\n    addIdentity(identity, passphrase);\n  }\n\n  /**\n   * Sets the private key, which will be referred in\n   * the public key authentication.\n   * Before registering it into identityRepository,\n   * it will be deciphered with <code>passphrase</code>.\n   *\n   * @param prvkey filename of the private key.\n   * @param pubkey filename of the public key.\n   * @param passphrase passphrase for <code>prvkey</code>.\n   *\n   * @throws JSchException if <code>passphrase</code> is not right.\n   */\n  public void addIdentity(String prvkey, String pubkey, byte[] passphrase) throws JSchException{\n    Identity identity=IdentityFile.newInstance(prvkey, pubkey, this);\n    addIdentity(identity, passphrase);\n  }\n\n  /**\n   * Sets the private key, which will be referred in\n   * the public key authentication.\n   * Before registering it into identityRepository,\n   * it will be deciphered with <code>passphrase</code>.\n   *\n   * @param name name of the identity to be used to\n                 retrieve it in the identityRepository.\n   * @param prvkey private key in byte array.\n   * @param pubkey public key in byte array.\n   * @param passphrase passphrase for <code>prvkey</code>.\n   *\n   */\n  public void addIdentity(String name, byte[]prvkey, byte[]pubkey, byte[] passphrase) throws JSchException{\n    Identity identity=IdentityFile.newInstance(name, prvkey, pubkey, this);\n    addIdentity(identity, passphrase);\n  }\n\n  /**\n   * Sets the private key, which will be referred in\n   * the public key authentication.\n   * Before registering it into identityRepository,\n   * it will be deciphered with <code>passphrase</code>.\n   *\n   * @param identity private key.\n   * @param passphrase passphrase for <code>identity</code>.\n   *\n   * @throws JSchException if <code>passphrase</code> is not right.\n   */\n  public void addIdentity(Identity identity, byte[] passphrase) throws JSchException{\n    if(passphrase!=null){\n      try{ \n        byte[] goo=new byte[passphrase.length];\n        System.arraycopy(passphrase, 0, goo, 0, passphrase.length);\n        passphrase=goo;\n        identity.setPassphrase(passphrase); \n      }\n      finally{\n        Util.bzero(passphrase);\n      }\n    }\n\n    if(identityRepository instanceof LocalIdentityRepository){\n      ((LocalIdentityRepository)identityRepository).add(identity);\n    }\n    else if(identity instanceof IdentityFile && !identity.isEncrypted()) {\n      identityRepository.add(((IdentityFile)identity).getKeyPair().forSSHAgent());\n    }\n    else {\n      synchronized(this){\n        if(!(identityRepository instanceof IdentityRepository.Wrapper)){\n          setIdentityRepository(new IdentityRepository.Wrapper(identityRepository));\n        }\n      }\n      ((IdentityRepository.Wrapper)identityRepository).add(identity);\n    }\n  }\n\n  /**\n   * @deprecated use #removeIdentity(Identity identity)\n   */\n  public void removeIdentity(String name) throws JSchException{\n    Vector identities = identityRepository.getIdentities();\n    for(int i=0; i<identities.size(); i++){\n      Identity identity=(Identity)(identities.elementAt(i));\n      if(!identity.getName().equals(name))\n        continue;\n      if(identityRepository instanceof LocalIdentityRepository){\n        ((LocalIdentityRepository)identityRepository).remove(identity);\n      }\n      else\n        identityRepository.remove(identity.getPublicKeyBlob());\n    }\n  }\n\n  /**\n   * Removes the identity from identityRepository.\n   *\n   * @param identity the indentity to be removed.\n   *\n   * @throws JSchException if <code>identity</code> is invalid.\n   */\n  public void removeIdentity(Identity identity) throws JSchException{\n    identityRepository.remove(identity.getPublicKeyBlob());\n  }\n\n  /**\n   * Lists names of identities included in the identityRepository.\n   *\n   * @return names of identities\n   *\n   * @throws JSchException if identityReposory has problems.\n   */\n  public Vector getIdentityNames() throws JSchException{\n    Vector foo=new Vector();\n    Vector identities = identityRepository.getIdentities();\n    for(int i=0; i<identities.size(); i++){\n      Identity identity=(Identity)(identities.elementAt(i));\n      foo.addElement(identity.getName());\n    }\n    return foo;\n  }\n\n  /**\n   * Removes all identities from identityRepository.\n   *\n   * @throws JSchException if identityReposory has problems.\n   */\n  public void removeAllIdentity() throws JSchException{\n    identityRepository.removeAll();\n  }\n\n  /**\n   * Returns the config value for the specified key.\n   *\n   * @param key key for the configuration.\n   * @return config value\n   */\n  public static String getConfig(String key){ \n    synchronized(config){\n      return (String)(config.get(key));\n    } \n  }\n\n  /**\n   * Sets or Overrides the configuration.\n   *\n   * @param newconf configurations\n   */\n  public static void setConfig(java.util.Hashtable newconf){\n    synchronized(config){\n      for(java.util.Enumeration e=newconf.keys() ; e.hasMoreElements() ;) {\n\tString key=(String)(e.nextElement());\n\tconfig.put(key, (String)(newconf.get(key)));\n      }\n    }\n  }\n\n  /**\n   * Sets or Overrides the configuration.\n   *\n   * @param key key for the configuration\n   * @param value value for the configuration\n   */\n  public static void setConfig(String key, String value){\n    config.put(key, value);\n  }\n\n  /**\n   * Sets the logger\n   *\n   * @param logger logger\n   *\n   * @see com.jcraft.jsch.Logger\n   */\n  public static void setLogger(Logger logger){\n    if(logger==null) logger=DEVNULL;\n    JSch.logger=logger;\n  }\n\n  static Logger getLogger(){\n    return logger;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/JSchAuthCancelException.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass JSchAuthCancelException extends JSchException{\n  //private static final long serialVersionUID=3204965907117900987L;\n  String method;\n  JSchAuthCancelException () {\n    super();\n  }\n  JSchAuthCancelException (String s) {\n    super(s);\n    this.method=s;\n  }\n  public String getMethod(){\n    return method;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/JSchException.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class JSchException extends Exception{\n  //private static final long serialVersionUID=-1319309923966731989L;\n  private Throwable cause=null;\n  public JSchException () {\n    super();\n  }\n  public JSchException (String s) {\n    super(s);\n  }\n  public JSchException (String s, Throwable e) {\n    super(s);\n    this.cause=e;\n  }\n  public Throwable getCause(){\n    return this.cause;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/JSchPartialAuthException.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass JSchPartialAuthException extends JSchException{\n  //private static final long serialVersionUID=-378849862323360367L;\n  String methods;\n  public JSchPartialAuthException () {\n    super();\n  }\n  public JSchPartialAuthException (String s) {\n    super(s);\n    this.methods=s;\n  }\n  public String getMethods(){\n    return methods;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/KeyExchange.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic abstract class KeyExchange{\n\n  static final int PROPOSAL_KEX_ALGS=0;\n  static final int PROPOSAL_SERVER_HOST_KEY_ALGS=1;\n  static final int PROPOSAL_ENC_ALGS_CTOS=2;\n  static final int PROPOSAL_ENC_ALGS_STOC=3;\n  static final int PROPOSAL_MAC_ALGS_CTOS=4;\n  static final int PROPOSAL_MAC_ALGS_STOC=5;\n  static final int PROPOSAL_COMP_ALGS_CTOS=6;\n  static final int PROPOSAL_COMP_ALGS_STOC=7;\n  static final int PROPOSAL_LANG_CTOS=8;\n  static final int PROPOSAL_LANG_STOC=9;\n  static final int PROPOSAL_MAX=10;\n\n  //static String kex_algs=\"diffie-hellman-group-exchange-sha1\"+\n  //                       \",diffie-hellman-group1-sha1\";\n\n//static String kex=\"diffie-hellman-group-exchange-sha1\";\n  static String kex=\"diffie-hellman-group1-sha1\";\n  static String server_host_key=\"ssh-rsa,ssh-dss\";\n  static String enc_c2s=\"blowfish-cbc\";\n  static String enc_s2c=\"blowfish-cbc\";\n  static String mac_c2s=\"hmac-md5\";     // hmac-md5,hmac-sha1,hmac-ripemd160,\n                                        // hmac-sha1-96,hmac-md5-96\n  static String mac_s2c=\"hmac-md5\";\n//static String comp_c2s=\"none\";        // zlib\n//static String comp_s2c=\"none\";\n  static String lang_c2s=\"\";\n  static String lang_s2c=\"\";\n\n  public static final int STATE_END=0;\n\n  protected Session session=null;\n  protected HASH sha=null;\n  protected byte[] K=null;\n  protected byte[] H=null;\n  protected byte[] K_S=null;\n\n  public abstract void init(Session session, \n\t\t\t    byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception;\n  public abstract boolean next(Buffer buf) throws Exception;\n\n  public abstract int getState();\n\n  protected final int RSA=0;\n  protected final int DSS=1;\n  protected final int ECDSA=2;\n  private int type=0;\n  private String key_alg_name = \"\";\n\n  public String getKeyType() {\n    if(type==DSS) return \"DSA\";\n    if(type==RSA) return \"RSA\";\n    return \"ECDSA\";\n  }\n\n  public String getKeyAlgorithName() {\n    return key_alg_name;\n  }\n\n  protected static String[] guess(byte[]I_S, byte[]I_C){\n    String[] guess=new String[PROPOSAL_MAX];\n    Buffer sb=new Buffer(I_S); sb.setOffSet(17);\n    Buffer cb=new Buffer(I_C); cb.setOffSet(17);\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      for(int i=0; i<PROPOSAL_MAX; i++){\n        JSch.getLogger().log(Logger.INFO,\n                             \"kex: server: \"+Util.byte2str(sb.getString()));\n      }\n      for(int i=0; i<PROPOSAL_MAX; i++){\n        JSch.getLogger().log(Logger.INFO,\n                             \"kex: client: \"+Util.byte2str(cb.getString()));\n      }\n      sb.setOffSet(17);\n      cb.setOffSet(17);\n    }\n\n    for(int i=0; i<PROPOSAL_MAX; i++){\n      byte[] sp=sb.getString();  // server proposal\n      byte[] cp=cb.getString();  // client proposal\n      int j=0;\n      int k=0;\n\n      loop:\n      while(j<cp.length){\n\twhile(j<cp.length && cp[j]!=',')j++; \n\tif(k==j) return null;\n\tString algorithm=Util.byte2str(cp, k, j-k);\n\tint l=0;\n\tint m=0;\n\twhile(l<sp.length){\n\t  while(l<sp.length && sp[l]!=',')l++; \n\t  if(m==l) return null;\n\t  if(algorithm.equals(Util.byte2str(sp, m, l-m))){\n\t    guess[i]=algorithm;\n\t    break loop;\n\t  }\n\t  l++;\n\t  m=l;\n\t}\t\n\tj++;\n\tk=j;\n      }\n      if(j==0){\n\tguess[i]=\"\";\n      }\n      else if(guess[i]==null){\n\treturn null;\n      }\n    }\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"kex: server->client\"+\n                           \" \"+guess[PROPOSAL_ENC_ALGS_STOC]+\n                           \" \"+guess[PROPOSAL_MAC_ALGS_STOC]+\n                           \" \"+guess[PROPOSAL_COMP_ALGS_STOC]);\n      JSch.getLogger().log(Logger.INFO, \n                           \"kex: client->server\"+\n                           \" \"+guess[PROPOSAL_ENC_ALGS_CTOS]+\n                           \" \"+guess[PROPOSAL_MAC_ALGS_CTOS]+\n                           \" \"+guess[PROPOSAL_COMP_ALGS_CTOS]);\n    }\n\n    return guess;\n  }\n\n  public String getFingerPrint(){\n    HASH hash=null;\n    try{\n      Class c=Class.forName(session.getConfig(\"md5\"));\n      hash=(HASH)(c.newInstance());\n    }\n    catch(Exception e){ System.err.println(\"getFingerPrint: \"+e); }\n    return Util.getFingerPrint(hash, getHostKey());\n  }\n  byte[] getK(){ return K; }\n  byte[] getH(){ return H; }\n  HASH getHash(){ return sha; }\n  byte[] getHostKey(){ return K_S; }\n\n  /*\n   * It seems JCE included in Oracle's Java7u6(and later) has suddenly changed\n   * its behavior.  The secrete generated by KeyAgreement#generateSecret()\n   * may start with 0, even if it is a positive value.\n   */\n  protected byte[] normalize(byte[] secret) {\n    if(secret.length > 1 &&\n       secret[0] == 0 && (secret[1]&0x80) == 0) {\n      byte[] tmp=new byte[secret.length-1];\n      System.arraycopy(secret, 1, tmp, 0, tmp.length);\n      return normalize(tmp);\n    }\n    else {\n      return secret;\n    }\n  }\n\n  protected boolean verify(String alg, byte[] K_S, int index,\n                           byte[] sig_of_H) throws Exception {\n    int i,j;\n\n    i=index;\n    boolean result=false;\n\n    if(alg.equals(\"ssh-rsa\")){\n      byte[] tmp;\n      byte[] ee;\n      byte[] n;\n\n      type=RSA;\n      key_alg_name=alg;\n      \n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;\n      ee=tmp;\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;\n      n=tmp;\n\t\n      SignatureRSA sig=null;\n      try{\n        Class c=Class.forName(session.getConfig(\"signature.rsa\"));\n        sig=(SignatureRSA)(c.newInstance());\n        sig.init();\n      }\n      catch(Exception e){\n        System.err.println(e);\n      }\n      sig.setPubKey(ee, n);   \n      sig.update(H);\n      result=sig.verify(sig_of_H);\n\n      if(JSch.getLogger().isEnabled(Logger.INFO)){\n        JSch.getLogger().log(Logger.INFO, \n                             \"ssh_rsa_verify: signature \"+result);\n      }\n    }\n    else if(alg.equals(\"ssh-dss\")){\n      byte[] q=null;\n      byte[] tmp;\n      byte[] p;\n      byte[] g;\n      byte[] f;\n      \n      type=DSS;\n      key_alg_name=alg;\n\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n\t  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;\n      p=tmp;\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;\n      q=tmp;\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n\t  ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;\n      g=tmp;\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;\n      f=tmp;\n\n      SignatureDSA sig=null;\n      try{\n        Class c=Class.forName(session.getConfig(\"signature.dss\"));\n        sig=(SignatureDSA)(c.newInstance());\n        sig.init();\n      }\n      catch(Exception e){\n        System.err.println(e);\n      }\n      sig.setPubKey(f, p, q, g);   \n      sig.update(H);\n      result=sig.verify(sig_of_H);\n\n      if(JSch.getLogger().isEnabled(Logger.INFO)){\n        JSch.getLogger().log(Logger.INFO, \n                             \"ssh_dss_verify: signature \"+result);\n      }\n    }\n    else if(alg.equals(\"ecdsa-sha2-nistp256\") ||\n            alg.equals(\"ecdsa-sha2-nistp384\") ||\n            alg.equals(\"ecdsa-sha2-nistp521\")) {\n      byte[] tmp;\n      byte[] r;\n      byte[] s;\n\n      // RFC 5656, \n      type=ECDSA;\n      key_alg_name=alg;\n\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;\n      j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|\n        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);\n      i++;\n      tmp=new byte[(j-1)/2];\n      System.arraycopy(K_S, i, tmp, 0, tmp.length); i+=(j-1)/2;\n      r=tmp;\n      tmp=new byte[(j-1)/2];\n      System.arraycopy(K_S, i, tmp, 0, tmp.length); i+=(j-1)/2;\n      s=tmp;\n\n      SignatureECDSA sig=null;\n      try{\n        Class c=Class.forName(session.getConfig(\"signature.ecdsa\"));\n        sig=(SignatureECDSA)(c.newInstance());\n        sig.init();\n      }\n      catch(Exception e){\n        System.err.println(e);\n      }\n\n      sig.setPubKey(r, s);\n\n      sig.update(H);\n\n      result=sig.verify(sig_of_H);\n    }\n    else{\n      System.err.println(\"unknown alg\");\n    }\t    \n\n    return result;\n  }\n\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/KeyPair.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.FileOutputStream;\nimport java.io.FileInputStream;\nimport java.io.File;\nimport java.io.IOException;\n\npublic abstract class KeyPair{\n  public static final int ERROR=0;\n  public static final int DSA=1;\n  public static final int RSA=2;\n  public static final int ECDSA=3;\n  public static final int UNKNOWN=4;\n\n  static final int VENDOR_OPENSSH=0;\n  static final int VENDOR_FSECURE=1;\n  static final int VENDOR_PUTTY=2;\n  static final int VENDOR_PKCS8=3;\n\n  int vendor=VENDOR_OPENSSH;\n\n  private static final byte[] cr=Util.str2byte(\"\\n\");\n\n  public static KeyPair genKeyPair(JSch jsch, int type) throws JSchException{\n    return genKeyPair(jsch, type, 1024);\n  }\n  public static KeyPair genKeyPair(JSch jsch, int type, int key_size) throws JSchException{\n    KeyPair kpair=null;\n    if(type==DSA){ kpair=new KeyPairDSA(jsch); }\n    else if(type==RSA){ kpair=new KeyPairRSA(jsch); }\n    else if(type==ECDSA){ kpair=new KeyPairECDSA(jsch); }\n    if(kpair!=null){\n      kpair.generate(key_size);\n    }\n    return kpair;\n  }\n\n  abstract void generate(int key_size) throws JSchException;\n\n  abstract byte[] getBegin();\n  abstract byte[] getEnd();\n  abstract int getKeySize();\n\n  public abstract byte[] getSignature(byte[] data);\n  public abstract Signature getVerifier();\n\n  public abstract byte[] forSSHAgent() throws JSchException;\n\n  public String getPublicKeyComment(){\n    return publicKeyComment;\n  }\n\n  public void setPublicKeyComment(String publicKeyComment){\n    this.publicKeyComment = publicKeyComment;\n  }\n\n  protected String publicKeyComment = \"no comment\";\n\n  JSch jsch=null;\n  private Cipher cipher;\n  private HASH hash;\n  private Random random;\n\n  private byte[] passphrase;\n\n  public KeyPair(JSch jsch){\n    this.jsch=jsch;\n  }\n\n  static byte[][] header={Util.str2byte(\"Proc-Type: 4,ENCRYPTED\"),\n                          Util.str2byte(\"DEK-Info: DES-EDE3-CBC,\")};\n\n  abstract byte[] getPrivateKey();\n\n  /**\n   * Writes the plain private key to the given output stream.\n   * @param out output stream \n   * @see #writePrivateKey(java.io.OutputStream out, byte[] passphrase)\n   */\n  public void writePrivateKey(java.io.OutputStream out){\n    this.writePrivateKey(out, null);\n  }\n\n  /**\n   * Writes the cyphered private key to the given output stream.\n   * @param out output stream \n   * @param passphrase a passphrase to encrypt the private key\n   */\n  public void writePrivateKey(java.io.OutputStream out, byte[] passphrase){\n    if(passphrase == null)\n      passphrase = this.passphrase;\n\n    byte[] plain=getPrivateKey();\n    byte[][] _iv=new byte[1][];\n    byte[] encoded=encrypt(plain, _iv, passphrase);\n    if(encoded!=plain)\n      Util.bzero(plain);\n    byte[] iv=_iv[0];\n    byte[] prv=Util.toBase64(encoded, 0, encoded.length);\n\n    try{\n      out.write(getBegin()); out.write(cr);\n      if(passphrase!=null){\n\tout.write(header[0]); out.write(cr);\n\tout.write(header[1]); \n\tfor(int i=0; i<iv.length; i++){\n\t  out.write(b2a((byte)((iv[i]>>>4)&0x0f)));\n\t  out.write(b2a((byte)(iv[i]&0x0f)));\n\t}\n        out.write(cr);\n\tout.write(cr);\n      }\n      int i=0;\n      while(i<prv.length){\n\tif(i+64<prv.length){\n\t  out.write(prv, i, 64);\n\t  out.write(cr);\n\t  i+=64;\n\t  continue;\n\t}\n\tout.write(prv, i, prv.length-i);\n\tout.write(cr);\n\tbreak;\n      }\n      out.write(getEnd()); out.write(cr);\n      //out.close();\n    }\n    catch(Exception e){\n    }\n  }\n\n  private static byte[] space=Util.str2byte(\" \");\n\n  abstract byte[] getKeyTypeName();\n  public abstract int getKeyType();\n\n  /**\n   * Returns the blob of the public key.\n   * @return blob of the public key\n   */\n  public byte[] getPublicKeyBlob() {\n    // TODO JSchException should be thrown\n    //if(publickeyblob == null)\n    //  throw new JSchException(\"public-key blob is not available\");\n    return publickeyblob;\n  }\n\n  /**\n   * Writes the public key with the specified comment to the output stream.\n   * @param out output stream \n   * @param comment comment\n   */\n  public void writePublicKey(java.io.OutputStream out, String comment){\n    byte[] pubblob=getPublicKeyBlob();\n    byte[] pub=Util.toBase64(pubblob, 0, pubblob.length);\n    try{\n      out.write(getKeyTypeName()); out.write(space);\n      out.write(pub, 0, pub.length); out.write(space);\n      out.write(Util.str2byte(comment));\n      out.write(cr);\n    }\n    catch(Exception e){\n    }\n  }\n\n  /**\n   * Writes the public key with the specified comment to the file.\n   * @param name file name\n   * @param comment comment\n   * @see #writePublicKey(java.io.OutputStream out, String comment)\n   */\n  public void writePublicKey(String name, String comment) throws java.io.FileNotFoundException, java.io.IOException{\n    FileOutputStream fos=new FileOutputStream(name);\n    writePublicKey(fos, comment);\n    fos.close();\n  }\n\n  /**\n   * Writes the public key with the specified comment to the output stream in\n   * the format defined in http://www.ietf.org/rfc/rfc4716.txt\n   * @param out output stream \n   * @param comment comment\n   */\n  public void writeSECSHPublicKey(java.io.OutputStream out, String comment){\n    byte[] pubblob=getPublicKeyBlob();\n    byte[] pub=Util.toBase64(pubblob, 0, pubblob.length);\n    try{\n      out.write(Util.str2byte(\"---- BEGIN SSH2 PUBLIC KEY ----\")); out.write(cr);\n      out.write(Util.str2byte(\"Comment: \\\"\"+comment+\"\\\"\")); out.write(cr);\n      int index=0;\n      while(index<pub.length){\n\tint len=70;\n\tif((pub.length-index)<len)len=pub.length-index;\n\tout.write(pub, index, len); out.write(cr);\n\tindex+=len;\n      }\n      out.write(Util.str2byte(\"---- END SSH2 PUBLIC KEY ----\")); out.write(cr);\n    }\n    catch(Exception e){\n    }\n  }\n\n  /**\n   * Writes the public key with the specified comment to the output stream in\n   * the format defined in http://www.ietf.org/rfc/rfc4716.txt\n   * @param name file name\n   * @param comment comment\n   * @see #writeSECSHPublicKey(java.io.OutputStream out, String comment)\n   */\n  public void writeSECSHPublicKey(String name, String comment) throws java.io.FileNotFoundException, java.io.IOException{\n    FileOutputStream fos=new FileOutputStream(name);\n    writeSECSHPublicKey(fos, comment);\n    fos.close();\n  }\n\n  /**\n   * Writes the plain private key to the file.\n   * @param name file name\n   * @see #writePrivateKey(String name,  byte[] passphrase)\n   */\n  public void writePrivateKey(String name) throws java.io.FileNotFoundException, java.io.IOException{\n    this.writePrivateKey(name, null);\n  }\n\n  /**\n   * Writes the cyphered private key to the file.\n   * @param name file name\n   * @param passphrase a passphrase to encrypt the private key\n   * @see #writePrivateKey(java.io.OutputStream out,  byte[] passphrase)\n   */\n  public void writePrivateKey(String name, byte[] passphrase) throws java.io.FileNotFoundException, java.io.IOException{\n    FileOutputStream fos=new FileOutputStream(name);\n    writePrivateKey(fos, passphrase);\n    fos.close();\n  }\n\n  /**\n   * Returns the finger-print of the public key.\n   * @return finger print\n   */\n  public String getFingerPrint(){\n    if(hash==null) hash=genHash();\n    byte[] kblob=getPublicKeyBlob();\n    if(kblob==null) return null;\n    return Util.getFingerPrint(hash, kblob);\n  }\n\n  private byte[] encrypt(byte[] plain, byte[][] _iv, byte[] passphrase){\n    if(passphrase==null) return plain;\n\n    if(cipher==null) cipher=genCipher();\n    byte[] iv=_iv[0]=new byte[cipher.getIVSize()];\n\n    if(random==null) random=genRandom();\n    random.fill(iv, 0, iv.length);\n\n    byte[] key=genKey(passphrase, iv);\n    byte[] encoded=plain;\n\n    // PKCS#5Padding\n    {\n      //int bsize=cipher.getBlockSize();\n      int bsize=cipher.getIVSize();\n      byte[] foo=new byte[(encoded.length/bsize+1)*bsize];\n      System.arraycopy(encoded, 0, foo, 0, encoded.length);\n      int padding=bsize-encoded.length%bsize;\n      for(int i=foo.length-1; (foo.length-padding)<=i; i--){\n        foo[i]=(byte)padding;\n      }\n      encoded=foo;\n    }\n\n    try{\n      cipher.init(Cipher.ENCRYPT_MODE, key, iv);\n      cipher.update(encoded, 0, encoded.length, encoded, 0);\n    }\n    catch(Exception e){\n      //System.err.println(e);\n    }\n    Util.bzero(key);\n    return encoded;\n  }\n\n  abstract boolean parse(byte[] data);\n\n  private byte[] decrypt(byte[] data, byte[] passphrase, byte[] iv){\n\n    try{\n      byte[] key=genKey(passphrase, iv);\n      cipher.init(Cipher.DECRYPT_MODE, key, iv);\n      Util.bzero(key);\n      byte[] plain=new byte[data.length];\n      cipher.update(data, 0, data.length, plain, 0);\n      return plain;\n    }\n    catch(Exception e){\n      //System.err.println(e);\n    }\n    return null;\n  }\n\n  int writeSEQUENCE(byte[] buf, int index, int len){\n    buf[index++]=0x30;\n    index=writeLength(buf, index, len);\n    return index;\n  }\n  int writeINTEGER(byte[] buf, int index, byte[] data){\n    buf[index++]=0x02;\n    index=writeLength(buf, index, data.length);\n    System.arraycopy(data, 0, buf, index, data.length);\n    index+=data.length;\n    return index;\n  }\n\n  int writeOCTETSTRING(byte[] buf, int index, byte[] data){\n    buf[index++]=0x04;\n    index=writeLength(buf, index, data.length);\n    System.arraycopy(data, 0, buf, index, data.length);\n    index+=data.length;\n    return index;\n  }\n\n int writeDATA(byte[] buf, byte n, int index, byte[] data){\n    buf[index++]=n;\n    index=writeLength(buf, index, data.length);\n    System.arraycopy(data, 0, buf, index, data.length);\n    index+=data.length;\n    return index;\n  }\n\n  int countLength(int len){\n    int i=1;\n    if(len<=0x7f) return i;\n    while(len>0){\n      len>>>=8;\n      i++;\n    }\n    return i;\n  }\n\n  int writeLength(byte[] data, int index, int len){\n    int i=countLength(len)-1;\n    if(i==0){\n      data[index++]=(byte)len;\n      return index;\n    }\n    data[index++]=(byte)(0x80|i);\n    int j=index+i;\n    while(i>0){\n      data[index+i-1]=(byte)(len&0xff);\n      len>>>=8;\n      i--;\n    }\n    return j;\n  }\n\n  @SuppressWarnings({\"static\"}) private Random genRandom(){\n    if(random==null){\n      try{\n\tClass c=Class.forName(jsch.getConfig(\"random\"));\n        random=(Random)(c.newInstance());\n      }\n      catch(Exception e){ System.err.println(\"connect: random \"+e); }\n    }\n    return random;\n  }\n\n  @SuppressWarnings({\"static\"}) private HASH genHash(){\n    try{\n      Class c=Class.forName(jsch.getConfig(\"md5\"));\n      hash=(HASH)(c.newInstance());\n      hash.init();\n    }\n    catch(Exception e){\n    }\n    return hash;\n  }\n  @SuppressWarnings({\"static\"}) private Cipher genCipher(){\n    try{\n      Class c;\n      c=Class.forName(jsch.getConfig(\"3des-cbc\"));\n      cipher=(Cipher)(c.newInstance());\n    }\n    catch(Exception e){\n    }\n    return cipher;\n  }\n\n  /*\n    hash is MD5\n    h(0) <- hash(passphrase, iv);\n    h(n) <- hash(h(n-1), passphrase, iv);\n    key <- (h(0),...,h(n))[0,..,key.length];\n  */\n  @SuppressWarnings({\"static\"}) synchronized byte[] genKey(byte[] passphrase, byte[] iv){\n    if(cipher==null) cipher=genCipher();\n    if(hash==null) hash=genHash();\n\n    byte[] key=new byte[cipher.getBlockSize()];\n    int hsize=hash.getBlockSize();\n    byte[] hn=new byte[key.length/hsize*hsize+\n\t\t       (key.length%hsize==0?0:hsize)];\n    try{\n      byte[] tmp=null;\n      if(vendor==VENDOR_OPENSSH){\n\tfor(int index=0; index+hsize<=hn.length;){\n\t  if(tmp!=null){ hash.update(tmp, 0, tmp.length); }\n\t  hash.update(passphrase, 0, passphrase.length);\n          hash.update(iv, 0, iv.length > 8 ? 8: iv.length);\n\t  tmp=hash.digest();\n\t  System.arraycopy(tmp, 0, hn, index, tmp.length);\n\t  index+=tmp.length;\n\t}\n\tSystem.arraycopy(hn, 0, key, 0, key.length); \n      }\n      else if(vendor==VENDOR_FSECURE){\n\tfor(int index=0; index+hsize<=hn.length;){\n\t  if(tmp!=null){ hash.update(tmp, 0, tmp.length); }\n\t  hash.update(passphrase, 0, passphrase.length);\n\t  tmp=hash.digest();\n\t  System.arraycopy(tmp, 0, hn, index, tmp.length);\n\t  index+=tmp.length;\n\t}\n\tSystem.arraycopy(hn, 0, key, 0, key.length); \n      }\n      else if(vendor==VENDOR_PUTTY){\n        Class c=Class.forName((String)jsch.getConfig(\"sha-1\"));\n        HASH sha1=(HASH)(c.newInstance());\n        tmp = new byte[4];\n        key = new byte[20*2];\n        for(int i = 0; i < 2; i++){\n          sha1.init();\n          tmp[3]=(byte)i;\n          sha1.update(tmp, 0, tmp.length);\n          sha1.update(passphrase, 0, passphrase.length);\n          System.arraycopy(sha1.digest(), 0, key, i*20, 20);\n        }\n      }\n    }\n    catch(Exception e){\n      System.err.println(e);\n    }\n    return key;\n  } \n\n  /**\n   * @deprecated use #writePrivateKey(java.io.OutputStream out, byte[] passphrase)\n   */\n  public void setPassphrase(String passphrase){\n    if(passphrase==null || passphrase.length()==0){\n      setPassphrase((byte[])null);\n    }\n    else{\n      setPassphrase(Util.str2byte(passphrase));\n    }\n  }\n\n  /**\n   * @deprecated use #writePrivateKey(String name, byte[] passphrase)\n   */\n  public void setPassphrase(byte[] passphrase){\n    if(passphrase!=null && passphrase.length==0) \n      passphrase=null;\n    this.passphrase=passphrase;\n  }\n\n  protected boolean encrypted=false;\n  protected byte[] data=null;\n  private byte[] iv=null;\n  private byte[] publickeyblob=null;\n\n  public boolean isEncrypted(){ return encrypted; }\n  public boolean decrypt(String _passphrase){\n    if(_passphrase==null || _passphrase.length()==0){\n      return !encrypted;\n    }\n    return decrypt(Util.str2byte(_passphrase));\n  }\n  public boolean decrypt(byte[] _passphrase){\n\n    if(!encrypted){\n      return true;\n    }\n    if(_passphrase==null){\n      return !encrypted;\n    }\n    byte[] bar=new byte[_passphrase.length];\n    System.arraycopy(_passphrase, 0, bar, 0, bar.length);\n    _passphrase=bar;\n    byte[] foo=decrypt(data, _passphrase, iv);\n    Util.bzero(_passphrase);\n    if(parse(foo)){\n      encrypted=false;\n    }\n    return !encrypted;\n  }\n\n  public static KeyPair load(JSch jsch, String prvkey) throws JSchException{\n    String pubkey=prvkey+\".pub\";\n    if(!new File(pubkey).exists()){\n      pubkey=null;\n    }\n    return load(jsch, prvkey, pubkey);\n  }\n  public static KeyPair load(JSch jsch, String prvfile, String pubfile) throws JSchException{\n\n    byte[] prvkey=null;\n    byte[] pubkey=null;\n\n    try{\n      prvkey = Util.fromFile(prvfile);\n    }\n    catch(IOException e){\n      throw new JSchException(e.toString(), (Throwable)e);\n    }\n\n    String _pubfile=pubfile;\n    if(pubfile==null){\n      _pubfile=prvfile+\".pub\";\n    }\n\n    try{\n      pubkey = Util.fromFile(_pubfile);\n    }\n    catch(IOException e){\n      if(pubfile!=null){  \n        throw new JSchException(e.toString(), (Throwable)e);\n      }\n    }\n\n    try {\n      return load(jsch, prvkey, pubkey);\n    }\n    finally {\n      Util.bzero(prvkey);\n    }\n  }\n\n  @SuppressWarnings({\"static\"}) public static KeyPair load(JSch jsch, byte[] prvkey, byte[] pubkey) throws JSchException{\n\n    byte[] iv=new byte[8];       // 8\n    boolean encrypted=true;\n    byte[] data=null;\n\n    byte[] publickeyblob=null;\n\n    int type=ERROR;\n    int vendor=VENDOR_OPENSSH;\n    String publicKeyComment = \"\";\n    Cipher cipher=null;\n\n    // prvkey from \"ssh-add\" command on the remote.\n    if(pubkey==null &&\n       prvkey!=null && \n       (prvkey.length>11 &&\n        prvkey[0]==0 && prvkey[1]==0 && prvkey[2]==0 &&\n        (prvkey[3]==7 || prvkey[3]==19))){\n\n      Buffer buf=new Buffer(prvkey);\n      buf.skip(prvkey.length);  // for using Buffer#available()\n      String _type = new String(buf.getString()); // ssh-rsa or ssh-dss\n      buf.rewind();\n\n      KeyPair kpair=null;\n      if(_type.equals(\"ssh-rsa\")){\n        kpair=KeyPairRSA.fromSSHAgent(jsch, buf);\n      }\n      else if(_type.equals(\"ssh-dss\")){\n        kpair=KeyPairDSA.fromSSHAgent(jsch, buf);\n      }\n      else if(_type.equals(\"ecdsa-sha2-nistp256\") ||\n              _type.equals(\"ecdsa-sha2-nistp384\") ||\n              _type.equals(\"ecdsa-sha2-nistp512\")){\n        kpair=KeyPairECDSA.fromSSHAgent(jsch, buf);\n      }\n      else{\n        throw new JSchException(\"privatekey: invalid key \"+new String(prvkey, 4, 7));\n      }\n      return kpair;\n    }\n\n    try{\n      byte[] buf=prvkey;\n\n      if(buf!=null){\n        KeyPair ppk = loadPPK(jsch, buf);\n        if(ppk !=null)\n          return ppk;\n      }\n\n      int len = (buf!=null ? buf.length : 0);\n      int i=0;\n\n      // skip garbage lines.\n      while(i<len){\n        if(buf[i] == '-' && i+4<len && \n           buf[i+1] == '-' && buf[i+2] == '-' && \n           buf[i+3] == '-' && buf[i+4] == '-'){\n          break;\n        }\n        i++;\n      }\n\n      while(i<len){\n        if(buf[i]=='B'&& i+3<len && buf[i+1]=='E'&& buf[i+2]=='G'&& buf[i+3]=='I'){\n          i+=6;\n          if(i+2 >= len)\n\t    throw new JSchException(\"invalid privatekey: \"+prvkey);\n          if(buf[i]=='D'&& buf[i+1]=='S'&& buf[i+2]=='A'){ type=DSA; }\n\t  else if(buf[i]=='R'&& buf[i+1]=='S'&& buf[i+2]=='A'){ type=RSA; }\n\t  else if(buf[i]=='E'&& buf[i+1]=='C'){ type=ECDSA; }\n\t  else if(buf[i]=='S'&& buf[i+1]=='S'&& buf[i+2]=='H'){ // FSecure\n\t    type=UNKNOWN;\n\t    vendor=VENDOR_FSECURE;\n\t  }\n\t  else if(i+6 < len &&\n                  buf[i]=='P' && buf[i+1]=='R' &&\n                  buf[i+2]=='I' && buf[i+3]=='V' &&\n                  buf[i+4]=='A' && buf[i+5]=='T' && buf[i+6]=='E'){\n\t    type=UNKNOWN;\n\t    vendor=VENDOR_PKCS8;\n            encrypted=false;\n            i+=3;\n\t  }\n\t  else if(i+8 < len &&\n                  buf[i]=='E' && buf[i+1]=='N' &&\n                  buf[i+2]=='C' && buf[i+3]=='R' &&\n                  buf[i+4]=='Y' && buf[i+5]=='P' && buf[i+6]=='T' &&\n                  buf[i+7]=='E' && buf[i+8]=='D'){\n\t    type=UNKNOWN;\n\t    vendor=VENDOR_PKCS8;\n            i+=5;\n\t  }\n\t  else{\n\t    throw new JSchException(\"invalid privatekey: \"+prvkey);\n\t  }\n          i+=3;\n\t  continue;\n\t}\n        if(buf[i]=='A'&& i+7<len && buf[i+1]=='E'&& buf[i+2]=='S'&& buf[i+3]=='-' && \n           buf[i+4]=='2'&& buf[i+5]=='5'&& buf[i+6]=='6'&& buf[i+7]=='-'){\n          i+=8;\n          if(Session.checkCipher((String)jsch.getConfig(\"aes256-cbc\"))){\n            Class c=Class.forName((String)jsch.getConfig(\"aes256-cbc\"));\n            cipher=(Cipher)(c.newInstance());\n            // key=new byte[cipher.getBlockSize()];\n            iv=new byte[cipher.getIVSize()];\n          }\n          else{\n            throw new JSchException(\"privatekey: aes256-cbc is not available \"+prvkey);\n          }\n          continue;\n        }\n        if(buf[i]=='A'&& i+7<len && buf[i+1]=='E'&& buf[i+2]=='S'&& buf[i+3]=='-' && \n           buf[i+4]=='1'&& buf[i+5]=='9'&& buf[i+6]=='2'&& buf[i+7]=='-'){\n          i+=8;\n          if(Session.checkCipher((String)jsch.getConfig(\"aes192-cbc\"))){\n            Class c=Class.forName((String)jsch.getConfig(\"aes192-cbc\"));\n            cipher=(Cipher)(c.newInstance());\n            // key=new byte[cipher.getBlockSize()];\n            iv=new byte[cipher.getIVSize()];\n          }\n          else{\n            throw new JSchException(\"privatekey: aes192-cbc is not available \"+prvkey);\n          }\n          continue;\n        }\n        if(buf[i]=='A'&& i+7<len && buf[i+1]=='E'&& buf[i+2]=='S'&& buf[i+3]=='-' && \n           buf[i+4]=='1'&& buf[i+5]=='2'&& buf[i+6]=='8'&& buf[i+7]=='-'){\n          i+=8;\n          if(Session.checkCipher((String)jsch.getConfig(\"aes128-cbc\"))){\n            Class c=Class.forName((String)jsch.getConfig(\"aes128-cbc\"));\n            cipher=(Cipher)(c.newInstance());\n            // key=new byte[cipher.getBlockSize()];\n            iv=new byte[cipher.getIVSize()];\n          }\n          else{\n            throw new JSchException(\"privatekey: aes128-cbc is not available \"+prvkey);\n          }\n          continue;\n        }\n        if(buf[i]=='C'&& i+3<len && buf[i+1]=='B'&& buf[i+2]=='C'&& buf[i+3]==','){\n          i+=4;\n\t  for(int ii=0; ii<iv.length; ii++){\n            iv[ii]=(byte)(((a2b(buf[i++])<<4)&0xf0)+(a2b(buf[i++])&0xf));\n  \t  }\n\t  continue;\n\t}\n\tif(buf[i]==0x0d && i+1<buf.length && buf[i+1]==0x0a){\n\t  i++;\n\t  continue;\n\t}\n\tif(buf[i]==0x0a && i+1<buf.length){\n\t  if(buf[i+1]==0x0a){ i+=2; break; }\n\t  if(buf[i+1]==0x0d &&\n\t     i+2<buf.length && buf[i+2]==0x0a){\n\t     i+=3; break;\n\t  }\n\t  boolean inheader=false;\n\t  for(int j=i+1; j<buf.length; j++){\n\t    if(buf[j]==0x0a) break;\n\t    //if(buf[j]==0x0d) break;\n\t    if(buf[j]==':'){inheader=true; break;}\n\t  }\n\t  if(!inheader){\n\t    i++; \n\t    if(vendor!=VENDOR_PKCS8)\n              encrypted=false;    // no passphrase\n\t    break;\n\t  }\n\t}\n\ti++;\n      }\n\n      if(buf!=null){\n\n        if(type==ERROR){\n          throw new JSchException(\"invalid privatekey: \"+prvkey);\n        }\n\n        int start = i;\n        while(i < len){\n          if(buf[i] == '-'){  break; }\n          i++;\n        }\n\n        if((len-i) == 0 || (i-start) == 0){\n          throw new JSchException(\"invalid privatekey: \"+prvkey);\n        }\n\n        // The content of 'buf' will be changed, so it should be copied.\n        byte[] tmp = new byte[i-start];\n        System.arraycopy(buf, start, tmp, 0, tmp.length);\n        byte[] _buf=tmp;\n\n        start = 0;\n        i = 0;\n\n        int _len = _buf.length;\n        while(i<_len){\n          if(_buf[i]==0x0a){\n            boolean xd=(_buf[i-1]==0x0d);\n            // ignore 0x0a (or 0x0d0x0a)\n            System.arraycopy(_buf, i+1, _buf, i-(xd ? 1 : 0), _len-(i+1));\n            if(xd)_len--;\n            _len--;\n            continue;\n          }\n          if(_buf[i]=='-'){  break; }\n          i++;\n        }\n        \n        if(i-start > 0)\n          data=Util.fromBase64(_buf, start, i-start);\n\n        Util.bzero(_buf);\n      }\n\n      if(data!=null &&\n         data.length>4 &&            // FSecure\n\t data[0]==(byte)0x3f &&\n\t data[1]==(byte)0x6f &&\n\t data[2]==(byte)0xf9 &&\n\t data[3]==(byte)0xeb){\n\n\tBuffer _buf=new Buffer(data);\n\t_buf.getInt();  // 0x3f6ff9be\n\t_buf.getInt();\n\tbyte[]_type=_buf.getString();\n\t//System.err.println(\"type: \"+new String(_type)); \n\tString _cipher=Util.byte2str(_buf.getString());\n\t//System.err.println(\"cipher: \"+_cipher); \n\tif(_cipher.equals(\"3des-cbc\")){\n  \t   _buf.getInt();\n\t   byte[] foo=new byte[data.length-_buf.getOffSet()];\n\t   _buf.getByte(foo);\n\t   data=foo;\n\t   encrypted=true;\n\t   throw new JSchException(\"unknown privatekey format: \"+prvkey);\n\t}\n\telse if(_cipher.equals(\"none\")){\n  \t   _buf.getInt();\n  \t   _buf.getInt();\n\n           encrypted=false;\n\n\t   byte[] foo=new byte[data.length-_buf.getOffSet()];\n\t   _buf.getByte(foo);\n\t   data=foo;\n\t}\n      }\n\n      if(pubkey!=null){\n\ttry{\n\t  buf=pubkey;\n          len=buf.length;\n\t  if(buf.length>4 &&             // FSecure's public key\n\t     buf[0]=='-' && buf[1]=='-' && buf[2]=='-' && buf[3]=='-'){\n\n\t    boolean valid=true;\n\t    i=0;\n\t    do{i++;}while(buf.length>i && buf[i]!=0x0a);\n\t    if(buf.length<=i) {valid=false;}\n\n\t    while(valid){\n\t      if(buf[i]==0x0a){\n\t\tboolean inheader=false;\n\t\tfor(int j=i+1; j<buf.length; j++){\n\t\t  if(buf[j]==0x0a) break;\n\t\t  if(buf[j]==':'){inheader=true; break;}\n\t\t}\n\t\tif(!inheader){\n\t\t  i++; \n\t\t  break;\n\t\t}\n\t      }\n\t      i++;\n\t    }\n\t    if(buf.length<=i){valid=false;}\n\n\t    int start=i;\n\t    while(valid && i<len){\n\t      if(buf[i]==0x0a){\n\t\tSystem.arraycopy(buf, i+1, buf, i, len-i-1);\n\t\tlen--;\n\t\tcontinue;\n\t      }\n\t      if(buf[i]=='-'){  break; }\n\t      i++;\n\t    }\n\t    if(valid){\n\t      publickeyblob=Util.fromBase64(buf, start, i-start);\n\t      if(prvkey==null || type==UNKNOWN){\n\t\tif(publickeyblob[8]=='d'){ type=DSA; }\n\t\telse if(publickeyblob[8]=='r'){ type=RSA; }\n\t      }\n\t    }\n\t  }\n\t  else{\n\t    if(buf[0]=='s'&& buf[1]=='s'&& buf[2]=='h' && buf[3]=='-'){\n              if(prvkey==null &&\n                 buf.length>7){\n\t\tif(buf[4]=='d'){ type=DSA; }\n\t\telse if(buf[4]=='r'){ type=RSA; }\n              }\n\t      i=0;\n\t      while(i<len){ if(buf[i]==' ')break; i++;} i++;\n\t      if(i<len){\n\t\tint start=i;\n\t\twhile(i<len){ if(buf[i]==' ')break; i++;}\n\t\tpublickeyblob=Util.fromBase64(buf, start, i-start);\n\t      }\n              if(i++<len){\n                int start=i;\n                while(i<len){ if(buf[i]=='\\n')break; i++;}\n                if(i>0 && buf[i-1]==0x0d) i--;\n                if(start<i){\n                  publicKeyComment = new String(buf, start, i-start);\n                }\n              } \n\t    }\n            else if(buf[0]=='e'&& buf[1]=='c'&& buf[2]=='d' && buf[3]=='s'){\n              if(prvkey==null && buf.length>7){\n               type=ECDSA;\n              }\n              i=0;\n              while(i<len){ if(buf[i]==' ')break; i++;} i++;\n              if(i<len){\n                int start=i;\n                while(i<len){ if(buf[i]==' ')break; i++;}\n                publickeyblob=Util.fromBase64(buf, start, i-start);\n              }\n              if(i++<len){\n                int start=i;\n                while(i<len){ if(buf[i]=='\\n')break; i++;}\n                if(i>0 && buf[i-1]==0x0d) i--;\n                if(start<i){\n                  publicKeyComment = new String(buf, start, i-start);\n                }\n              } \n            }\n\t  }\n\t}\n\tcatch(Exception ee){\n\t}\n      }\n    }\n    catch(Exception e){\n      if(e instanceof JSchException) throw (JSchException)e;\n      if(e instanceof Throwable)\n        throw new JSchException(e.toString(), (Throwable)e);\n      throw new JSchException(e.toString());\n    }\n\n    KeyPair kpair=null;\n    if(type==DSA){ kpair=new KeyPairDSA(jsch); }\n    else if(type==RSA){ kpair=new KeyPairRSA(jsch); }\n    else if(type==ECDSA){ kpair=new KeyPairECDSA(jsch); }\n    else if(vendor==VENDOR_PKCS8){ kpair = new KeyPairPKCS8(jsch); }\n\n    if(kpair!=null){\n      kpair.encrypted=encrypted;\n      kpair.publickeyblob=publickeyblob;\n      kpair.vendor=vendor;\n      kpair.publicKeyComment=publicKeyComment;\n      kpair.cipher=cipher;\n\n      if(encrypted){\n        kpair.encrypted=true;\n\tkpair.iv=iv;\n\tkpair.data=data;\n      }\n      else{\n\tif(kpair.parse(data)){\n          kpair.encrypted=false;\n\t  return kpair;\n\t}\n\telse{\n\t  throw new JSchException(\"invalid privatekey: \"+prvkey);\n\t}\n      }\n    }\n\n    return kpair;\n  }\n\n  static private byte a2b(byte c){\n    if('0'<=c&&c<='9') return (byte)(c-'0');\n    return (byte)(c-'a'+10);\n  }\n  static private byte b2a(byte c){\n    if(0<=c&&c<=9) return (byte)(c+'0');\n    return (byte)(c-10+'A');\n  }\n\n  public void dispose(){\n    Util.bzero(passphrase);\n  }\n\n  public void finalize (){\n    dispose();\n  }\n\n  private static final String[] header1 = {\n    \"PuTTY-User-Key-File-2: \",\n    \"Encryption: \",\n    \"Comment: \",\n    \"Public-Lines: \"\n  };\n\n  private static final String[] header2 = {\n    \"Private-Lines: \"\n  };\n\n  private static final String[] header3 = {\n    \"Private-MAC: \"\n  };\n\n  @SuppressWarnings({\"static\"}) static KeyPair loadPPK(JSch jsch, byte[] buf) throws JSchException {\n    byte[] pubkey = null;\n    byte[] prvkey = null;\n    int lines = 0;\n\n    Buffer buffer = new Buffer(buf);\n    java.util.Hashtable v = new java.util.Hashtable();\n\n    while(true){\n      if(!parseHeader(buffer, v))\n        break;\n    } \n\n    String typ = (String)v.get(\"PuTTY-User-Key-File-2\");\n    if(typ == null){\n      return null;\n    }\n\n    lines = Integer.parseInt((String)v.get(\"Public-Lines\"));\n    pubkey = parseLines(buffer, lines); \n\n    while(true){\n      if(!parseHeader(buffer, v))\n        break;\n    } \n    \n    lines = Integer.parseInt((String)v.get(\"Private-Lines\"));\n    prvkey = parseLines(buffer, lines); \n\n    while(true){\n      if(!parseHeader(buffer, v))\n        break;\n    } \n\n    prvkey = Util.fromBase64(prvkey, 0, prvkey.length);\n    pubkey = Util.fromBase64(pubkey, 0, pubkey.length);\n\n    KeyPair kpair = null;\n\n    if(typ.equals(\"ssh-rsa\")) {\n\n      Buffer _buf = new Buffer(pubkey);\n      _buf.skip(pubkey.length);\n\n      int len = _buf.getInt();\n      _buf.getByte(new byte[len]);             // ssh-rsa\n      byte[] pub_array = new byte[_buf.getInt()];\n      _buf.getByte(pub_array);\n      byte[] n_array = new byte[_buf.getInt()];\n      _buf.getByte(n_array);\n\n      kpair = new KeyPairRSA(jsch, n_array, pub_array, null);\n    }\n    else if(typ.equals(\"ssh-dss\")){\n      Buffer _buf = new Buffer(pubkey);\n      _buf.skip(pubkey.length);\n\n      int len = _buf.getInt();\n      _buf.getByte(new byte[len]);              // ssh-dss\n\n      byte[] p_array = new byte[_buf.getInt()];\n      _buf.getByte(p_array);\n      byte[] q_array = new byte[_buf.getInt()];\n      _buf.getByte(q_array);\n      byte[] g_array = new byte[_buf.getInt()];\n      _buf.getByte(g_array);\n      byte[] y_array = new byte[_buf.getInt()];\n      _buf.getByte(y_array);\n\n      kpair = new KeyPairDSA(jsch, p_array, q_array, g_array, y_array, null);\n    }\n    else {\n      return null;\n    }\n\n    if(kpair == null)\n      return null;\n\n    kpair.encrypted = !v.get(\"Encryption\").equals(\"none\");\n    kpair.vendor = VENDOR_PUTTY;\n    kpair.publicKeyComment = (String)v.get(\"Comment\");\n    if(kpair.encrypted){\n      if(Session.checkCipher((String)jsch.getConfig(\"aes256-cbc\"))){\n        try {\n          Class c=Class.forName((String)jsch.getConfig(\"aes256-cbc\"));\n          kpair.cipher=(Cipher)(c.newInstance());\n          kpair.iv=new byte[kpair.cipher.getIVSize()];\n        }\n        catch(Exception e){\n          throw new JSchException(\"The cipher 'aes256-cbc' is required, but it is not available.\");\n        }\n      }\n      else {\n        throw new JSchException(\"The cipher 'aes256-cbc' is required, but it is not available.\");\n      }\n      kpair.data = prvkey;\n    }\n    else {\n      kpair.data = prvkey;\n      kpair.parse(prvkey);\n    }\n    return kpair;\n  }\n\n  private static byte[] parseLines(Buffer buffer, int lines){\n    byte[] buf = buffer.buffer;\n    int index = buffer.index;\n    byte[] data = null;\n\n    int i = index;\n    while(lines-->0){\n      while(buf.length > i){\n        if(buf[i++] == 0x0d){\n          if(data == null){\n            data = new byte[i - index - 1];\n            System.arraycopy(buf, index, data, 0, i - index - 1);\n          }\n          else {\n            byte[] tmp = new byte[data.length + i - index - 1];\n            System.arraycopy(data, 0, tmp, 0, data.length);\n            System.arraycopy(buf, index, tmp, data.length, i - index -1);\n            for(int j = 0; j < data.length; j++) data[j] = 0; // clear\n            data = tmp;\n          } \n          break;\n        }\n      }\n      if(buf[i]==0x0a)\n        i++;\n      index=i;\n    }\n\n    if(data != null)\n      buffer.index = index;\n\n    return data;\n  }\n\n  private static boolean parseHeader(Buffer buffer, java.util.Hashtable v){\n    byte[] buf = buffer.buffer;\n    int index = buffer.index;\n    String key = null;\n    String value = null;\n    for(int i = index; i < buf.length; i++){\n      if(buf[i] == 0x0d){\n        break;\n      }\n      if(buf[i] == ':'){\n        key = new String(buf, index, i - index);\n        i++;\n        if(i < buf.length && buf[i] == ' '){\n          i++;\n        }\n        index = i;\n        break;\n      }\n    }\n\n    if(key == null)\n      return false;\n\n    for(int i = index; i < buf.length; i++){\n      if(buf[i] == 0x0d){\n        value = new String(buf, index, i - index);\n        i++;\n        if(i < buf.length && buf[i] == 0x0a){\n          i++;\n        }\n        index = i;\n        break;\n      }\n    }\n\n    if(value != null){\n      v.put(key, value);\n      buffer.index = index;\n    }\n\n    return (key != null && value != null);\n  }\n\n  void copy(KeyPair kpair){\n    this.publickeyblob=kpair.publickeyblob;\n    this.vendor=kpair.vendor;\n    this.publicKeyComment=kpair.publicKeyComment;\n    this.cipher=kpair.cipher;\n  }\n\n  class ASN1Exception extends Exception {\n  }\n\n  class ASN1 {\n    byte[] buf;\n    int start;\n    int length;\n    ASN1(byte[] buf) throws ASN1Exception {\n      this(buf, 0, buf.length);\n    }\n    ASN1(byte[] buf, int start, int length) throws ASN1Exception {\n      this.buf = buf;\n      this.start = start;\n      this.length = length;\n      if(start+length>buf.length)\n        throw new ASN1Exception();\n    }\n    int getType() {\n      return buf[start]&0xff;\n    }\n    boolean isSEQUENCE() {\n      return getType()==(0x30&0xff);\n    }\n    boolean isINTEGER() {\n      return getType()==(0x02&0xff);\n    }\n    boolean isOBJECT() {\n      return getType()==(0x06&0xff);\n    }\n    boolean isOCTETSTRING() {\n      return getType()==(0x04&0xff);\n    }\n    private int getLength(int[] indexp) {\n      int index=indexp[0];\n      int length=buf[index++]&0xff;\n      if((length&0x80)!=0) {\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(buf[index++]&0xff); }\n      }\n      indexp[0]=index;\n      return length;\n    }\n    byte[] getContent() {\n      int[] indexp=new int[1];\n      indexp[0]=start+1;\n      int length = getLength(indexp);\n      int index=indexp[0];\n      byte[] tmp = new byte[length];\n      System.arraycopy(buf, index, tmp, 0, tmp.length);\n      return tmp;\n    }\n    ASN1[] getContents() throws ASN1Exception {\n      int typ = buf[start];\n      int[] indexp=new int[1];\n      indexp[0]=start+1;\n      int length = getLength(indexp);\n      if(typ == 0x05){\n        return new ASN1[0];\n      }\n      int index=indexp[0];\n      java.util.Vector values = new java.util.Vector();\n      while(length>0) {\n        index++; length--;\n        int tmp=index;\n        indexp[0]=index;\n        int l=getLength(indexp);\n        index=indexp[0];\n        length-=(index-tmp);\n        values.addElement(new ASN1(buf, tmp-1, 1+(index-tmp)+l));\n        index+=l;\n        length-=l;\n      }\n      ASN1[] result = new ASN1[values.size()];\n      for(int  i = 0; i <values.size(); i++) {\n        result[i]=(ASN1)values.elementAt(i);\n      }\n      return result;\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/KeyPairDSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class KeyPairDSA extends KeyPair{\n  private byte[] P_array;\n  private byte[] Q_array;\n  private byte[] G_array;\n  private byte[] pub_array;\n  private byte[] prv_array;\n\n  //private int key_size=0;\n  private int key_size=1024;\n\n  public KeyPairDSA(JSch jsch){\n    this(jsch, null, null, null, null, null);\n  }\n\n  public KeyPairDSA(JSch jsch,\n                    byte[] P_array,\n                    byte[] Q_array,\n                    byte[] G_array,\n                    byte[] pub_array,\n                    byte[] prv_array){\n    super(jsch);\n    this.P_array = P_array;\n    this.Q_array = Q_array;\n    this.G_array = G_array;\n    this.pub_array = pub_array;\n    this.prv_array = prv_array;\n    if(P_array!=null)\n      key_size = (new java.math.BigInteger(P_array)).bitLength();\n  }\n\n  @SuppressWarnings({\"static\"}) void generate(int key_size) throws JSchException{\n    this.key_size=key_size;\n    try{\n      Class c=Class.forName(jsch.getConfig(\"keypairgen.dsa\"));\n      KeyPairGenDSA keypairgen=(KeyPairGenDSA)(c.newInstance());\n      keypairgen.init(key_size);\n      P_array=keypairgen.getP();\n      Q_array=keypairgen.getQ();\n      G_array=keypairgen.getG();\n      pub_array=keypairgen.getY();\n      prv_array=keypairgen.getX();\n\n      keypairgen=null;\n    }\n    catch(Exception e){\n      //System.err.println(\"KeyPairDSA: \"+e); \n      if(e instanceof Throwable)\n        throw new JSchException(e.toString(), (Throwable)e);\n      throw new JSchException(e.toString());\n    }\n  }\n\n  private static final byte[] begin=Util.str2byte(\"-----BEGIN DSA PRIVATE KEY-----\");\n  private static final byte[] end=Util.str2byte(\"-----END DSA PRIVATE KEY-----\");\n\n  byte[] getBegin(){ return begin; }\n  byte[] getEnd(){ return end; }\n\n  byte[] getPrivateKey(){\n    int content=\n      1+countLength(1) + 1 +                           // INTEGER\n      1+countLength(P_array.length) + P_array.length + // INTEGER  P\n      1+countLength(Q_array.length) + Q_array.length + // INTEGER  Q\n      1+countLength(G_array.length) + G_array.length + // INTEGER  G\n      1+countLength(pub_array.length) + pub_array.length + // INTEGER  pub\n      1+countLength(prv_array.length) + prv_array.length;  // INTEGER  prv\n\n    int total=\n      1+countLength(content)+content;   // SEQUENCE\n\n    byte[] plain=new byte[total];\n    int index=0;\n    index=writeSEQUENCE(plain, index, content);\n    index=writeINTEGER(plain, index, new byte[1]);  // 0\n    index=writeINTEGER(plain, index, P_array);\n    index=writeINTEGER(plain, index, Q_array);\n    index=writeINTEGER(plain, index, G_array);\n    index=writeINTEGER(plain, index, pub_array);\n    index=writeINTEGER(plain, index, prv_array);\n    return plain;\n  }\n\n  boolean parse(byte[] plain){\n    try{\n\n      if(vendor==VENDOR_FSECURE){\n\tif(plain[0]!=0x30){              // FSecure\n\t  Buffer buf=new Buffer(plain);\n\t  buf.getInt();\n\t  P_array=buf.getMPIntBits();\n\t  G_array=buf.getMPIntBits();\n\t  Q_array=buf.getMPIntBits();\n\t  pub_array=buf.getMPIntBits();\n\t  prv_array=buf.getMPIntBits();\n          if(P_array!=null)\n            key_size = (new java.math.BigInteger(P_array)).bitLength();\n\t  return true;\n\t}\n\treturn false;\n      }\n      else if(vendor==VENDOR_PUTTY){\n        Buffer buf=new Buffer(plain);\n        buf.skip(plain.length);\n\n        try {\n          byte[][] tmp = buf.getBytes(1, \"\");\n          prv_array = tmp[0];\n        }\n        catch(JSchException e){\n          return false;\n        }\n\n        return true;\n      }\n\n      int index=0;\n      int length=0;\n\n      if(plain[index]!=0x30)return false;\n      index++; // SEQUENCE\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n\n      if(plain[index]!=0x02)return false;\n      index++; // INTEGER\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      P_array=new byte[length];\n      System.arraycopy(plain, index, P_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      Q_array=new byte[length];\n      System.arraycopy(plain, index, Q_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      G_array=new byte[length];\n      System.arraycopy(plain, index, G_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      pub_array=new byte[length];\n      System.arraycopy(plain, index, pub_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      prv_array=new byte[length];\n      System.arraycopy(plain, index, prv_array, 0, length);\n      index+=length;\n\n      if(P_array!=null)\n        key_size = (new java.math.BigInteger(P_array)).bitLength();\n    }\n    catch(Exception e){\n      //System.err.println(e);\n      //e.printStackTrace();\n      return false;\n    }\n    return true;\n  }\n\n  public byte[] getPublicKeyBlob(){\n    byte[] foo=super.getPublicKeyBlob();\n    if(foo!=null) return foo;\n\n    if(P_array==null) return null;\n    byte[][] tmp = new byte[5][];\n    tmp[0] = sshdss;\n    tmp[1] = P_array;\n    tmp[2] = Q_array;\n    tmp[3] = G_array;\n    tmp[4] = pub_array;\n    return Buffer.fromBytes(tmp).buffer;\n  }\n\n  private static final byte[] sshdss=Util.str2byte(\"ssh-dss\");\n  byte[] getKeyTypeName(){return sshdss;}\n  public int getKeyType(){return DSA;}\n\n  public int getKeySize(){\n    return key_size;\n  }\n\n  @SuppressWarnings({\"static\"}) public byte[] getSignature(byte[] data){\n    try{      \n      Class c=Class.forName((String)jsch.getConfig(\"signature.dss\"));\n      SignatureDSA dsa=(SignatureDSA)(c.newInstance());\n      dsa.init();\n      dsa.setPrvKey(prv_array, P_array, Q_array, G_array);\n\n      dsa.update(data);\n      byte[] sig = dsa.sign();\n      byte[][] tmp = new byte[2][];\n      tmp[0] = sshdss;\n      tmp[1] = sig;\n      return Buffer.fromBytes(tmp).buffer;\n    }\n    catch(Exception e){\n      //System.err.println(\"e \"+e);\n    }\n    return null;\n  }\n\n  @SuppressWarnings({\"static\"}) public Signature getVerifier(){\n    try{      \n      Class c=Class.forName((String)jsch.getConfig(\"signature.dss\"));\n      SignatureDSA dsa=(SignatureDSA)(c.newInstance());\n      dsa.init();\n\n      if(pub_array == null && P_array == null && getPublicKeyBlob()!=null){\n        Buffer buf = new Buffer(getPublicKeyBlob());\n        buf.getString();\n        P_array = buf.getString();\n        Q_array = buf.getString();\n        G_array = buf.getString();\n        pub_array = buf.getString();\n      } \n\n      dsa.setPubKey(pub_array, P_array, Q_array, G_array);\n      return dsa;\n    }\n    catch(Exception e){\n      //System.err.println(\"e \"+e);\n    }\n    return null;\n  }\n\n  static KeyPair fromSSHAgent(JSch jsch, Buffer buf) throws JSchException {\n\n    byte[][] tmp = buf.getBytes(7, \"invalid key format\");\n\n    byte[] P_array = tmp[1];\n    byte[] Q_array = tmp[2];\n    byte[] G_array = tmp[3];\n    byte[] pub_array = tmp[4];\n    byte[] prv_array = tmp[5];\n    KeyPairDSA kpair = new KeyPairDSA(jsch,\n                                      P_array, Q_array, G_array,\n                                      pub_array, prv_array);\n    kpair.publicKeyComment = new String(tmp[6]);\n    kpair.vendor=VENDOR_OPENSSH;\n    return kpair;\n  }\n\n  public byte[] forSSHAgent() throws JSchException {\n    if(isEncrypted()){\n      throw new JSchException(\"key is encrypted.\");\n    }\n    Buffer buf = new Buffer();\n    buf.putString(sshdss);\n    buf.putString(P_array);\n    buf.putString(Q_array);\n    buf.putString(G_array);\n    buf.putString(pub_array);\n    buf.putString(prv_array);\n    buf.putString(Util.str2byte(publicKeyComment));\n    byte[] result = new byte[buf.getLength()];\n    buf.getByte(result, 0, result.length);\n    return result;\n  }\n\n  public void dispose(){\n    super.dispose();\n    Util.bzero(prv_array);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/KeyPairECDSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class KeyPairECDSA extends KeyPair{\n\n  private static byte[][] oids = {\n    {(byte)0x06, (byte)0x08, (byte)0x2a, (byte)0x86, (byte)0x48, // 256\n     (byte)0xce, (byte)0x3d, (byte)0x03, (byte)0x01, (byte)0x07},\n    {(byte)0x06, (byte)0x05, (byte)0x2b, (byte)0x81, (byte)0x04, // 384\n     (byte)0x00, (byte)0x22},\n    {(byte)0x06, (byte)0x05, (byte)0x2b, (byte)0x81, (byte)0x04, //521\n     (byte)0x00, (byte)0x23},\n  };\n\n  private static String[] names = {\n    \"nistp256\", \"nistp384\", \"nistp521\"\n  };\n\n  private byte[] name=Util.str2byte(names[0]);\n  private byte[] r_array;\n  private byte[] s_array;\n  private byte[] prv_array;\n\n  private int key_size=256;\n\n  public KeyPairECDSA(JSch jsch){\n    this(jsch, null, null, null, null);\n  }\n\n  public KeyPairECDSA(JSch jsch,\n                      byte[] name,\n                      byte[] r_array,\n                      byte[] s_array,\n                      byte[] prv_array){\n    super(jsch);\n    if(name!=null)\n      this.name = name;\n    this.r_array = r_array;\n    this.s_array = s_array;\n    this.prv_array = prv_array;\n    if(prv_array!=null)\n      key_size = prv_array.length>=64 ? 521 : \n                  (prv_array.length>=48 ? 384 : 256);\n  }\n\n  @SuppressWarnings({\"static\"}) void generate(int key_size) throws JSchException{\n    this.key_size=key_size;\n    try{\n      Class c=Class.forName(jsch.getConfig(\"keypairgen.ecdsa\"));\n      KeyPairGenECDSA keypairgen=(KeyPairGenECDSA)(c.newInstance());\n      keypairgen.init(key_size);\n      prv_array=keypairgen.getD();\n      r_array=keypairgen.getR();\n      s_array=keypairgen.getS();\n      name=Util.str2byte(names[prv_array.length>=64 ? 2 :\n                               (prv_array.length>=48 ? 1 : 0)]);\n      keypairgen=null;\n    }\n    catch(Exception e){\n      if(e instanceof Throwable)\n        throw new JSchException(e.toString(), (Throwable)e);\n      throw new JSchException(e.toString());\n    }\n  }\n\n  private static final byte[] begin = \n    Util.str2byte(\"-----BEGIN EC PRIVATE KEY-----\");\n  private static final byte[] end =\n    Util.str2byte(\"-----END EC PRIVATE KEY-----\");\n\n  byte[] getBegin(){ return begin; }\n  byte[] getEnd(){ return end; }\n\n  byte[] getPrivateKey(){\n\n    byte[] tmp = new byte[1]; tmp[0]=1;\n\n    byte[] oid = oids[\n                      (r_array.length>=64) ? 2 :\n                       ((r_array.length>=48) ? 1 : 0)\n                     ];\n\n    byte[] point = toPoint(r_array, s_array);\n\n    int bar = ((point.length+1)&0x80)==0 ? 3 : 4;\n    byte[] foo = new byte[point.length+bar];\n    System.arraycopy(point, 0, foo, bar, point.length);\n    foo[0]=0x03;                     // BITSTRING \n    if(bar==3){\n      foo[1]=(byte)(point.length+1);\n    }\n    else {\n      foo[1]=(byte)0x81;\n      foo[2]=(byte)(point.length+1);\n    }\n    point = foo;\n\n    int content=\n      1+countLength(tmp.length) + tmp.length +\n      1+countLength(prv_array.length) + prv_array.length +\n      1+countLength(oid.length) + oid.length +\n      1+countLength(point.length) + point.length;\n\n    int total=\n      1+countLength(content)+content;   // SEQUENCE\n\n    byte[] plain=new byte[total];\n    int index=0;\n    index=writeSEQUENCE(plain, index, content);\n    index=writeINTEGER(plain, index, tmp);\n    index=writeOCTETSTRING(plain, index, prv_array);\n    index=writeDATA(plain, (byte)0xa0, index, oid);\n    index=writeDATA(plain, (byte)0xa1, index, point);\n\n    return plain;\n  }\n\n  boolean parse(byte[] plain){\n    try{\n\n      if(vendor==VENDOR_FSECURE){\n        /*\n\tif(plain[0]!=0x30){              // FSecure\n\t  return true;\n\t}\n\treturn false;\n        */\n\treturn false;\n      }\n      else if(vendor==VENDOR_PUTTY){\n        /*\n        Buffer buf=new Buffer(plain);\n        buf.skip(plain.length);\n\n        try {\n          byte[][] tmp = buf.getBytes(1, \"\");\n          prv_array = tmp[0];\n        }\n        catch(JSchException e){\n          return false;\n        }\n\n        return true;\n        */\n\treturn false;\n      }\n\n      int index=0;\n      int length=0;\n\n      if(plain[index]!=0x30)return false;\n      index++; // SEQUENCE\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n\n      if(plain[index]!=0x02)return false;\n      index++; // INTEGER\n\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n\n      index+=length;\n      index++;   // 0x04\n\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n\n      prv_array=new byte[length];\n      System.arraycopy(plain, index, prv_array, 0, length);\n\n      index+=length;\n\n      index++;  // 0xa0\n\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n\n      byte[] oid_array=new byte[length];\n      System.arraycopy(plain, index, oid_array, 0, length);\n      index+=length;\n\n      for(int i = 0; i<oids.length; i++){\n        if(Util.array_equals(oids[i], oid_array)){\n          name = Util.str2byte(names[i]);\n          break;\n        }\n      }\n\n      index++;  // 0xa1\n\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n\n      byte[] Q_array=new byte[length];\n      System.arraycopy(plain, index, Q_array, 0, length);\n      index+=length;\n\n      byte[][] tmp = fromPoint(Q_array);\n      r_array = tmp[0];\n      s_array = tmp[1];\n\n      if(prv_array!=null)\n        key_size = prv_array.length>=64 ? 521 : \n                    (prv_array.length>=48 ? 384 : 256);\n    }\n    catch(Exception e){\n      //System.err.println(e);\n      //e.printStackTrace();\n      return false;\n    }\n    return true;\n  }\n\n  public byte[] getPublicKeyBlob(){\n    byte[] foo = super.getPublicKeyBlob();\n\n    if(foo!=null) return foo;\n\n    if(r_array==null) return null;\n\n    byte[][] tmp = new byte[3][];\n    tmp[0] = Util.str2byte(\"ecdsa-sha2-\"+new String(name));\n    tmp[1] = name;\n    tmp[2] = new byte[1+r_array.length+s_array.length];\n    tmp[2][0] = 4;   // POINT_CONVERSION_UNCOMPRESSED\n    System.arraycopy(r_array, 0, tmp[2], 1, r_array.length);\n    System.arraycopy(s_array, 0, tmp[2], 1+r_array.length, s_array.length);\n\n    return Buffer.fromBytes(tmp).buffer;\n  }\n\n  byte[] getKeyTypeName(){\n    return Util.str2byte(\"ecdsa-sha2-\"+new String(name));\n  }\n  public int getKeyType(){\n    return ECDSA;\n  }\n  public int getKeySize(){\n    return key_size;\n  }\n\n  @SuppressWarnings({\"static\"}) public byte[] getSignature(byte[] data){\n    try{      \n      Class c=Class.forName((String)jsch.getConfig(\"signature.ecdsa\"));\n      SignatureECDSA ecdsa=(SignatureECDSA)(c.newInstance());\n      ecdsa.init();\n      ecdsa.setPrvKey(prv_array);\n\n      ecdsa.update(data);\n      byte[] sig = ecdsa.sign();\n\n      byte[][] tmp = new byte[2][];\n      tmp[0] = Util.str2byte(\"ecdsa-sha2-\"+new String(name));\n      tmp[1] = sig;\n      return Buffer.fromBytes(tmp).buffer;\n    }\n    catch(Exception e){\n      //System.err.println(\"e \"+e);\n    }\n    return null;\n  }\n\n  @SuppressWarnings({\"static\"}) public Signature getVerifier(){\n    try{      \n      Class c=Class.forName((String)jsch.getConfig(\"signature.ecdsa\"));\n      final SignatureECDSA ecdsa=(SignatureECDSA)(c.newInstance());\n      ecdsa.init();\n\n      if(r_array == null && s_array == null && getPublicKeyBlob()!=null){\n        Buffer buf = new Buffer(getPublicKeyBlob());\n        buf.getString();    // ecdsa-sha2-nistp256\n        buf.getString();    // nistp256\n        byte[][] tmp = fromPoint(buf.getString());\n        r_array = tmp[0];\n        s_array = tmp[1];\n      } \n      ecdsa.setPubKey(r_array, s_array);\n      return ecdsa;\n    }\n    catch(Exception e){\n      //System.err.println(\"e \"+e);\n    }\n    return null;\n  }\n\n  static KeyPair fromSSHAgent(JSch jsch, Buffer buf) throws JSchException {\n\n    byte[][] tmp = buf.getBytes(5, \"invalid key format\");\n\n    byte[] name = tmp[1];       // nistp256\n    byte[][] foo = fromPoint(tmp[2]);\n    byte[] r_array = foo[0];\n    byte[] s_array = foo[1];\n\n    byte[] prv_array = tmp[3];\n    KeyPairECDSA kpair = new KeyPairECDSA(jsch,\n                                          name,\n                                          r_array, s_array,\n                                          prv_array);\n    kpair.publicKeyComment = new String(tmp[4]);\n    kpair.vendor=VENDOR_OPENSSH;\n    return kpair;\n  }\n\n  public byte[] forSSHAgent() throws JSchException {\n    if(isEncrypted()){\n      throw new JSchException(\"key is encrypted.\");\n    }\n    Buffer buf = new Buffer();\n    buf.putString(Util.str2byte(\"ecdsa-sha2-\"+new String(name)));\n    buf.putString(name);\n    buf.putString(toPoint(r_array, s_array));\n    buf.putString(prv_array);\n    buf.putString(Util.str2byte(publicKeyComment));\n    byte[] result = new byte[buf.getLength()];\n    buf.getByte(result, 0, result.length);\n    return result;\n  }\n\n  static byte[] toPoint(byte[] r_array, byte[] s_array) {\n    byte[] tmp = new byte[1+r_array.length+s_array.length];\n    tmp[0]=0x04;\n    System.arraycopy(r_array, 0, tmp, 1, r_array.length);\n    System.arraycopy(s_array, 0, tmp, 1+r_array.length, s_array.length);\n    return tmp;\n  }\n\n  static byte[][] fromPoint(byte[] point) {\n    int i = 0;\n    while(point[i]!=4) i++;\n    i++;\n    byte[][] tmp = new byte[2][];\n    byte[] r_array = new byte[(point.length-i)/2];\n    byte[] s_array = new byte[(point.length-i)/2];\n    // point[0] == 0x04 == POINT_CONVERSION_UNCOMPRESSED\n    System.arraycopy(point, i, r_array, 0, r_array.length);\n    System.arraycopy(point, i+r_array.length, s_array, 0, s_array.length);\n    tmp[0] = r_array;\n    tmp[1] = s_array;\n\n    return tmp;\n  }\n\n  public void dispose(){\n    super.dispose();\n    Util.bzero(prv_array);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/KeyPairGenDSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface KeyPairGenDSA{\n  void init(int key_size) throws Exception;\n  byte[] getX();\n  byte[] getY();\n  byte[] getP();\n  byte[] getQ();\n  byte[] getG();\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/KeyPairGenECDSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface KeyPairGenECDSA{\n  void init(int key_size) throws Exception;\n  byte[] getD();\n  byte[] getR();\n  byte[] getS();\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/KeyPairGenRSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface KeyPairGenRSA{\n  void init(int key_size) throws Exception;\n  byte[] getD();\n  byte[] getE();\n  byte[] getN();\n\n  byte[] getC();\n  byte[] getEP();\n  byte[] getEQ();\n  byte[] getP();\n  byte[] getQ();\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/KeyPairPKCS8.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2013-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.util.Vector;\nimport java.math.BigInteger;\n\npublic class KeyPairPKCS8 extends KeyPair {\n  private static final byte[] rsaEncryption = {\n    (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86,\n    (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01\n  };\n\n  private static final byte[] dsaEncryption = {\n    (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0xce,\n    (byte)0x38, (byte)0x04, (byte)0x1\n  };\n\n  private static final byte[] pbes2 = {\n    (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,\n    (byte)0x0d, (byte)0x01, (byte)0x05, (byte)0x0d \n  };\n\n  private static final byte[] pbkdf2 = {\n    (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,\n    (byte)0x0d, (byte)0x01, (byte)0x05, (byte)0x0c \n  };\n\n  private static final byte[] aes128cbc = {\n    (byte)0x60, (byte)0x86, (byte)0x48, (byte)0x01, (byte)0x65,\n    (byte)0x03, (byte)0x04, (byte)0x01, (byte)0x02 \n  };\n\n  private static final byte[] aes192cbc = {\n    (byte)0x60, (byte)0x86, (byte)0x48, (byte)0x01, (byte)0x65,\n    (byte)0x03, (byte)0x04, (byte)0x01, (byte)0x16 \n  };\n\n  private static final byte[] aes256cbc = {\n    (byte)0x60, (byte)0x86, (byte)0x48, (byte)0x01, (byte)0x65,\n    (byte)0x03, (byte)0x04, (byte)0x01, (byte)0x2a \n  };\n\n  private static final byte[] pbeWithMD5AndDESCBC = {\n    (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,\n    (byte)0x0d, (byte)0x01, (byte)0x05, (byte)0x03\n  };\n\n  private KeyPair kpair = null;\n\n  public KeyPairPKCS8(JSch jsch){\n    super(jsch);\n  }\n\n  void generate(int key_size) throws JSchException{\n  }\n\n  private static final byte[] begin=Util.str2byte(\"-----BEGIN DSA PRIVATE KEY-----\");\n  private static final byte[] end=Util.str2byte(\"-----END DSA PRIVATE KEY-----\");\n\n  byte[] getBegin(){ return begin; }\n  byte[] getEnd(){ return end; }\n\n  byte[] getPrivateKey(){\n    return null;\n  }\n\n  boolean parse(byte[] plain){\n\n    /* from RFC5208\n      PrivateKeyInfo ::= SEQUENCE {\n        version                   Version,\n        privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,\n        privateKey                PrivateKey,\n        attributes           [0]  IMPLICIT Attributes OPTIONAL \n      }\n      Version ::= INTEGER\n      PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier\n      PrivateKey ::= OCTET STRING\n      Attributes ::= SET OF Attribute\n    }\n    */\n\n    try{\n      Vector values = new Vector();\n\n      ASN1[] contents = null;\n      ASN1 asn1 = new ASN1(plain);\n      contents = asn1.getContents();\n\n      ASN1 privateKeyAlgorithm = contents[1];\n      ASN1 privateKey = contents[2];\n\n      contents = privateKeyAlgorithm.getContents();\n      byte[] privateKeyAlgorithmID = contents[0].getContent();\n      contents = contents[1].getContents();\n      if(contents.length>0){\n        for(int i = 0; i < contents.length; i++){\n          values.addElement(contents[i].getContent());\n        }\n      }\n\n      byte[] _data = privateKey.getContent();\n\n      KeyPair _kpair = null;\n      if(Util.array_equals(privateKeyAlgorithmID, rsaEncryption)){\n        _kpair = new KeyPairRSA(jsch);\n        _kpair.copy(this);\n        if(_kpair.parse(_data)){\n          kpair = _kpair;\n        } \n      }\n      else if(Util.array_equals(privateKeyAlgorithmID, dsaEncryption)){\n        asn1 = new ASN1(_data);\n        if(values.size() == 0) {  // embedded DSA parameters format\n          /*\n             SEQUENCE\n               SEQUENCE\n                 INTEGER    // P_array\n                 INTEGER    // Q_array\n                 INTEGER    // G_array\n               INTEGER      // prv_array\n          */\n          contents = asn1.getContents();\n          byte[] bar = contents[1].getContent();\n          contents = contents[0].getContents();\n          for(int i = 0; i < contents.length; i++){\n            values.addElement(contents[i].getContent());\n          }\n          values.addElement(bar);\n        }\n        else {\n          /*\n             INTEGER      // prv_array\n          */\n          values.addElement(asn1.getContent());\n        }\n\n        byte[] P_array = (byte[])values.elementAt(0);\n        byte[] Q_array = (byte[])values.elementAt(1);\n        byte[] G_array = (byte[])values.elementAt(2);\n        byte[] prv_array = (byte[])values.elementAt(3);\n        // Y = g^X mode p\n        byte[] pub_array =\n          (new BigInteger(G_array)).\n            modPow(new BigInteger(prv_array), new BigInteger(P_array)).\n            toByteArray();\n\n        KeyPairDSA _key = new KeyPairDSA(jsch,\n                                         P_array, Q_array, G_array,\n                                         pub_array, prv_array);\n        plain = _key.getPrivateKey();\n\n        _kpair = new KeyPairDSA(jsch);\n        _kpair.copy(this);\n        if(_kpair.parse(plain)){\n          kpair = _kpair;\n        }\n      }\n    }\n    catch(ASN1Exception e){\n      return false;\n    }\n    catch(Exception e){\n      //System.err.println(e);\n      return false;\n    }\n    return kpair != null;\n  }\n\n  public byte[] getPublicKeyBlob(){\n    return kpair.getPublicKeyBlob();\n  }\n\n  byte[] getKeyTypeName(){ return kpair.getKeyTypeName();}\n  public int getKeyType(){return kpair.getKeyType();}\n\n  public int getKeySize(){\n    return kpair.getKeySize();\n  }\n\n  public byte[] getSignature(byte[] data){\n    return kpair.getSignature(data);\n  }\n\n  public Signature getVerifier(){\n    return kpair.getVerifier();\n  }\n\n  public byte[] forSSHAgent() throws JSchException {\n    return kpair.forSSHAgent();\n  }\n\n  @SuppressWarnings({\"static\"}) public boolean decrypt(byte[] _passphrase){\n    if(!isEncrypted()){\n      return true;\n    }\n    if(_passphrase==null){\n      return !isEncrypted();\n    }\n\n    /*\n      SEQUENCE\n        SEQUENCE\n          OBJECT            :PBES2\n          SEQUENCE\n            SEQUENCE\n              OBJECT            :PBKDF2\n              SEQUENCE\n                OCTET STRING      [HEX DUMP]:E4E24ADC9C00BD4D\n                INTEGER           :0800\n            SEQUENCE\n              OBJECT            :aes-128-cbc\n              OCTET STRING      [HEX DUMP]:5B66E6B3BF03944C92317BC370CC3AD0\n        OCTET STRING      [HEX DUMP]:\n\nor\n\n      SEQUENCE\n        SEQUENCE\n          OBJECT            :pbeWithMD5AndDES-CBC\n          SEQUENCE\n            OCTET STRING      [HEX DUMP]:DBF75ECB69E3C0FC\n            INTEGER           :0800\n        OCTET STRING      [HEX DUMP]\n    */\n\n    try{\n\n      ASN1[] contents = null;\n      ASN1 asn1 = new ASN1(data);\n\n      contents =  asn1.getContents();\n\n      byte[] _data = contents[1].getContent();\n\n      ASN1 pbes = contents[0];\n      contents = pbes.getContents();\n      byte[] pbesid = contents[0].getContent();\n      ASN1 pbesparam = contents[1];\n\n      byte[] salt = null;\n      int iterations = 0;\n      byte[] iv = null;\n      byte[] encryptfuncid = null;\n\n      if(Util.array_equals(pbesid, pbes2)){\n        contents = pbesparam.getContents();\n        ASN1 pbkdf = contents[0];\n        ASN1 encryptfunc = contents[1];\n        contents = pbkdf.getContents();\n        byte[] pbkdfid = contents[0].getContent();\n        ASN1 pbkdffunc = contents[1];\n        contents = pbkdffunc.getContents();\n        salt = contents[0].getContent();\n        iterations = \n          Integer.parseInt((new BigInteger(contents[1].getContent())).toString());\n\n        contents = encryptfunc.getContents();\n        encryptfuncid = contents[0].getContent();\n        iv = contents[1].getContent();\n      }\n      else if(Util.array_equals(pbesid, pbeWithMD5AndDESCBC)){\n        // not supported\n        return false;\n      }\n      else {\n        return false;\n      }\n\n      Cipher cipher=getCipher(encryptfuncid);\n      if(cipher==null) return false;\n\n      byte[] key=null;\n      try{\n        Class c=Class.forName((String)jsch.getConfig(\"pbkdf\"));\n        PBKDF tmp=(PBKDF)(c.newInstance());\n        key = tmp.getKey(_passphrase, salt, iterations, cipher.getBlockSize());\n      }\n      catch(Exception ee){\n      }\n\n      if(key==null){\n        return false;\n      }\n\n      cipher.init(Cipher.DECRYPT_MODE, key, iv);\n      Util.bzero(key);\n      byte[] plain=new byte[_data.length];\n      cipher.update(_data, 0, _data.length, plain, 0);\n      if(parse(plain)){\n        encrypted=false;\n        return true;\n      }\n    }\n    catch(ASN1Exception e){\n      // System.err.println(e);\n    }\n    catch(Exception e){\n      // System.err.println(e);\n    }\n\n    return false;\n  }\n\n  @SuppressWarnings({\"static\"}) Cipher getCipher(byte[] id){\n    Cipher cipher=null;\n    String name = null;\n    try{\n      if(Util.array_equals(id, aes128cbc)){\n        name=\"aes128-cbc\";\n      }\n      else if(Util.array_equals(id, aes192cbc)){\n        name=\"aes192-cbc\";\n      }\n      else if(Util.array_equals(id, aes256cbc)){\n        name=\"aes256-cbc\";\n      }\n      Class c=Class.forName((String)jsch.getConfig(name));\n      cipher=(Cipher)(c.newInstance());\n    }\n    catch(Exception e){\n      if(JSch.getLogger().isEnabled(Logger.FATAL)){\n        String message=\"\";\n        if(name==null){\n          message=\"unknown oid: \"+Util.toHex(id);\n        }\n        else {\n          message=\"function \"+name+\" is not supported\";\n        }\n        JSch.getLogger().log(Logger.FATAL, \"PKCS8: \"+message);\n      }\n    }\n    return cipher;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/KeyPairRSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.math.BigInteger;\n\npublic class KeyPairRSA extends KeyPair{\n  private byte[] n_array;   // modulus   p multiply q\n  private byte[] pub_array; // e         \n  private byte[] prv_array; // d         e^-1 mod (p-1)(q-1)\n\n  private byte[] p_array;  // prime p\n  private byte[] q_array;  // prime q\n  private byte[] ep_array; // prime exponent p  dmp1 == prv mod (p-1)\n  private byte[] eq_array; // prime exponent q  dmq1 == prv mod (q-1)\n  private byte[] c_array;  // coefficient  iqmp == modinv(q, p) == q^-1 mod p\n\n  private int key_size=1024;\n\n  public KeyPairRSA(JSch jsch){\n    this(jsch, null, null, null);\n  }\n\n  public KeyPairRSA(JSch jsch,\n                    byte[] n_array,\n                    byte[] pub_array,\n                    byte[] prv_array){\n    super(jsch);\n    this.n_array = n_array;\n    this.pub_array = pub_array;\n    this.prv_array = prv_array;\n    if(n_array!=null){\n      key_size = (new java.math.BigInteger(n_array)).bitLength();\n    }\n  }\n\n  @SuppressWarnings({\"static\"}) void generate(int key_size) throws JSchException{\n    this.key_size=key_size;\n    try{\n      Class c=Class.forName(jsch.getConfig(\"keypairgen.rsa\"));\n      KeyPairGenRSA keypairgen=(KeyPairGenRSA)(c.newInstance());\n      keypairgen.init(key_size);\n      pub_array=keypairgen.getE();\n      prv_array=keypairgen.getD();\n      n_array=keypairgen.getN();\n\n      p_array=keypairgen.getP();\n      q_array=keypairgen.getQ();\n      ep_array=keypairgen.getEP();\n      eq_array=keypairgen.getEQ();\n      c_array=keypairgen.getC();\n\n      keypairgen=null;\n    }\n    catch(Exception e){\n      //System.err.println(\"KeyPairRSA: \"+e); \n      if(e instanceof Throwable)\n        throw new JSchException(e.toString(), (Throwable)e);\n      throw new JSchException(e.toString());\n    }\n  }\n\n  private static final byte[] begin=Util.str2byte(\"-----BEGIN RSA PRIVATE KEY-----\");\n  private static final byte[] end=Util.str2byte(\"-----END RSA PRIVATE KEY-----\");\n\n  byte[] getBegin(){ return begin; }\n  byte[] getEnd(){ return end; }\n\n  byte[] getPrivateKey(){\n    int content=\n      1+countLength(1) + 1 +                           // INTEGER\n      1+countLength(n_array.length) + n_array.length + // INTEGER  N\n      1+countLength(pub_array.length) + pub_array.length + // INTEGER  pub\n      1+countLength(prv_array.length) + prv_array.length+  // INTEGER  prv\n      1+countLength(p_array.length) + p_array.length+      // INTEGER  p\n      1+countLength(q_array.length) + q_array.length+      // INTEGER  q\n      1+countLength(ep_array.length) + ep_array.length+    // INTEGER  ep\n      1+countLength(eq_array.length) + eq_array.length+    // INTEGER  eq\n      1+countLength(c_array.length) + c_array.length;      // INTEGER  c\n\n    int total=\n      1+countLength(content)+content;   // SEQUENCE\n\n    byte[] plain=new byte[total];\n    int index=0;\n    index=writeSEQUENCE(plain, index, content);\n    index=writeINTEGER(plain, index, new byte[1]);  // 0\n    index=writeINTEGER(plain, index, n_array);\n    index=writeINTEGER(plain, index, pub_array);\n    index=writeINTEGER(plain, index, prv_array);\n    index=writeINTEGER(plain, index, p_array);\n    index=writeINTEGER(plain, index, q_array);\n    index=writeINTEGER(plain, index, ep_array);\n    index=writeINTEGER(plain, index, eq_array);\n    index=writeINTEGER(plain, index, c_array);\n    return plain;\n  }\n\n  boolean parse(byte [] plain){\n\n    try{\n      int index=0;\n      int length=0;\n\n      if(vendor==VENDOR_PUTTY){\n        Buffer buf = new Buffer(plain);\n        buf.skip(plain.length);\n\n        try {\n          byte[][] tmp = buf.getBytes(4, \"\");\n          prv_array = tmp[0];\n          p_array = tmp[1];\n          q_array = tmp[2];\n          c_array = tmp[3];\n        }\n        catch(JSchException e){\n          return false;\n        }\n\n        getEPArray();\n        getEQArray();\n\n        return true;\n      }\n\n      if(vendor==VENDOR_FSECURE){\n\tif(plain[index]!=0x30){                  // FSecure\n\t  Buffer buf=new Buffer(plain);\n\t  pub_array=buf.getMPIntBits();\n\t  prv_array=buf.getMPIntBits();\n\t  n_array=buf.getMPIntBits();\n\t  byte[] u_array=buf.getMPIntBits();\n\t  p_array=buf.getMPIntBits();\n\t  q_array=buf.getMPIntBits();\n          if(n_array!=null){\n            key_size = (new java.math.BigInteger(n_array)).bitLength();\n          }\n\n          getEPArray();\n          getEQArray();\n          getCArray();\n\n\t  return true;\n\t}\n\treturn false;\n      }\n\n      /*\n        Key must be in the following ASN.1 DER encoding,\n        RSAPrivateKey ::= SEQUENCE {\n          version           Version,\n          modulus           INTEGER,  -- n\n          publicExponent    INTEGER,  -- e\n          privateExponent   INTEGER,  -- d\n          prime1            INTEGER,  -- p\n          prime2            INTEGER,  -- q\n          exponent1         INTEGER,  -- d mod (p-1)\n          exponent2         INTEGER,  -- d mod (q-1)\n          coefficient       INTEGER,  -- (inverse of q) mod p\n          otherPrimeInfos   OtherPrimeInfos OPTIONAL\n        }\n      */\n\n      index++; // SEQUENCE\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n\n      if(plain[index]!=0x02)return false;\n      index++; // INTEGER\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      n_array=new byte[length];\n      System.arraycopy(plain, index, n_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      pub_array=new byte[length];\n      System.arraycopy(plain, index, pub_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      prv_array=new byte[length];\n      System.arraycopy(plain, index, prv_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      p_array=new byte[length];\n      System.arraycopy(plain, index, p_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      q_array=new byte[length];\n      System.arraycopy(plain, index, q_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      ep_array=new byte[length];\n      System.arraycopy(plain, index, ep_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      eq_array=new byte[length];\n      System.arraycopy(plain, index, eq_array, 0, length);\n      index+=length;\n\n      index++;\n      length=plain[index++]&0xff;\n      if((length&0x80)!=0){\n        int foo=length&0x7f; length=0;\n        while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }\n      }\n      c_array=new byte[length];\n      System.arraycopy(plain, index, c_array, 0, length);\n      index+=length;\n\n      if(n_array!=null){\n        key_size = (new java.math.BigInteger(n_array)).bitLength();\n      }\n\n    }\n    catch(Exception e){\n      //System.err.println(e);\n      return false;\n    }\n    return true;\n  }\n\n  public byte[] getPublicKeyBlob(){\n    byte[] foo=super.getPublicKeyBlob();\n    if(foo!=null) return foo;\n\n    if(pub_array==null) return null;\n    byte[][] tmp = new byte[3][];\n    tmp[0] = sshrsa;\n    tmp[1] = pub_array;\n    tmp[2] = n_array;\n    return Buffer.fromBytes(tmp).buffer;\n  }\n\n  private static final byte[] sshrsa=Util.str2byte(\"ssh-rsa\");\n  byte[] getKeyTypeName(){return sshrsa;}\n  public int getKeyType(){return RSA;}\n\n  public int getKeySize(){\n    return key_size;\n  }\n\n  @SuppressWarnings({\"static\"}) public byte[] getSignature(byte[] data){\n    try{      \n      Class c=Class.forName((String)jsch.getConfig(\"signature.rsa\"));\n      SignatureRSA rsa=(SignatureRSA)(c.newInstance());\n      rsa.init();\n      rsa.setPrvKey(prv_array, n_array);\n\n      rsa.update(data);\n      byte[] sig = rsa.sign();\n      byte[][] tmp = new byte[2][];\n      tmp[0] = sshrsa;\n      tmp[1] = sig;\n      return Buffer.fromBytes(tmp).buffer;\n    }\n    catch(Exception e){\n    }\n    return null;\n  }\n\n  @SuppressWarnings({\"static\"}) public Signature getVerifier(){\n    try{      \n      Class c=Class.forName((String)jsch.getConfig(\"signature.rsa\"));\n      SignatureRSA rsa=(SignatureRSA)(c.newInstance());\n      rsa.init();\n\n      if(pub_array == null && n_array == null && getPublicKeyBlob()!=null){\n        Buffer buf = new Buffer(getPublicKeyBlob());\n        buf.getString();\n        pub_array = buf.getString();\n        n_array = buf.getString();\n      } \n\n      rsa.setPubKey(pub_array, n_array);\n      return rsa;\n    }\n    catch(Exception e){\n    }\n    return null;\n  }\n\n  static KeyPair fromSSHAgent(JSch jsch, Buffer buf) throws JSchException {\n\n    byte[][] tmp = buf.getBytes(8, \"invalid key format\");\n\n    byte[] n_array = tmp[1];\n    byte[] pub_array = tmp[2];\n    byte[] prv_array = tmp[3];\n    KeyPairRSA kpair = new KeyPairRSA(jsch, n_array, pub_array, prv_array);\n    kpair.c_array = tmp[4];     // iqmp\n    kpair.p_array = tmp[5];\n    kpair.q_array = tmp[6];\n    kpair.publicKeyComment = new String(tmp[7]);\n    kpair.vendor=VENDOR_OPENSSH;\n    return kpair;\n  }\n\n  public byte[] forSSHAgent() throws JSchException {\n    if(isEncrypted()){\n      throw new JSchException(\"key is encrypted.\");\n    }\n    Buffer buf = new Buffer();\n    buf.putString(sshrsa);\n    buf.putString(n_array);\n    buf.putString(pub_array);\n    buf.putString(prv_array);\n    buf.putString(getCArray());\n    buf.putString(p_array);\n    buf.putString(q_array);\n    buf.putString(Util.str2byte(publicKeyComment));\n    byte[] result = new byte[buf.getLength()];\n    buf.getByte(result, 0, result.length);\n    return result;\n  }\n\n  private byte[] getEPArray(){\n    if(ep_array==null){\n      ep_array=(new BigInteger(prv_array)).mod(new BigInteger(p_array).subtract(BigInteger.ONE)).toByteArray();\n    }\n    return ep_array;\n  } \n\n  private byte[] getEQArray(){\n    if(eq_array==null){\n      eq_array=(new BigInteger(prv_array)).mod(new BigInteger(q_array).subtract(BigInteger.ONE)).toByteArray();\n    }\n    return eq_array;\n  } \n\n  private byte[] getCArray(){\n    if(c_array==null){\n      c_array=(new BigInteger(q_array)).modInverse(new BigInteger(p_array)).toByteArray();\n    }\n    return c_array;\n  } \n\n  public void dispose(){\n    super.dispose();\n    Util.bzero(prv_array);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/KnownHosts.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.*;\n\npublic\nclass KnownHosts implements HostKeyRepository{\n  private static final String _known_hosts=\"known_hosts\";\n\n  private JSch jsch=null;\n  private String known_hosts=null;\n  private java.util.Vector pool=null;\n\n  private MAC hmacsha1=null;\n\n  KnownHosts(JSch jsch){\n    super();\n    this.jsch=jsch;\n    pool=new java.util.Vector();\n  }\n\n  void setKnownHosts(String filename) throws JSchException{\n    try{\n      known_hosts = filename;\n      FileInputStream fis=new FileInputStream(Util.checkTilde(filename));\n      setKnownHosts(fis);\n    }\n    catch(FileNotFoundException e){\n      throw new JSchException(e.toString(), (Throwable)e);\n    } \n  }\n  void setKnownHosts(InputStream input) throws JSchException{\n    pool.removeAllElements();\n    StringBuffer sb=new StringBuffer();\n    byte i;\n    int j;\n    boolean error=false;\n    try{\n      InputStream fis=input;\n      String host;\n      String key=null;\n      int type;\n      byte[] buf=new byte[1024];\n      int bufl=0;\nloop:\n      while(true){\n\tbufl=0;\n        while(true){\n          j=fis.read();\n          if(j==-1){\n            if(bufl==0){ break loop; }\n            else{ break; }\n          }\n\t  if(j==0x0d){ continue; }\n\t  if(j==0x0a){ break; }\n          if(buf.length<=bufl){\n            if(bufl>1024*10) break;   // too long...\n            byte[] newbuf=new byte[buf.length*2];\n            System.arraycopy(buf, 0, newbuf, 0, buf.length);\n            buf=newbuf;\n          }\n          buf[bufl++]=(byte)j;\n\t}\n\n\tj=0;\n        while(j<bufl){\n          i=buf[j];\n\t  if(i==' '||i=='\\t'){ j++; continue; }\n\t  if(i=='#'){\n\t    addInvalidLine(Util.byte2str(buf, 0, bufl));\n\t    continue loop;\n\t  }\n\t  break;\n\t}\n\tif(j>=bufl){ \n\t  addInvalidLine(Util.byte2str(buf, 0, bufl));\n\t  continue loop; \n\t}\n\n        sb.setLength(0);\n        while(j<bufl){\n          i=buf[j++];\n          if(i==0x20 || i=='\\t'){ break; }\n          sb.append((char)i);\n\t}\n\thost=sb.toString();\n\tif(j>=bufl || host.length()==0){\n\t  addInvalidLine(Util.byte2str(buf, 0, bufl));\n\t  continue loop; \n\t}\n\n        while(j<bufl){\n          i=buf[j];\n\t  if(i==' '||i=='\\t'){ j++; continue; }\n          break;\n        }\n\n        String marker=\"\";\n        if(host.charAt(0) == '@'){\n          marker = host;\n\n          sb.setLength(0);\n          while(j<bufl){\n            i=buf[j++];\n            if(i==0x20 || i=='\\t'){ break; }\n            sb.append((char)i);\n          }\n          host=sb.toString();\n          if(j>=bufl || host.length()==0){\n            addInvalidLine(Util.byte2str(buf, 0, bufl));\n            continue loop; \n          }\n\n          while(j<bufl){\n            i=buf[j];\n            if(i==' '||i=='\\t'){ j++; continue; }\n            break;\n          }\n        }\n\n        sb.setLength(0);\n\ttype=-1;\n        while(j<bufl){\n          i=buf[j++];\n          if(i==0x20 || i=='\\t'){ break; }\n          sb.append((char)i);\n\t}\n\tString tmp = sb.toString();\n\tif(HostKey.name2type(tmp)!=HostKey.UNKNOWN){\n\t  type=HostKey.name2type(tmp);\n\t}\n\telse { j=bufl; }\n\tif(j>=bufl){\n\t  addInvalidLine(Util.byte2str(buf, 0, bufl));\n\t  continue loop; \n\t}\n\n        while(j<bufl){\n          i=buf[j];\n\t  if(i==' '||i=='\\t'){ j++; continue; }\n          break;\n        }\n\n        sb.setLength(0);\n        while(j<bufl){\n          i=buf[j++];\n          if(i==0x0d){ continue; }\n          if(i==0x0a){ break; }\n          if(i==0x20 || i=='\\t'){ break; }\n          sb.append((char)i);\n\t}\n\tkey=sb.toString();\n\tif(key.length()==0){\n\t  addInvalidLine(Util.byte2str(buf, 0, bufl));\n\t  continue loop; \n\t}\n\n        while(j<bufl){\n          i=buf[j];\n\t  if(i==' '||i=='\\t'){ j++; continue; }\n          break;\n        }\n\n        /**\n          \"man sshd\" has following descriptions,\n            Note that the lines in these files are typically hundreds\n            of characters long, and you definitely don't want to type\n            in the host keys by hand.  Rather, generate them by a script,\n            ssh-keyscan(1) or by taking /usr/local/etc/ssh_host_key.pub and\n            adding the host names at the front.\n          This means that a comment is allowed to appear at the end of each\n          key entry.\n        */\n        String comment=null;\n        if(j<bufl){\n          sb.setLength(0);\n          while(j<bufl){\n            i=buf[j++];\n            if(i==0x0d){ continue; }\n            if(i==0x0a){ break; }\n            sb.append((char)i);\n          }\n          comment=sb.toString();\n        }\n\n\t//System.err.println(host);\n\t//System.err.println(\"|\"+key+\"|\");\n\n\tHostKey hk = null;\n        hk = new HashedHostKey(marker, host, type, \n                               Util.fromBase64(Util.str2byte(key), 0, \n                                               key.length()), comment);\n\tpool.addElement(hk);\n      }\n      if(error){\n\tthrow new JSchException(\"KnownHosts: invalid format\");\n      }\n    }\n    catch(Exception e){\n      if(e instanceof JSchException)\n\tthrow (JSchException)e;         \n      if(e instanceof Throwable)\n        throw new JSchException(e.toString(), (Throwable)e);\n      throw new JSchException(e.toString());\n    }\n    finally {\n      try{ input.close(); }\n      catch(IOException e){\n        throw new JSchException(e.toString(), (Throwable)e);\n      }\n    }\n  }\n  private void addInvalidLine(String line) throws JSchException {\n    HostKey hk = new HostKey(line, HostKey.UNKNOWN, null);\n    pool.addElement(hk);\n  }\n  String getKnownHostsFile(){ return known_hosts; }\n  public String getKnownHostsRepositoryID(){ return known_hosts; }\n\n  public int check(String host, byte[] key){\n    int result=NOT_INCLUDED;\n    if(host==null){\n      return result;\n    }\n\n    HostKey hk = null;\n    try {\n      hk = new HostKey(host, HostKey.GUESS, key);\n    }\n    catch(JSchException e){  // unsupported key\n      return result;\n    }\n\n    synchronized(pool){\n      for(int i=0; i<pool.size(); i++){\n        HostKey _hk=(HostKey)(pool.elementAt(i));\n        if(_hk.isMatched(host) && _hk.type==hk.type){\n          if(Util.array_equals(_hk.key, key)){\n            return OK;\n          }\n          else{\n            result=CHANGED;\n\t  }\n        }\n      }\n    }\n\n    if(result==NOT_INCLUDED &&\n       host.startsWith(\"[\") &&\n       host.indexOf(\"]:\")>1\n       ){\n      return check(host.substring(1, host.indexOf(\"]:\")), key);\n    }\n\n    return result;\n  }\n\n  public void add(HostKey hostkey, UserInfo userinfo){\n    int type=hostkey.type;\n    String host=hostkey.getHost();\n    byte[] key=hostkey.key;\n\n    HostKey hk=null;\n    synchronized(pool){\n      for(int i=0; i<pool.size(); i++){\n        hk=(HostKey)(pool.elementAt(i));\n        if(hk.isMatched(host) && hk.type==type){\n/*\n\t  if(Util.array_equals(hk.key, key)){ return; }\n\t  if(hk.host.equals(host)){\n\t    hk.key=key;\n\t    return;\n\t  }\n\t  else{\n\t    hk.host=deleteSubString(hk.host, host);\n\t    break;\n\t  }\n*/\n        }\n      }\n    }\n\n    hk=hostkey;\n\n    pool.addElement(hk);\n\n    String bar=getKnownHostsRepositoryID();\n    if(bar!=null){\n      boolean foo=true;\n      File goo=new File(Util.checkTilde(bar));\n      if(!goo.exists()){\n        foo=false;\n        if(userinfo!=null){\n          foo=userinfo.promptYesNo(bar+\" does not exist.\\n\"+\n                                   \"Are you sure you want to create it?\"\n                                   );\n          goo=goo.getParentFile();\n          if(foo && goo!=null && !goo.exists()){\n            foo=userinfo.promptYesNo(\"The parent directory \"+goo+\" does not exist.\\n\"+\n                                     \"Are you sure you want to create it?\"\n                                     );\n            if(foo){\n              if(!goo.mkdirs()){\n                userinfo.showMessage(goo+\" has not been created.\");\n                foo=false;\n              }\n              else{\n                userinfo.showMessage(goo+\" has been succesfully created.\\nPlease check its access permission.\");\n              }\n            }\n          }\n          if(goo==null)foo=false;\n        }\n      }\n      if(foo){\n        try{ \n          sync(bar); \n        }\n        catch(Exception e){ System.err.println(\"sync known_hosts: \"+e); }\n      }\n    }\n  }\n\n  public HostKey[] getHostKey(){\n    return getHostKey(null, (String)null);\n  }\n  public HostKey[] getHostKey(String host, String type){\n    synchronized(pool){\n      java.util.ArrayList v = new java.util.ArrayList();\n      for(int i=0; i<pool.size(); i++){\n\tHostKey hk=(HostKey)pool.elementAt(i);\n\tif(hk.type==HostKey.UNKNOWN) continue;\n\tif(host==null || \n\t   (hk.isMatched(host) && \n\t    (type==null || hk.getType().equals(type)))){\n          v.add(hk);\n\t}\n      }\n      HostKey[] foo = new HostKey[v.size()];\n      for(int i=0; i<v.size(); i++){\n        foo[i] = (HostKey)v.get(i);\n      }\n      if(host != null && host.startsWith(\"[\") && host.indexOf(\"]:\")>1){\n        HostKey[] tmp =\n          getHostKey(host.substring(1, host.indexOf(\"]:\")), type);\n        if(tmp.length > 0){\n          HostKey[] bar = new HostKey[foo.length + tmp.length];\n          System.arraycopy(foo, 0, bar, 0, foo.length);\n          System.arraycopy(tmp, 0, bar, foo.length, tmp.length);\n          foo = bar;\n        }\n      }\n      return foo;\n    }\n  }\n  public void remove(String host, String type){\n    remove(host, type, null);\n  }\n  public void remove(String host, String type, byte[] key){\n    boolean sync=false;\n    synchronized(pool){\n    for(int i=0; i<pool.size(); i++){\n      HostKey hk=(HostKey)(pool.elementAt(i));\n      if(host==null ||\n\t (hk.isMatched(host) && \n\t  (type==null || (hk.getType().equals(type) &&\n\t\t\t  (key==null || Util.array_equals(key, hk.key)))))){\n        String hosts=hk.getHost();\n        if(hosts.equals(host) || \n           ((hk instanceof HashedHostKey) &&\n            ((HashedHostKey)hk).isHashed())){\n          pool.removeElement(hk);\n        }\n        else{\n          hk.host=deleteSubString(hosts, host);\n        }\n\tsync=true;\n      }\n    }\n    }\n    if(sync){\n      try{sync();}catch(Exception e){};\n    }\n  }\n\n  protected void sync() throws IOException { \n    if(known_hosts!=null)\n      sync(known_hosts); \n  }\n  protected synchronized void sync(String foo) throws IOException {\n    if(foo==null) return;\n    FileOutputStream fos=new FileOutputStream(Util.checkTilde(foo));\n    dump(fos);\n    fos.close();\n  }\n\n  private static final byte[] space={(byte)0x20};\n  private static final byte[] cr=Util.str2byte(\"\\n\");\n  void dump(OutputStream out) throws IOException {\n    try{\n      HostKey hk;\n      synchronized(pool){\n      for(int i=0; i<pool.size(); i++){\n        hk=(HostKey)(pool.elementAt(i));\n        //hk.dump(out);\n\tString marker=hk.getMarker();\n\tString host=hk.getHost();\n\tString type=hk.getType();\n        String comment = hk.getComment();\n\tif(type.equals(\"UNKNOWN\")){\n\t  out.write(Util.str2byte(host));\n\t  out.write(cr);\n\t  continue;\n\t}\n        if(marker.length()!=0){\n          out.write(Util.str2byte(marker));\n          out.write(space);\n        }\n\tout.write(Util.str2byte(host));\n\tout.write(space);\n\tout.write(Util.str2byte(type));\n\tout.write(space);\n\tout.write(Util.str2byte(hk.getKey()));\n        if(comment!=null){\n          out.write(space);\n          out.write(Util.str2byte(comment));\n        }\n\tout.write(cr);\n      }\n      }\n    }\n    catch(Exception e){\n      System.err.println(e);\n    }\n  }\n\n  private String deleteSubString(String hosts, String host){\n    int i=0;\n    int hostlen=host.length();\n    int hostslen=hosts.length();\n    int j;\n    while(i<hostslen){\n      j=hosts.indexOf(',', i);\n      if(j==-1) break;\n      if(!host.equals(hosts.substring(i, j))){\n        i=j+1;\t  \n        continue;\n      }\n      return hosts.substring(0, i)+hosts.substring(j+1);\n    }\n    if(hosts.endsWith(host) && hostslen-i==hostlen){\n      return hosts.substring(0, (hostlen==hostslen) ? 0 :hostslen-hostlen-1);\n    }\n    return hosts;\n  }\n\n  @SuppressWarnings({\"static\"}) private synchronized MAC getHMACSHA1(){\n    if(hmacsha1==null){\n      try{\n        Class c=Class.forName(jsch.getConfig(\"hmac-sha1\"));\n        hmacsha1=(MAC)(c.newInstance());\n      }\n      catch(Exception e){ \n        System.err.println(\"hmacsha1: \"+e); \n      }\n    }\n    return hmacsha1;\n  }\n\n  HostKey createHashedHostKey(String host, byte[]key) throws JSchException {\n    HashedHostKey hhk=new HashedHostKey(host, key);\n    hhk.hash();\n    return hhk;\n  } \n  class HashedHostKey extends HostKey{\n    private static final String HASH_MAGIC=\"|1|\";\n    private static final String HASH_DELIM=\"|\";\n\n    private boolean hashed=false;\n    byte[] salt=null;\n    byte[] hash=null;\n\n    HashedHostKey(String host, byte[] key) throws JSchException {\n      this(host, GUESS, key);\n    }\n    HashedHostKey(String host, int type, byte[] key) throws JSchException {\n      this(\"\", host, type, key, null);\n    }\n    HashedHostKey(String marker, String host, int type, byte[] key, String comment) throws JSchException {\n      super(marker, host, type, key, comment);\n      if(this.host.startsWith(HASH_MAGIC) &&\n         this.host.substring(HASH_MAGIC.length()).indexOf(HASH_DELIM)>0){\n        String data=this.host.substring(HASH_MAGIC.length());\n        String _salt=data.substring(0, data.indexOf(HASH_DELIM));\n        String _hash=data.substring(data.indexOf(HASH_DELIM)+1);\n        salt=Util.fromBase64(Util.str2byte(_salt), 0, _salt.length());\n        hash=Util.fromBase64(Util.str2byte(_hash), 0, _hash.length());\n        if(salt.length!=20 ||  // block size of hmac-sha1\n           hash.length!=20){\n          salt=null;\n          hash=null;\n          return;\n        }\n        hashed=true;\n      }\n    }\n\n    boolean isMatched(String _host){\n      if(!hashed){\n        return super.isMatched(_host);\n      }\n      MAC macsha1=getHMACSHA1();\n      try{\n        synchronized(macsha1){\n          macsha1.init(salt);\n          byte[] foo=Util.str2byte(_host);\n          macsha1.update(foo, 0, foo.length);\n          byte[] bar=new byte[macsha1.getBlockSize()];\n          macsha1.doFinal(bar, 0);\n          return Util.array_equals(hash, bar);\n        }\n      }\n      catch(Exception e){\n        System.out.println(e);\n      }\n      return false;\n    }\n\n    boolean isHashed(){\n      return hashed;\n    }\n\n    void hash(){\n      if(hashed)\n        return;\n      MAC macsha1=getHMACSHA1();\n      if(salt==null){\n        Random random=Session.random;\n        synchronized(random){\n          salt=new byte[macsha1.getBlockSize()];\n          random.fill(salt, 0, salt.length);\n        }\n      }\n      try{\n        synchronized(macsha1){\n          macsha1.init(salt);\n          byte[] foo=Util.str2byte(host);\n          macsha1.update(foo, 0, foo.length);\n          hash=new byte[macsha1.getBlockSize()];\n          macsha1.doFinal(hash, 0);\n        }\n      }\n      catch(Exception e){\n      }\n      host=HASH_MAGIC+Util.byte2str(Util.toBase64(salt, 0, salt.length))+\n        HASH_DELIM+Util.byte2str(Util.toBase64(hash, 0, hash.length));\n      hashed=true;\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/LICENSE.txt",
    "content": "JSch 0.0.* was released under the GNU LGPL license.  Later, we have switched \nover to a BSD-style license. \n\n------------------------------------------------------------------------------\nCopyright (c) 2002-2015 Atsuhiko Yamanaka, JCraft,Inc. \nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "java/com/jcraft/jsch/LocalIdentityRepository.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2012-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.util.Vector;\n\nclass LocalIdentityRepository implements IdentityRepository {\n  private static final String name = \"Local Identity Repository\";\n\n  private Vector identities = new Vector();\n  private JSch jsch;\n\n  LocalIdentityRepository(JSch jsch){\n    this.jsch = jsch;\n  }\n\n  public String getName(){\n    return name;\n  }\n\n  public int getStatus(){\n    return RUNNING;\n  }\n\n  public synchronized Vector getIdentities() {\n    removeDupulicates();\n    Vector v = new Vector();\n    for(int i=0; i<identities.size(); i++){\n      v.addElement(identities.elementAt(i));\n    }\n    return v;\n  }\n\n  public synchronized void add(Identity identity) {\n    if(!identities.contains(identity)) {\n      byte[] blob1 = identity.getPublicKeyBlob();\n      if(blob1 == null) {\n        identities.addElement(identity);\n        return;\n      }\n      for(int i = 0; i<identities.size(); i++){\n        byte[] blob2 = ((Identity)identities.elementAt(i)).getPublicKeyBlob();\n        if(blob2 != null && Util.array_equals(blob1, blob2)){\n          if(!identity.isEncrypted() && \n             ((Identity)identities.elementAt(i)).isEncrypted()){\n            remove(blob2);\n          }\n          else {  \n            return;\n          }\n        }\n      }\n      identities.addElement(identity);\n    }\n  }\n\n  public synchronized boolean add(byte[] identity) {\n    try{\n      Identity _identity =\n        IdentityFile.newInstance(\"from remote:\", identity, null, jsch);\n      add(_identity);\n      return true;\n    }\n    catch(JSchException e){\n      return false;\n    }\n  }\n\n  synchronized void remove(Identity identity) {\n    if(identities.contains(identity)) {\n      identities.removeElement(identity);\n      identity.clear();\n    }\n    else {\n      remove(identity.getPublicKeyBlob());\n    }\n  }\n\n  public synchronized boolean remove(byte[] blob) {\n    if(blob == null) return false;\n    for(int i=0; i<identities.size(); i++) {\n      Identity _identity = (Identity)(identities.elementAt(i));\n      byte[] _blob = _identity.getPublicKeyBlob();\n      if(_blob == null || !Util.array_equals(blob, _blob))\n        continue;\n      identities.removeElement(_identity);\n      _identity.clear();\n      return true;\n    }\n    return false;\n  }\n\n  public synchronized void removeAll() {\n    for(int i=0; i<identities.size(); i++) {\n      Identity identity=(Identity)(identities.elementAt(i));\n      identity.clear();\n    }\n    identities.removeAllElements();\n  } \n\n  private void removeDupulicates(){\n    Vector v = new Vector();\n    int len = identities.size();\n    if(len == 0) return;\n    for(int i=0; i<len; i++){\n      Identity foo = (Identity)identities.elementAt(i);\n      byte[] foo_blob = foo.getPublicKeyBlob();\n      if(foo_blob == null) continue;\n      for(int j=i+1; j<len; j++){\n        Identity bar = (Identity)identities.elementAt(j);\n        byte[] bar_blob = bar.getPublicKeyBlob();\n        if(bar_blob == null) continue;\n        if(Util.array_equals(foo_blob, bar_blob) &&\n           foo.isEncrypted() == bar.isEncrypted()){\n          v.addElement(foo_blob);\n          break;\n        }\n      }\n    }\n    for(int i=0; i<v.size(); i++){\n      remove((byte[])v.elementAt(i));\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/Logger.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface Logger{\n\n  public final int DEBUG=0;\n  public final int INFO=1;\n  public final int WARN=2;\n  public final int ERROR=3;\n  public final int FATAL=4;\n\n  public boolean isEnabled(int level);\n\n  public void log(int level, String message);\n\n  /*\n  public final Logger SIMPLE_LOGGER=new Logger(){\n      public boolean isEnabled(int level){return true;}\n      public void log(int level, String message){System.err.println(message);}\n    };\n  final Logger DEVNULL=new Logger(){\n      public boolean isEnabled(int level){return false;}\n      public void log(int level, String message){}\n    };\n  */\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/MAC.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface MAC{\n  String getName();\n  int getBlockSize(); \n  void init(byte[] key) throws Exception; \n  void update(byte[] foo, int start, int len);\n  void update(int foo);\n  void doFinal(byte[] buf, int offset);\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/OpenSSHConfig.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2013-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.io.StringReader;\nimport java.io.FileReader;\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.util.Hashtable;\nimport java.util.Vector;\n\n/**\n * This class implements ConfigRepository interface, and parses\n * OpenSSH's configuration file.  The following keywords will be recognized,\n * <ul>\n *   <li>Host</li>\n *   <li>User</li>\n *   <li>Hostname</li>\n *   <li>Port</li>\n *   <li>PreferredAuthentications</li>\n *   <li>IdentityFile</li>\n *   <li>NumberOfPasswordPrompts</li>\n *   <li>ConnectTimeout</li>\n *   <li>HostKeyAlias</li>\n *   <li>UserKnownHostsFile</li>\n *   <li>KexAlgorithms</li>\n *   <li>HostKeyAlgorithms</li>\n *   <li>Ciphers</li>\n *   <li>Macs</li>\n *   <li>Compression</li>\n *   <li>CompressionLevel</li>\n *   <li>ForwardAgent</li>\n *   <li>RequestTTY</li>\n *   <li>ServerAliveInterval</li>  \n *   <li>LocalForward</li>\n *   <li>RemoteForward</li>\n *   <li>ClearAllForwardings</li>\n * </ul>\n *\n * @see ConfigRepository\n */\npublic class OpenSSHConfig implements ConfigRepository {\n\n  /**\n   * Parses the given string, and returns an instance of ConfigRepository.\n   *\n   * @param conf string, which includes OpenSSH's config\n   * @return an instanceof OpenSSHConfig\n   */\n  public static OpenSSHConfig parse(String conf) throws IOException {\n    Reader r = new StringReader(conf);\n    try {\n      return new OpenSSHConfig(r);\n    }\n    finally {\n      r.close();\n    }\n  }\n\n  /**\n   * Parses the given file, and returns an instance of ConfigRepository.\n   *\n   * @param file OpenSSH's config file\n   * @return an instanceof OpenSSHConfig\n   */\n  public static OpenSSHConfig parseFile(String file) throws IOException {\n    Reader r = new FileReader(Util.checkTilde(file));\n    try {\n      return new OpenSSHConfig(r);\n    }\n    finally {\n      r.close();\n    }\n  }\n\n  OpenSSHConfig(Reader r) throws IOException {\n    _parse(r);\n  }\n\n  private final Hashtable config = new Hashtable();\n  private final Vector hosts = new Vector();\n\n  private void _parse(Reader r) throws IOException {\n    BufferedReader br = new BufferedReader(r);\n\n    String host = \"\";\n    Vector/*<String[]>*/ kv = new Vector();\n    String l = null;\n\n    while((l = br.readLine()) != null){\n      l = l.trim();\n      if(l.length() == 0 || l.startsWith(\"#\"))\n        continue;\n\n      String[] key_value = l.split(\"[= \\t]\", 2);\n      for(int i = 0; i < key_value.length; i++)\n        key_value[i] = key_value[i].trim();\n\n      if(key_value.length <= 1)\n        continue;\n\n      if(key_value[0].equals(\"Host\")){\n        config.put(host, kv);\n        hosts.addElement(host);\n        host = key_value[1];\n        kv = new Vector();\n      }\n      else {\n        kv.addElement(key_value);\n      }\n    }\n    config.put(host, kv);\n    hosts.addElement(host);\n  }\n\n  public Config getConfig(String host) {\n    return new MyConfig(host);\n  }\n\n  private static final Hashtable keymap = new Hashtable();\n  static {\n    keymap.put(\"kex\", \"KexAlgorithms\");\n    keymap.put(\"server_host_key\", \"HostKeyAlgorithms\");\n    keymap.put(\"cipher.c2s\", \"Ciphers\");\n    keymap.put(\"cipher.s2c\", \"Ciphers\");\n    keymap.put(\"mac.c2s\", \"Macs\");\n    keymap.put(\"mac.s2c\", \"Macs\");\n    keymap.put(\"compression.s2c\", \"Compression\");\n    keymap.put(\"compression.c2s\", \"Compression\");\n    keymap.put(\"compression_level\", \"CompressionLevel\");\n    keymap.put(\"MaxAuthTries\", \"NumberOfPasswordPrompts\");\n  }\n\n  class MyConfig implements Config {\n\n    private String host;\n    private Vector _configs = new Vector();\n\n    MyConfig(String host){\n      this.host = host;\n\n      _configs.addElement(config.get(\"\"));\n\n      byte[] _host = Util.str2byte(host);\n      if(hosts.size() > 1){\n        for(int i = 1; i < hosts.size(); i++){\n          String patterns[] = ((String)hosts.elementAt(i)).split(\"[ \\t]\");\n          for(int j = 0; j < patterns.length; j++){\n            boolean negate = false;\n            String foo = patterns[j].trim();\n            if(foo.startsWith(\"!\")){\n              negate = true;\n              foo = foo.substring(1).trim();\n            }\n            if(Util.glob(Util.str2byte(foo), _host)){\n              if(!negate){\n                _configs.addElement(config.get((String)hosts.elementAt(i)));\n              }\n            }\n            else if(negate){\n              _configs.addElement(config.get((String)hosts.elementAt(i)));\n            }\n          }\n        }\n      }\n    }\n\n    private String find(String key) {\n      if(keymap.get(key)!=null) {\n        key = (String)keymap.get(key);\n      }\n      key = key.toUpperCase();\n      String value = null;\n      for(int i = 0; i < _configs.size(); i++) {\n        Vector v = (Vector)_configs.elementAt(i);\n        for(int j = 0; j < v.size(); j++) {\n          String[] kv = (String[])v.elementAt(j);\n          if(kv[0].toUpperCase().equals(key)) {\n            value = kv[1];\n            break;\n          }\n        }\n        if(value != null)\n          break;\n      }\n      return value;\n    }\n\n    private String[] multiFind(String key) {\n      key = key.toUpperCase();\n      Vector value = new Vector();\n      for(int i = 0; i < _configs.size(); i++) {\n        Vector v = (Vector)_configs.elementAt(i);\n        for(int j = 0; j < v.size(); j++) {\n          String[] kv = (String[])v.elementAt(j);\n          if(kv[0].toUpperCase().equals(key)) {\n            String foo = kv[1];\n            if(foo != null) {\n              value.remove(foo);\n              value.addElement(foo);\n            }\n          }\n        }\n      }\n      String[] result = new String[value.size()]; \n      value.toArray(result);\n      return result;\n    }\n\n    public String getHostname(){ return find(\"Hostname\"); }\n    public String getUser(){ return find(\"User\"); }\n    public int getPort(){\n      String foo = find(\"Port\");\n      int port = -1;\n      try {\n        port = Integer.parseInt(foo);\n      }\n      catch(NumberFormatException e){\n        // wrong format\n      }\n      return port;\n    }\n    public String getValue(String key){\n      if(key.equals(\"compression.s2c\") ||\n         key.equals(\"compression.c2s\")) {\n        String foo = find(key);\n        if(foo == null || foo.equals(\"no\"))\n          return \"none,zlib@openssh.com,zlib\";\n        return \"zlib@openssh.com,zlib,none\";\n      }\n      return find(key);\n    }\n    public String[] getValues(String key){ return multiFind(key); }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/PBKDF.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2013-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface PBKDF {\n  byte[] getKey(byte[] pass, byte[] salt, int iteration, int size);\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/Packet.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class Packet{\n\n  private static Random random=null;\n  static void setRandom(Random foo){ random=foo;}\n\n  Buffer buffer;\n  byte[] ba4=new byte[4]; \n  public Packet(Buffer buffer){\n    this.buffer=buffer;\n  }\n  public void reset(){\n    buffer.index=5;\n  }\n  void padding(int bsize){\n    int len=buffer.index;\n    int pad=(-len)&(bsize-1);\n    if(pad<bsize){\n      pad+=bsize;\n    }\n    len=len+pad-4;\n    ba4[0]=(byte)(len>>>24);\n    ba4[1]=(byte)(len>>>16);\n    ba4[2]=(byte)(len>>>8);\n    ba4[3]=(byte)(len);\n    System.arraycopy(ba4, 0, buffer.buffer, 0, 4);\n    buffer.buffer[4]=(byte)pad;\n    synchronized(random){\n      random.fill(buffer.buffer, buffer.index, pad);\n    }\n    buffer.skip(pad);\n    //buffer.putPad(pad);\n/*\nfor(int i=0; i<buffer.index; i++){\nSystem.err.print(Integer.toHexString(buffer.buffer[i]&0xff)+\":\");\n}\nSystem.err.println(\"\");\n*/\n  }\n\n  int shift(int len, int bsize, int mac){\n    int s=len+5+9;\n    int pad=(-s)&(bsize-1);\n    if(pad<bsize)pad+=bsize;\n    s+=pad;\n    s+=mac;\n    s+=32; // margin for deflater; deflater may inflate data\n\n    /**/\n    if(buffer.buffer.length<s+buffer.index-5-9-len){\n      byte[] foo=new byte[s+buffer.index-5-9-len];\n      System.arraycopy(buffer.buffer, 0, foo, 0, buffer.buffer.length);\n      buffer.buffer=foo;\n    }\n    /**/\n\n//if(buffer.buffer.length<len+5+9)\n//  System.err.println(\"buffer.buffer.length=\"+buffer.buffer.length+\" len+5+9=\"+(len+5+9));\n\n//if(buffer.buffer.length<s)\n//  System.err.println(\"buffer.buffer.length=\"+buffer.buffer.length+\" s=\"+(s));\n\n    System.arraycopy(buffer.buffer, \n\t\t     len+5+9, \n\t\t     buffer.buffer, s, buffer.index-5-9-len);\n\n    buffer.index=10;\n    buffer.putInt(len);\n    buffer.index=len+5+9;\n    return s;\n  }\n  void unshift(byte command, int recipient, int s, int len){\n    System.arraycopy(buffer.buffer, \n\t\t     s, \n\t\t     buffer.buffer, 5+9, len);\n    buffer.buffer[5]=command;\n    buffer.index=6;\n    buffer.putInt(recipient);\n    buffer.putInt(len);\n    buffer.index=len+5+9;\n  }\n  Buffer getBuffer(){\n    return buffer;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/PortWatcher.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.net.*;\nimport java.io.*;\n\nclass PortWatcher implements Runnable{\n  private static java.util.Vector pool=new java.util.Vector();\n  private static InetAddress anyLocalAddress=null;\n  static{\n    // 0.0.0.0\n/*\n    try{ anyLocalAddress=InetAddress.getByAddress(new byte[4]); }\n    catch(UnknownHostException e){\n    }\n*/\n    try{ anyLocalAddress=InetAddress.getByName(\"0.0.0.0\"); }\n    catch(UnknownHostException e){\n    }\n  }\n\n  Session session;\n  int lport;\n  int rport;\n  String host;\n  InetAddress boundaddress;\n  Runnable thread;\n  ServerSocket ss;\n  int connectTimeout=0;\n\n  static String[] getPortForwarding(Session session){\n    java.util.Vector foo=new java.util.Vector();\n    synchronized(pool){\n      for(int i=0; i<pool.size(); i++){\n\tPortWatcher p=(PortWatcher)(pool.elementAt(i));\n\tif(p.session==session){\n\t  foo.addElement(p.lport+\":\"+p.host+\":\"+p.rport);\n\t}\n      }\n    }\n    String[] bar=new String[foo.size()];\n    for(int i=0; i<foo.size(); i++){\n      bar[i]=(String)(foo.elementAt(i));\n    }\n    return bar;\n  }\n  static PortWatcher getPort(Session session, String address, int lport) throws JSchException{\n    InetAddress addr;\n    try{\n      addr=InetAddress.getByName(address);\n    }\n    catch(UnknownHostException uhe){\n      throw new JSchException(\"PortForwardingL: invalid address \"+address+\" specified.\", uhe);\n    }\n    synchronized(pool){\n      for(int i=0; i<pool.size(); i++){\n\tPortWatcher p=(PortWatcher)(pool.elementAt(i));\n\tif(p.session==session && p.lport==lport){\n\t  if(/*p.boundaddress.isAnyLocalAddress() ||*/\n             (anyLocalAddress!=null &&  p.boundaddress.equals(anyLocalAddress)) ||\n\t     p.boundaddress.equals(addr))\n\t  return p;\n\t}\n      }\n      return null;\n    }\n  }\n  private static String normalize(String address){\n    if(address!=null){\n      if(address.length()==0 || address.equals(\"*\"))\n        address=\"0.0.0.0\";\n      else if(address.equals(\"localhost\"))\n        address=\"127.0.0.1\";\n    }\n    return address;\n  }\n  static PortWatcher addPort(Session session, String address, int lport, String host, int rport, ServerSocketFactory ssf) throws JSchException{\n    address = normalize(address);\n    if(getPort(session, address, lport)!=null){\n      throw new JSchException(\"PortForwardingL: local port \"+ address+\":\"+lport+\" is already registered.\");\n    }\n    PortWatcher pw=new PortWatcher(session, address, lport, host, rport, ssf);\n    pool.addElement(pw);\n    return pw;\n  }\n  static void delPort(Session session, String address, int lport) throws JSchException{\n    address = normalize(address);\n    PortWatcher pw=getPort(session, address, lport);\n    if(pw==null){\n      throw new JSchException(\"PortForwardingL: local port \"+address+\":\"+lport+\" is not registered.\");\n    }\n    pw.delete();\n    pool.removeElement(pw);\n  }\n  static void delPort(Session session){\n    synchronized(pool){\n      PortWatcher[] foo=new PortWatcher[pool.size()];\n      int count=0;\n      for(int i=0; i<pool.size(); i++){\n\tPortWatcher p=(PortWatcher)(pool.elementAt(i));\n\tif(p.session==session) {\n\t  p.delete();\n\t  foo[count++]=p;\n\t}\n      }\n      for(int i=0; i<count; i++){\n\tPortWatcher p=foo[i];\n\tpool.removeElement(p);\n      }\n    }\n  }\n  PortWatcher(Session session, \n\t      String address, int lport, \n\t      String host, int rport,\n              ServerSocketFactory factory) throws JSchException{\n    this.session=session;\n    this.lport=lport;\n    this.host=host;\n    this.rport=rport;\n    try{\n      boundaddress=InetAddress.getByName(address);\n      ss=(factory==null) ? \n        new ServerSocket(lport, 0, boundaddress) :\n        factory.createServerSocket(lport, 0, boundaddress);\n    }\n    catch(Exception e){ \n      //System.err.println(e);\n      String message=\"PortForwardingL: local port \"+address+\":\"+lport+\" cannot be bound.\";\n      if(e instanceof Throwable)\n        throw new JSchException(message, (Throwable)e);\n      throw new JSchException(message);\n    }\n    if(lport==0){\n      int assigned=ss.getLocalPort();\n      if(assigned!=-1)\n        this.lport=assigned;\n    }\n  }\n\n  public void run(){\n    thread=this;\n    try{\n      while(thread!=null){\n        Socket socket=ss.accept();\n\tsocket.setTcpNoDelay(true);\n        InputStream in=socket.getInputStream();\n        OutputStream out=socket.getOutputStream();\n        ChannelDirectTCPIP channel=new ChannelDirectTCPIP();\n        channel.init();\n        channel.setInputStream(in);\n        channel.setOutputStream(out);\n\tsession.addChannel(channel);\n\t((ChannelDirectTCPIP)channel).setHost(host);\n\t((ChannelDirectTCPIP)channel).setPort(rport);\n\t((ChannelDirectTCPIP)channel).setOrgIPAddress(socket.getInetAddress().getHostAddress());\n\t((ChannelDirectTCPIP)channel).setOrgPort(socket.getPort());\n        channel.connect(connectTimeout);\n\tif(channel.exitstatus!=-1){\n\t}\n      }\n    }\n    catch(Exception e){\n      //System.err.println(\"! \"+e);\n    }\n    delete();\n  }\n\n  void delete(){\n    thread=null;\n    try{ \n      if(ss!=null)ss.close();\n      ss=null;\n    }\n    catch(Exception e){\n    }\n  }\n\n  void setConnectTimeout(int connectTimeout){\n    this.connectTimeout=connectTimeout;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/Proxy.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.*;\nimport java.net.Socket;\npublic interface Proxy{\n  void connect(SocketFactory socket_factory, String host, int port, int timeout) throws Exception;\n  InputStream getInputStream();\n  OutputStream getOutputStream();\n  Socket getSocket();\n  void close();\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ProxyHTTP.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.*;\nimport java.net.*;\n\npublic class ProxyHTTP implements Proxy{\n  private static int DEFAULTPORT=80;\n  private String proxy_host;\n  private int proxy_port;\n  private InputStream in;\n  private OutputStream out;\n  private Socket socket;\n\n  private String user;\n  private String passwd;\n\n  public ProxyHTTP(String proxy_host){\n    int port=DEFAULTPORT;\n    String host=proxy_host;\n    if(proxy_host.indexOf(':')!=-1){\n      try{\n\thost=proxy_host.substring(0, proxy_host.indexOf(':'));\n\tport=Integer.parseInt(proxy_host.substring(proxy_host.indexOf(':')+1));\n      }\n      catch(Exception e){\n      }\n    }\n    this.proxy_host=host;\n    this.proxy_port=port;\n  }\n  public ProxyHTTP(String proxy_host, int proxy_port){\n    this.proxy_host=proxy_host;\n    this.proxy_port=proxy_port;\n  }\n  public void setUserPasswd(String user, String passwd){\n    this.user=user;\n    this.passwd=passwd;\n  }\n  public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws JSchException{\n    try{\n      if(socket_factory==null){\n        socket=Util.createSocket(proxy_host, proxy_port, timeout);    \n        in=socket.getInputStream();\n        out=socket.getOutputStream();\n      }\n      else{\n        socket=socket_factory.createSocket(proxy_host, proxy_port);\n        in=socket_factory.getInputStream(socket);\n        out=socket_factory.getOutputStream(socket);\n      }\n      if(timeout>0){\n        socket.setSoTimeout(timeout);\n      }\n      socket.setTcpNoDelay(true);\n\n      out.write(Util.str2byte(\"CONNECT \"+host+\":\"+port+\" HTTP/1.0\\r\\n\"));\n\n      if(user!=null && passwd!=null){\n\tbyte[] code=Util.str2byte(user+\":\"+passwd);\n\tcode=Util.toBase64(code, 0, code.length);\n\tout.write(Util.str2byte(\"Proxy-Authorization: Basic \"));\n\tout.write(code);\n\tout.write(Util.str2byte(\"\\r\\n\"));\n      }\n\n      out.write(Util.str2byte(\"\\r\\n\"));\n      out.flush();\n\n      int foo=0;\n\n      StringBuffer sb=new StringBuffer();\n      while(foo>=0){\n        foo=in.read(); if(foo!=13){sb.append((char)foo);  continue;}\n        foo=in.read(); if(foo!=10){continue;}\n        break;\n      }\n      if(foo<0){\n        throw new IOException();\n      }\n\n      String response=sb.toString(); \n      String reason=\"Unknow reason\";\n      int code=-1;\n      try{\n        foo=response.indexOf(' ');\n        int bar=response.indexOf(' ', foo+1);\n        code=Integer.parseInt(response.substring(foo+1, bar));\n        reason=response.substring(bar+1);\n      }\n      catch(Exception e){\n      }\n      if(code!=200){\n        throw new IOException(\"proxy error: \"+reason);\n      }\n\n      /*\n      while(foo>=0){\n        foo=in.read(); if(foo!=13) continue;\n        foo=in.read(); if(foo!=10) continue;\n        foo=in.read(); if(foo!=13) continue;      \n        foo=in.read(); if(foo!=10) continue;\n        break;\n      }\n      */\n\n      int count=0;\n      while(true){\n        count=0;\n        while(foo>=0){\n          foo=in.read(); if(foo!=13){count++;  continue;}\n          foo=in.read(); if(foo!=10){continue;}\n          break;\n        }\n        if(foo<0){\n          throw new IOException();\n        }\n        if(count==0)break;\n      }\n    }\n    catch(RuntimeException e){\n      throw e;\n    }\n    catch(Exception e){\n      try{ if(socket!=null)socket.close(); }\n      catch(Exception eee){\n      }\n      String message=\"ProxyHTTP: \"+e.toString();\n      if(e instanceof Throwable)\n        throw new JSchException(message, (Throwable)e);\n      throw new JSchException(message);\n    }\n  }\n  public InputStream getInputStream(){ return in; }\n  public OutputStream getOutputStream(){ return out; }\n  public Socket getSocket(){ return socket; }\n  public void close(){\n    try{\n      if(in!=null)in.close();\n      if(out!=null)out.close();\n      if(socket!=null)socket.close();\n    }\n    catch(Exception e){\n    }\n    in=null;\n    out=null;\n    socket=null;\n  }\n  public static int getDefaultPort(){\n    return DEFAULTPORT;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ProxySOCKS4.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n/*\n This file depends on following documents,\n   - SOCKS: A protocol for TCP proxy across firewalls, Ying-Da Lee\n     http://www.socks.nec.com/protocol/socks4.protocol\n */\n\npackage com.jcraft.jsch;\n\nimport java.io.*;\nimport java.net.*;\n\npublic class ProxySOCKS4 implements Proxy{\n  private static int DEFAULTPORT=1080;\n  private String proxy_host;\n  private int proxy_port;\n  private InputStream in;\n  private OutputStream out;\n  private Socket socket;\n  private String user;\n  private String passwd;\n\n  public ProxySOCKS4(String proxy_host){\n    int port=DEFAULTPORT;\n    String host=proxy_host;\n    if(proxy_host.indexOf(':')!=-1){\n      try{\n\thost=proxy_host.substring(0, proxy_host.indexOf(':'));\n\tport=Integer.parseInt(proxy_host.substring(proxy_host.indexOf(':')+1));\n      }\n      catch(Exception e){\n      }\n    }\n    this.proxy_host=host;\n    this.proxy_port=port;\n  }\n  public ProxySOCKS4(String proxy_host, int proxy_port){\n    this.proxy_host=proxy_host;\n    this.proxy_port=proxy_port;\n  }\n  public void setUserPasswd(String user, String passwd){\n    this.user=user;\n    this.passwd=passwd;\n  }\n  public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws JSchException{\n    try{\n      if(socket_factory==null){\n        socket=Util.createSocket(proxy_host, proxy_port, timeout);\n        //socket=new Socket(proxy_host, proxy_port);    \n        in=socket.getInputStream();\n        out=socket.getOutputStream();\n      }\n      else{\n        socket=socket_factory.createSocket(proxy_host, proxy_port);\n        in=socket_factory.getInputStream(socket);\n        out=socket_factory.getOutputStream(socket);\n      }\n      if(timeout>0){\n        socket.setSoTimeout(timeout);\n      }\n      socket.setTcpNoDelay(true);\n\n      byte[] buf=new byte[1024];\n      int index=0;\n\n/*\n   1) CONNECT\n   \n   The client connects to the SOCKS server and sends a CONNECT request when\n   it wants to establish a connection to an application server. The client\n   includes in the request packet the IP address and the port number of the\n   destination host, and userid, in the following format.\n   \n               +----+----+----+----+----+----+----+----+----+----+....+----+\n               | VN | CD | DSTPORT |      DSTIP        | USERID       |NULL|\n               +----+----+----+----+----+----+----+----+----+----+....+----+\n   # of bytes:   1    1      2              4           variable       1\n   \n   VN is the SOCKS protocol version number and should be 4. CD is the\n   SOCKS command code and should be 1 for CONNECT request. NULL is a byte\n   of all zero bits.\n*/\n     \n      index=0;\n      buf[index++]=4;\n      buf[index++]=1;\n\n      buf[index++]=(byte)(port>>>8);\n      buf[index++]=(byte)(port&0xff);\n\n      try{\n        InetAddress addr=InetAddress.getByName(host);\n        byte[] byteAddress = addr.getAddress();\n        for (int i = 0; i < byteAddress.length; i++) {\n          buf[index++]=byteAddress[i];\n        }\n      }\n      catch(UnknownHostException uhe){\n        throw new JSchException(\"ProxySOCKS4: \"+uhe.toString(), uhe);\n      }\n\n      if(user!=null){\n        System.arraycopy(Util.str2byte(user), 0, buf, index, user.length());\n        index+=user.length();\n      }\n      buf[index++]=0;\n      out.write(buf, 0, index);\n\n/*\n   The SOCKS server checks to see whether such a request should be granted\n   based on any combination of source IP address, destination IP address,\n   destination port number, the userid, and information it may obtain by\n   consulting IDENT, cf. RFC 1413.  If the request is granted, the SOCKS\n   server makes a connection to the specified port of the destination host.\n   A reply packet is sent to the client when this connection is established,\n   or when the request is rejected or the operation fails. \n   \n               +----+----+----+----+----+----+----+----+\n               | VN | CD | DSTPORT |      DSTIP        |\n               +----+----+----+----+----+----+----+----+\n   # of bytes:   1    1      2              4\n   \n   VN is the version of the reply code and should be 0. CD is the result\n   code with one of the following values:\n   \n   90: request granted\n   91: request rejected or failed\n   92: request rejected becasue SOCKS server cannot connect to\n       identd on the client\n   93: request rejected because the client program and identd\n       report different user-ids\n   \n   The remaining fields are ignored.\n*/\n\n      int len=8;\n      int s=0;\n      while(s<len){\n        int i=in.read(buf, s, len-s);\n        if(i<=0){\n          throw new JSchException(\"ProxySOCKS4: stream is closed\");\n        }\n        s+=i;\n      }\n      if(buf[0]!=0){\n        throw new JSchException(\"ProxySOCKS4: server returns VN \"+buf[0]);\n      }\n      if(buf[1]!=90){\n        try{ socket.close(); }\n\tcatch(Exception eee){\n\t}\n        String message=\"ProxySOCKS4: server returns CD \"+buf[1];\n        throw new JSchException(message);\n      }\n    }\n    catch(RuntimeException e){\n      throw e;\n    }\n    catch(Exception e){\n      try{ if(socket!=null)socket.close(); }\n      catch(Exception eee){\n      }\n      throw new JSchException(\"ProxySOCKS4: \"+e.toString());\n    }\n  }\n  public InputStream getInputStream(){ return in; }\n  public OutputStream getOutputStream(){ return out; }\n  public Socket getSocket(){ return socket; }\n  public void close(){\n    try{\n      if(in!=null)in.close();\n      if(out!=null)out.close();\n      if(socket!=null)socket.close();\n    }\n    catch(Exception e){\n    }\n    in=null;\n    out=null;\n    socket=null;\n  }\n  public static int getDefaultPort(){\n    return DEFAULTPORT;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ProxySOCKS5.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n/*\n This file depends on following documents,\n   - RFC 1928  SOCKS Protocol Verseion 5  \n   - RFC 1929  Username/Password Authentication for SOCKS V5. \n */\n\npackage com.jcraft.jsch;\n\nimport java.io.*;\nimport java.net.*;\n\npublic class ProxySOCKS5 implements Proxy{\n  private static int DEFAULTPORT=1080;\n  private String proxy_host;\n  private int proxy_port;\n  private InputStream in;\n  private OutputStream out;\n  private Socket socket;\n  private String user;\n  private String passwd;\n\n  public ProxySOCKS5(String proxy_host){\n    int port=DEFAULTPORT;\n    String host=proxy_host;\n    if(proxy_host.indexOf(':')!=-1){\n      try{\n\thost=proxy_host.substring(0, proxy_host.indexOf(':'));\n\tport=Integer.parseInt(proxy_host.substring(proxy_host.indexOf(':')+1));\n      }\n      catch(Exception e){\n      }\n    }\n    this.proxy_host=host;\n    this.proxy_port=port;\n  }\n  public ProxySOCKS5(String proxy_host, int proxy_port){\n    this.proxy_host=proxy_host;\n    this.proxy_port=proxy_port;\n  }\n  public void setUserPasswd(String user, String passwd){\n    this.user=user;\n    this.passwd=passwd;\n  }\n  public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws JSchException{\n    try{\n      if(socket_factory==null){\n        socket=Util.createSocket(proxy_host, proxy_port, timeout);\n        //socket=new Socket(proxy_host, proxy_port);    \n        in=socket.getInputStream();\n        out=socket.getOutputStream();\n      }\n      else{\n        socket=socket_factory.createSocket(proxy_host, proxy_port);\n        in=socket_factory.getInputStream(socket);\n        out=socket_factory.getOutputStream(socket);\n      }\n      if(timeout>0){\n        socket.setSoTimeout(timeout);\n      }\n      socket.setTcpNoDelay(true);\n\n      byte[] buf=new byte[1024];\n      int index=0;\n\n/*\n                   +----+----------+----------+\n                   |VER | NMETHODS | METHODS  |\n                   +----+----------+----------+\n                   | 1  |    1     | 1 to 255 |\n                   +----+----------+----------+\n\n   The VER field is set to X'05' for this version of the protocol.  The\n   NMETHODS field contains the number of method identifier octets that\n   appear in the METHODS field.\n\n   The values currently defined for METHOD are:\n\n          o  X'00' NO AUTHENTICATION REQUIRED\n          o  X'01' GSSAPI\n          o  X'02' USERNAME/PASSWORD\n          o  X'03' to X'7F' IANA ASSIGNED\n          o  X'80' to X'FE' RESERVED FOR PRIVATE METHODS\n          o  X'FF' NO ACCEPTABLE METHODS\n*/\n\n      buf[index++]=5;\n\n      buf[index++]=2;\n      buf[index++]=0;           // NO AUTHENTICATION REQUIRED\n      buf[index++]=2;           // USERNAME/PASSWORD\n\n      out.write(buf, 0, index);\n\n/*\n    The server selects from one of the methods given in METHODS, and\n    sends a METHOD selection message:\n\n                         +----+--------+\n                         |VER | METHOD |\n                         +----+--------+\n                         | 1  |   1    |\n                         +----+--------+\n*/\n      //in.read(buf, 0, 2);\n      fill(in, buf, 2);\n \n      boolean check=false;\n      switch((buf[1])&0xff){\n        case 0:                // NO AUTHENTICATION REQUIRED\n          check=true;\n          break;\n        case 2:                // USERNAME/PASSWORD\n          if(user==null || passwd==null)break;\n\n/*\n   Once the SOCKS V5 server has started, and the client has selected the\n   Username/Password Authentication protocol, the Username/Password\n   subnegotiation begins.  This begins with the client producing a\n   Username/Password request:\n\n           +----+------+----------+------+----------+\n           |VER | ULEN |  UNAME   | PLEN |  PASSWD  |\n           +----+------+----------+------+----------+\n           | 1  |  1   | 1 to 255 |  1   | 1 to 255 |\n           +----+------+----------+------+----------+\n\n   The VER field contains the current version of the subnegotiation,\n   which is X'01'. The ULEN field contains the length of the UNAME field\n   that follows. The UNAME field contains the username as known to the\n   source operating system. The PLEN field contains the length of the\n   PASSWD field that follows. The PASSWD field contains the password\n   association with the given UNAME.\n*/\n          index=0;\n          buf[index++]=1;\n          buf[index++]=(byte)(user.length());\n\t  System.arraycopy(Util.str2byte(user), 0, buf, index, user.length());\n\t  index+=user.length();\n          buf[index++]=(byte)(passwd.length());\n\t  System.arraycopy(Util.str2byte(passwd), 0, buf, index, passwd.length());\n\t  index+=passwd.length();\n\n          out.write(buf, 0, index);\n\n/*\n   The server verifies the supplied UNAME and PASSWD, and sends the\n   following response:\n\n                        +----+--------+\n                        |VER | STATUS |\n                        +----+--------+\n                        | 1  |   1    |\n                        +----+--------+\n\n   A STATUS field of X'00' indicates success. If the server returns a\n   `failure' (STATUS value other than X'00') status, it MUST close the\n   connection.\n*/\n          //in.read(buf, 0, 2);\n          fill(in, buf, 2);\n          if(buf[1]==0)\n            check=true;\n          break;\n        default:\n      }\n\n      if(!check){\n        try{ socket.close(); }\n\tcatch(Exception eee){\n\t}\n        throw new JSchException(\"fail in SOCKS5 proxy\");\n      }\n\n/*\n      The SOCKS request is formed as follows:\n\n        +----+-----+-------+------+----------+----------+\n        |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |\n        +----+-----+-------+------+----------+----------+\n        | 1  |  1  | X'00' |  1   | Variable |    2     |\n        +----+-----+-------+------+----------+----------+\n\n      Where:\n\n      o  VER    protocol version: X'05'\n      o  CMD\n         o  CONNECT X'01'\n         o  BIND X'02'\n         o  UDP ASSOCIATE X'03'\n      o  RSV    RESERVED\n         o  ATYP   address type of following address\n         o  IP V4 address: X'01'\n         o  DOMAINNAME: X'03'\n         o  IP V6 address: X'04'\n      o  DST.ADDR       desired destination address\n      o  DST.PORT desired destination port in network octet\n         order\n*/\n     \n      index=0;\n      buf[index++]=5;\n      buf[index++]=1;       // CONNECT\n      buf[index++]=0;\n\n      byte[] hostb=Util.str2byte(host);\n      int len=hostb.length;\n      buf[index++]=3;      // DOMAINNAME\n      buf[index++]=(byte)(len);\n      System.arraycopy(hostb, 0, buf, index, len);\n      index+=len;\n      buf[index++]=(byte)(port>>>8);\n      buf[index++]=(byte)(port&0xff);\n\n      out.write(buf, 0, index);\n\n/*\n   The SOCKS request information is sent by the client as soon as it has\n   established a connection to the SOCKS server, and completed the\n   authentication negotiations.  The server evaluates the request, and\n   returns a reply formed as follows:\n\n        +----+-----+-------+------+----------+----------+\n        |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |\n        +----+-----+-------+------+----------+----------+\n        | 1  |  1  | X'00' |  1   | Variable |    2     |\n        +----+-----+-------+------+----------+----------+\n\n   Where:\n\n   o  VER    protocol version: X'05'\n   o  REP    Reply field:\n      o  X'00' succeeded\n      o  X'01' general SOCKS server failure\n      o  X'02' connection not allowed by ruleset\n      o  X'03' Network unreachable\n      o  X'04' Host unreachable\n      o  X'05' Connection refused\n      o  X'06' TTL expired\n      o  X'07' Command not supported\n      o  X'08' Address type not supported\n      o  X'09' to X'FF' unassigned\n    o  RSV    RESERVED\n    o  ATYP   address type of following address\n      o  IP V4 address: X'01'\n      o  DOMAINNAME: X'03'\n      o  IP V6 address: X'04'\n    o  BND.ADDR       server bound address\n    o  BND.PORT       server bound port in network octet order\n*/\n\n      //in.read(buf, 0, 4);\n      fill(in, buf, 4);\n\n      if(buf[1]!=0){\n        try{ socket.close(); }\n\tcatch(Exception eee){\n\t}\n        throw new JSchException(\"ProxySOCKS5: server returns \"+buf[1]);\n      }\n\n      switch(buf[3]&0xff){\n        case 1:\n          //in.read(buf, 0, 6);\n          fill(in, buf, 6);\n\t  break;\n        case 3:\n          //in.read(buf, 0, 1);\n          fill(in, buf, 1);\n          //in.read(buf, 0, buf[0]+2);\n          fill(in, buf, (buf[0]&0xff)+2);\n\t  break;\n        case 4:\n          //in.read(buf, 0, 18);\n          fill(in, buf, 18);\n          break;\n        default:\n      }\n    }\n    catch(RuntimeException e){\n      throw e;\n    }\n    catch(Exception e){\n      try{ if(socket!=null)socket.close(); }\n      catch(Exception eee){\n      }\n      String message=\"ProxySOCKS5: \"+e.toString();\n      if(e instanceof Throwable)\n        throw new JSchException(message, (Throwable)e);\n      throw new JSchException(message);\n    }\n  }\n  public InputStream getInputStream(){ return in; }\n  public OutputStream getOutputStream(){ return out; }\n  public Socket getSocket(){ return socket; }\n  public void close(){\n    try{\n      if(in!=null)in.close();\n      if(out!=null)out.close();\n      if(socket!=null)socket.close();\n    }\n    catch(Exception e){\n    }\n    in=null;\n    out=null;\n    socket=null;\n  }\n  public static int getDefaultPort(){\n    return DEFAULTPORT;\n  }\n  private void fill(InputStream in, byte[] buf, int len) throws JSchException, IOException{\n    int s=0;\n    while(s<len){\n      int i=in.read(buf, s, len-s);\n      if(i<=0){\n        throw new JSchException(\"ProxySOCKS5: stream is closed\");\n      }\n      s+=i;\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/README",
    "content": "\n                                      JSch\n\n                                Java Secure Channel\n                         by ymnk@jcraft.com, JCraft,Inc.\n\n                            http://www.jcraft.com/jsch/\n\nLast modified: Thu Mar 18 13:58:16 UTC 2015\n\n\nDescription\n===========\nJSch is a pure Java implementation of SSH2.  JSch allows you to \nconnect to an sshd server and use port forwarding, X11 forwarding, \nfile transfer, etc., and you can integrate its functionality\ninto your own Java programs. JSch is licensed under BSD style license.\n\n\nDocumentation\n=============\n* README files all over the source tree have info related to the stuff\n  in the directories. \n* ChangeLog: what changed from the previous version?\n\n\nDirectories & Files in the Source Tree\n======================================\n* src/com/ has source trees of JSch\n* example/ has some samples, which demonstrate the usages.\n* tools/ has scripts for Ant.\n\n\nWhy JSch?\n==========\nOur intension in developing this stuff is to enable users of our pure\njava X servers, WiredX(http://wiredx.net/) and WeirdX, to enjoy secure X\nsessions.  Our efforts have mostly targeted the SSH2 protocol in relation\nto X Window System and X11 forwarding.  Of course, we are also interested in \nadding other functionality - port forward, file transfer, terminal emulation, etc.\n\n\nFeatures\n========\n* JSch is in pure Java, but it depends on JavaTM Cryptography\n  Extension (JCE).  JSch is know to work with:\n  o J2SE 1.4.0 or later (no additional libraries required).\n  o J2SE 1.3 and Sun's JCE reference implementation that can be\n    obtained at http://java.sun.com/products/jce/\n  o J2SE 1.2.2 and later and Bouncycastle's JCE implementation that\n    can be obtained at http://www.bouncycastle.org/\n* SSH2 protocol support.\n* Key exchange: diffie-hellman-group-exchange-sha1,\n                diffie-hellman-group1-sha1,\n                diffie-hellman-group14-sha1,\n                diffie-hellman-group-exchange-sha256,\n                ecdh-sha2-nistp256,\n                ecdh-sha2-nistp384,\n                ecdh-sha2-nistp521\n* Cipher: blowfish-cbc,3des-cbc,aes128-cbc,aes192-cbc,aes256-cbc\n          3des-ctr,aes128-ctr,aes192-ctr,aes256-ctc,\n          arcfour,arcfour128,arcfour256\n* MAC: hmac-md5,hmac-md5-96,hmac-sha1,hmac-sha1-96\n* Host key type: ssh-dss,ssh-rsa,\n                 ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521\n* Userauth: password\n* Userauth: publickey(DSA,RSA,ECDSA)\n* Userauth: keyboard-interactive\n* Userauth: gssapi-with-mic\n* X11 forwarding.\n* xauth spoofing.\n* connection through HTTP proxy.\n* connection through SOCKS5, SOCKS4 proxy.\n* port forwarding.\n* stream forwarding.\n* signal sending.\n  The unofficial patch for sshd of openssh will be find in the thread\n  http://marc.theaimsgroup.com/?l=openssh-unix-dev&m=104295745607575&w=2\n* envrironment variable passing.\n* remote exec.\n* generating DSA and RSA key pairs.\n* supporting private keys in OpenSSL(traditional SSLeay) and PKCS#8 format.\n* SSH File Transfer Protocol(version 0, 1, 2, 3)\n* partial authentication\n* packet compression: zlib, zlib@openssh.com\n  JZlib(http://www.jcraft.com/jzlib/) has been used.\n* hashed known_hosts file.\n* NONE Cipher switching.\n  http://www.psc.edu/networking/projects/hpn-ssh/none.php\n* JSch is licensed under BSD style license(refer to LICENSE.txt).\n\n\nHow To Try\n==========\nThis archive does not include java byte code, so please compile\nthe source code by your self.\n  $ cd jsch-?.?.?/src\n  $ javac com/jcraft/jsch/*java com/jcraft/jsch/jce/*java com/jcraft/jzlib/*.java\n'/examples/' directory has included some samples to demonstrate what \nJSch can do.  Please refer to '/examples/README' file.\n\n\nAES cipher\n==========\nJSch supports aes128-cbc,aes192-cbc,aes256-cbc,aes128-ctr,aes192-ctr,\naes256-ctr but you require AES support in your J2SE to choose some of them.  \nIf you are using Sun's J2SE, J2SE 1.4.2 or later is required.  \nAnd then, J2SE 1.4.2(or later) does not support aes256 by the default, \nbecause of 'import control restrictions of some countries'.\nWe have confirmed that by applying\n  \"Java Cryptography Extension (JCE)\n  Unlimited Strength Jurisdiction Policy Files 1.4.2\"\non\n  http://java.sun.com/j2se/1.4.2/download.html#docs\nwe can enjoy 'aes256-cbc,aes256-ctr'.\n\n\nStream Forwarding\n=================\nJSch has a unique functionality, Stream Forwarding.\nStream Forwarding allows you to plug Java I/O streams directly into a remote TCP\nport without assigning and opening a local TCP port.\nIn port forwarding, as with the -L option of ssh command, you have to assign\nand open a local TCP port and that port is also accessible by crackers\non localhost.  In some case, that local TCP port may be plugged to a\nsecret port via SSH session.\nA sample program, /example/StreamForwarding.java , demonstrates\nthis functionality.\n\n\nGenerating Authentication Keys\n==============================\nJSch allows you to generate DSA and RSA key pairs, which are in OpenSSH format.\nPlease refer to 'examples/KeyGen.java'.\n\n\nPacket Compression\n==================\nAccording to the draft from IETF sesch working group, the packet\ncompression can be applied to each data stream directions; from sshd\nserver to ssh client and from ssh client to sshd server.  So, jsch\nallows you to choose which data stream direction will be compressed or not.\nFor example, in X11 forwarding session, the packet compression for data\nstream from sshd to ssh client will save the network traffic, but\nusually the traffic from ssh client to sshd is light, so by omitting\nthe compression for this direction, you may be able to save some CPU time.\nPlease refer to a sample program 'examples/Compression.java'.\n\n\nProperty\n========\nBy setting properties, you can control the behavior of jsch.\nHere is an example of enabling the packet compression,\n\n      Session session=jsch.getSession(user, host, 22);\n      java.util.Properties config=new java.util.Properties();\n      config.put(\"compression.s2c\", \"zlib,none\");\n      config.put(\"compression.c2s\", \"zlib,none\");\n      session.setConfig(config);\n      session.connect();\n\nCurrent release has supported following properties,\n* compression.s2c: zlib, none\n  default: none\n  Specifies whether to use compression for the data stream\n  from sshd to jsch.  If \"zlib,none\" is given and the remote sshd does\n  not allow the packet compression, compression will not be done.\n* compression.c2s: zlib, none\n  default: none\n  Specifies whether to use compression for the data stream\n  from jsch to sshd.\n* StrictHostKeyChecking: ask | yes | no\n  default: ask\n  If this property is set to ``yes'', jsch will never automatically add\n  host keys to the $HOME/.ssh/known_hosts file, and refuses to connect\n  to hosts whose host key has changed.  This property forces the user\n  to manually add all new hosts.  If this property is set to ``no'', \n  jsch will automatically add new host keys to the user known hosts\n  files.  If this property is set to ``ask'', new  host keys will be\n  added to the user known host files only after the user has confirmed \n  that is what they really want to do, and jsch will refuse to connect \n  to hosts whose host key has changed.\n\n\nTODO\n====\n* re-implementation with java.nio.\n* replacing cipher, hash by JCE with pure Java code.\n* SSH File Transfer Protocol version 4.\n* error handling.\n\n\nCopyrights & Disclaimers\n========================\nJSch is copyrighted by ymnk, JCraft,Inc. and is licensed through BSD style license.\nRead the LICENSE.txt file for the complete license.\n\n\nCredits and Acknowledgments\n============================\nJSch has been developed by ymnk@jcraft.com and it can not be hacked\nwithout several help.\n* First of all, we want to thank JCE team at Sun Microsystems.\n  For long time, we had planed to implement SSH2 in pure Java,\n  but we had hesitated to do because tons of work must be done for\n  implementing ciphers, hashes, etc., from the scratch.\n  Thanks to newly added functionalities to J2SE 1.4.0, we could\n  start this project.\n* We appreciate the OpenSSH project.\n  The options '-ddd' of sshd, '---vvv' of ssh and the compile options \n  '-DPACKET_DEBUG', '-DDEBUG_KEXDH' and  '-DDEBUG_KEX' were very\n  useful in debugging JSch.\n* We appreciate IETF sesch working group and SSH Communications Security Corp.\n  Without the standardization of the protocol, we could not get the\n  chance to implement JSch.\n* We appreciate Seigo Haruyama(http://www.unixuser.org/~haruyama/),\n  who are interpreting drafts of SSH2 protocol in Japanese.\n  His works were very useful for us to understand the technical terms\n  in our native language.\n* We also appreciate SourceForge.net's awesome service to the \n  Open Source Community.\n\n\nIf you have any comments, suggestions and questions, write us \nat jsch@jcraft.com\n\n\n``SSH is a registered trademark and Secure Shell is a trademark of\nSSH Communications Security Corp (www.ssh.com)''.\n"
  },
  {
    "path": "java/com/jcraft/jsch/Random.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface Random{\n  void fill(byte[] foo, int start, int len);\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/Request.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nabstract class Request{\n  private boolean reply=false;\n  private Session session=null;\n  private Channel channel=null;\n  void request(Session session, Channel channel) throws Exception{\n    this.session=session;\n    this.channel=channel;\n    if(channel.connectTimeout>0){\n      setReply(true);\n    }\n  }\n  boolean waitForReply(){ return reply; }\n  void setReply(boolean reply){ this.reply=reply; }\n  void write(Packet packet) throws Exception{\n    if(reply){\n      channel.reply=-1;\n    }\n    session.write(packet);\n    if(reply){\n      long start=System.currentTimeMillis();\n      long timeout=channel.connectTimeout;\n      while(channel.isConnected() && channel.reply==-1){\n\ttry{Thread.sleep(10);}\n\tcatch(Exception ee){\n\t}\n        if(timeout>0L &&\n           (System.currentTimeMillis()-start)>timeout){\n          channel.reply=0;\n          throw new JSchException(\"channel request: timeout\");\n        }\n      }\n\n      if(channel.reply==0){\n\tthrow new JSchException(\"failed to send channel request\");\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/RequestAgentForwarding.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass RequestAgentForwarding extends Request{\n  public void request(Session session, Channel channel) throws Exception{\n    super.request(session, channel);\n\n    setReply(false);\n\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n\n    // byte      SSH_MSG_CHANNEL_REQUEST(98)\n    // uint32 recipient channel\n    // string request type        // \"auth-agent-req@openssh.com\"\n    // boolean want reply         // 0\n    packet.reset();\n    buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST);\n    buf.putInt(channel.getRecipient());\n    buf.putString(Util.str2byte(\"auth-agent-req@openssh.com\"));\n    buf.putByte((byte)(waitForReply() ? 1 : 0));\n    write(packet);\n    session.agent_forwarding=true;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/RequestEnv.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass RequestEnv extends Request{\n  byte[] name=new byte[0];\n  byte[] value=new byte[0];\n  void setEnv(byte[] name, byte[] value){\n    this.name=name;\n    this.value=value;\n  }\n  public void request(Session session, Channel channel) throws Exception{\n    super.request(session, channel);\n\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n\n    packet.reset();\n    buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST);\n    buf.putInt(channel.getRecipient());\n    buf.putString(Util.str2byte(\"env\"));\n    buf.putByte((byte)(waitForReply() ? 1 : 0));\n    buf.putString(name);\n    buf.putString(value);\n    write(packet);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/RequestExec.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass RequestExec extends Request{\n  private byte[] command=new byte[0];\n  RequestExec(byte[] command){\n    this.command=command;\n  }\n  public void request(Session session, Channel channel) throws Exception{\n    super.request(session, channel);\n\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n\n    // send\n    // byte     SSH_MSG_CHANNEL_REQUEST(98)\n    // uint32 recipient channel\n    // string request type       // \"exec\"\n    // boolean want reply        // 0\n    // string command\n    packet.reset();\n    buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST);\n    buf.putInt(channel.getRecipient());\n    buf.putString(Util.str2byte(\"exec\"));\n    buf.putByte((byte)(waitForReply() ? 1 : 0));\n    buf.checkFreeSize(4+command.length);\n    buf.putString(command);\n    write(packet);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/RequestPtyReq.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass RequestPtyReq extends Request{\n  private String ttype=\"vt100\";\n  private int tcol=80;\n  private int trow=24;\n  private int twp=640;\n  private int thp=480;\n\n  private byte[] terminal_mode=Util.empty;\n\n  void setCode(String cookie){\n  }\n\n  void setTType(String ttype){\n    this.ttype=ttype;\n  }\n  \n  void setTerminalMode(byte[] terminal_mode){\n    this.terminal_mode=terminal_mode;\n  }\n\n  void setTSize(int tcol, int trow, int twp, int thp){\n    this.tcol=tcol;\n    this.trow=trow;\n    this.twp=twp;\n    this.thp=thp;\n  }\n\n  public void request(Session session, Channel channel) throws Exception{\n    super.request(session, channel);\n\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n\n    packet.reset();\n    buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST);\n    buf.putInt(channel.getRecipient());\n    buf.putString(Util.str2byte(\"pty-req\"));\n    buf.putByte((byte)(waitForReply() ? 1 : 0));\n    buf.putString(Util.str2byte(ttype));\n    buf.putInt(tcol);\n    buf.putInt(trow);\n    buf.putInt(twp);\n    buf.putInt(thp);\n    buf.putString(terminal_mode);\n    write(packet);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/RequestSftp.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class RequestSftp extends Request{\n  RequestSftp(){\n    setReply(true);\n  }\n  public void request(Session session, Channel channel) throws Exception{\n    super.request(session, channel);\n\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n    packet.reset();\n    buf.putByte((byte)Session.SSH_MSG_CHANNEL_REQUEST);\n    buf.putInt(channel.getRecipient());\n    buf.putString(Util.str2byte(\"subsystem\"));\n    buf.putByte((byte)(waitForReply() ? 1 : 0));\n    buf.putString(Util.str2byte(\"sftp\"));\n    write(packet);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/RequestShell.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass RequestShell extends Request{\n  public void request(Session session, Channel channel) throws Exception{\n    super.request(session, channel);\n\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n\n    // send\n    // byte     SSH_MSG_CHANNEL_REQUEST(98)\n    // uint32 recipient channel\n    // string request type       // \"shell\"\n    // boolean want reply        // 0\n    packet.reset();\n    buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST);\n    buf.putInt(channel.getRecipient());\n    buf.putString(Util.str2byte(\"shell\"));\n    buf.putByte((byte)(waitForReply() ? 1 : 0));\n    write(packet);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/RequestSignal.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass RequestSignal extends Request{\n  private String signal=\"KILL\";\n  public void setSignal(String foo){ signal=foo; }\n  public void request(Session session, Channel channel) throws Exception{\n    super.request(session, channel);\n\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n\n    packet.reset();\n    buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST);\n    buf.putInt(channel.getRecipient());\n    buf.putString(Util.str2byte(\"signal\"));\n    buf.putByte((byte)(waitForReply() ? 1 : 0));\n    buf.putString(Util.str2byte(signal));\n    write(packet);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/RequestSubsystem.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2005-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class RequestSubsystem extends Request{\n  private String subsystem=null;\n  public void request(Session session, Channel channel, String subsystem, boolean want_reply) throws Exception{\n    setReply(want_reply);\n    this.subsystem=subsystem;\n    this.request(session, channel);\n  }\n  public void request(Session session, Channel channel) throws Exception{\n    super.request(session, channel);\n\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n\n    packet.reset();\n    buf.putByte((byte)Session.SSH_MSG_CHANNEL_REQUEST);\n    buf.putInt(channel.getRecipient());\n    buf.putString(Util.str2byte(\"subsystem\"));\n    buf.putByte((byte)(waitForReply() ? 1 : 0));\n    buf.putString(Util.str2byte(subsystem));\n    write(packet);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/RequestWindowChange.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass RequestWindowChange extends Request{\n  int width_columns=80;\n  int height_rows=24;\n  int width_pixels=640;\n  int height_pixels=480;\n  void setSize(int col, int row, int wp, int hp){\n    this.width_columns=col; \n    this.height_rows=row; \n    this.width_pixels=wp;\n    this.height_pixels=hp;\n  }\n  public void request(Session session, Channel channel) throws Exception{\n    super.request(session, channel);\n\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n\n    //byte      SSH_MSG_CHANNEL_REQUEST\n    //uint32    recipient_channel\n    //string    \"window-change\"\n    //boolean   FALSE\n    //uint32    terminal width, columns\n    //uint32    terminal height, rows\n    //uint32    terminal width, pixels\n    //uint32    terminal height, pixels\n    packet.reset();\n    buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST);\n    buf.putInt(channel.getRecipient());\n    buf.putString(Util.str2byte(\"window-change\"));\n    buf.putByte((byte)(waitForReply() ? 1 : 0));\n    buf.putInt(width_columns);\n    buf.putInt(height_rows);\n    buf.putInt(width_pixels);\n    buf.putInt(height_pixels);\n    write(packet);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/RequestX11.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass RequestX11 extends Request{\n  public void setCookie(String cookie){\n    ChannelX11.cookie=Util.str2byte(cookie);\n  }\n  public void request(Session session, Channel channel) throws Exception{\n    super.request(session, channel);\n\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n\n    // byte      SSH_MSG_CHANNEL_REQUEST(98)\n    // uint32 recipient channel\n    // string request type        // \"x11-req\"\n    // boolean want reply         // 0\n    // boolean   single connection\n    // string    x11 authentication protocol // \"MIT-MAGIC-COOKIE-1\".\n    // string    x11 authentication cookie\n    // uint32    x11 screen number\n    packet.reset();\n    buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST);\n    buf.putInt(channel.getRecipient());\n    buf.putString(Util.str2byte(\"x11-req\"));\n    buf.putByte((byte)(waitForReply() ? 1 : 0));\n    buf.putByte((byte)0);\n    buf.putString(Util.str2byte(\"MIT-MAGIC-COOKIE-1\"));\n    buf.putString(ChannelX11.getFakedCookie(session));\n    buf.putInt(0);\n    write(packet);\n\n    session.x11_forwarding=true;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/ServerSocketFactory.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.net.*;\nimport java.io.*;\n\npublic interface ServerSocketFactory{\n  public ServerSocket createServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException;\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/Session.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.io.*;\nimport java.net.*;\nimport java.util.Vector;\n\npublic class Session implements Runnable{\n\n  // http://ietf.org/internet-drafts/draft-ietf-secsh-assignednumbers-01.txt\n  static final int SSH_MSG_DISCONNECT=                      1;\n  static final int SSH_MSG_IGNORE=                          2;\n  static final int SSH_MSG_UNIMPLEMENTED=                   3;\n  static final int SSH_MSG_DEBUG=                           4;\n  static final int SSH_MSG_SERVICE_REQUEST=                 5;\n  static final int SSH_MSG_SERVICE_ACCEPT=                  6;\n  static final int SSH_MSG_KEXINIT=                        20;\n  static final int SSH_MSG_NEWKEYS=                        21;\n  static final int SSH_MSG_KEXDH_INIT=                     30;\n  static final int SSH_MSG_KEXDH_REPLY=                    31;\n  static final int SSH_MSG_KEX_DH_GEX_GROUP=               31;\n  static final int SSH_MSG_KEX_DH_GEX_INIT=                32;\n  static final int SSH_MSG_KEX_DH_GEX_REPLY=               33;\n  static final int SSH_MSG_KEX_DH_GEX_REQUEST=             34;\n  static final int SSH_MSG_GLOBAL_REQUEST=                 80;\n  static final int SSH_MSG_REQUEST_SUCCESS=                81;\n  static final int SSH_MSG_REQUEST_FAILURE=                82;\n  static final int SSH_MSG_CHANNEL_OPEN=                   90;\n  static final int SSH_MSG_CHANNEL_OPEN_CONFIRMATION=      91;\n  static final int SSH_MSG_CHANNEL_OPEN_FAILURE=           92;\n  static final int SSH_MSG_CHANNEL_WINDOW_ADJUST=          93;\n  static final int SSH_MSG_CHANNEL_DATA=                   94;\n  static final int SSH_MSG_CHANNEL_EXTENDED_DATA=          95;\n  static final int SSH_MSG_CHANNEL_EOF=                    96;\n  static final int SSH_MSG_CHANNEL_CLOSE=                  97;\n  static final int SSH_MSG_CHANNEL_REQUEST=                98;\n  static final int SSH_MSG_CHANNEL_SUCCESS=                99;\n  static final int SSH_MSG_CHANNEL_FAILURE=               100;\n\n  private static final int PACKET_MAX_SIZE = 256 * 1024;\n\n  private byte[] V_S;                                 // server version\n  private byte[] V_C=Util.str2byte(\"SSH-2.0-JSCH-\"+JSch.VERSION); // client version\n\n  private byte[] I_C; // the payload of the client's SSH_MSG_KEXINIT\n  private byte[] I_S; // the payload of the server's SSH_MSG_KEXINIT\n  private byte[] K_S; // the host key\n\n  private byte[] session_id;\n\n  private byte[] IVc2s;\n  private byte[] IVs2c;\n  private byte[] Ec2s;\n  private byte[] Es2c;\n  private byte[] MACc2s;\n  private byte[] MACs2c;\n\n  private int seqi=0;\n  private int seqo=0;\n\n  String[] guess=null;\n  private Cipher s2ccipher;\n  private Cipher c2scipher;\n  private MAC s2cmac;\n  private MAC c2smac;\n  //private byte[] mac_buf;\n  private byte[] s2cmac_result1;\n  private byte[] s2cmac_result2;\n\n  private Compression deflater;\n  private Compression inflater;\n\n  private IO io;\n  private Socket socket;\n  private int timeout=0;\n\n  private volatile boolean isConnected=false;\n\n  private boolean isAuthed=false;\n\n  private Thread connectThread=null;\n  private Object lock=new Object();\n\n  boolean x11_forwarding=false;\n  boolean agent_forwarding=false;\n\n  InputStream in=null;\n  OutputStream out=null;\n\n  static Random random;\n\n  Buffer buf;\n  Packet packet;\n\n  SocketFactory socket_factory=null;\n\n  static final int buffer_margin = 32 + // maximum padding length\n                                   20 + // maximum mac length\n                                   32;  // margin for deflater; deflater may inflate data\n\n  private java.util.Hashtable config=null;\n\n  private Proxy proxy=null;\n  private UserInfo userinfo;\n\n  private String hostKeyAlias=null;\n  private int serverAliveInterval=0;\n  private int serverAliveCountMax=1;\n\n  private IdentityRepository identityRepository = null;\n  private HostKeyRepository hostkeyRepository = null;\n\n  protected boolean daemon_thread=false;\n\n  private long kex_start_time=0L;\n\n  int max_auth_tries = 6;\n  int auth_failures = 0;\n\n  String host=\"127.0.0.1\";\n  String org_host=\"127.0.0.1\";\n  int port=22;\n\n  String username=null;\n  byte[] password=null;\n\n  JSch jsch;\n\n  Session(JSch jsch, String username, String host, int port) throws JSchException{\n    super();\n    this.jsch=jsch;\n    buf=new Buffer();\n    packet=new Packet(buf);\n    this.username = username;\n    this.org_host = this.host = host;\n    this.port = port;\n\n    applyConfig();\n\n    if(this.username==null) {\n      try {\n        this.username=(String)(System.getProperties().get(\"user.name\"));\n      }\n      catch(SecurityException e){\n        // ignore e\n      }\n    }\n\n    if(this.username==null) {\n      throw new JSchException(\"username is not given.\");\n    }\n  }\n\n  public void connect() throws JSchException{\n    connect(timeout);\n  }\n\n  public void connect(int connectTimeout) throws JSchException{\n    if(isConnected){\n      throw new JSchException(\"session is already connected\");\n    }\n\n    io=new IO();\n    if(random==null){\n      try{\n\tClass c=Class.forName(getConfig(\"random\"));\n        random=(Random)(c.newInstance());\n      }\n      catch(Exception e){ \n        throw new JSchException(e.toString(), e);\n      }\n    }\n    Packet.setRandom(random);\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"Connecting to \"+host+\" port \"+port);\n    }\n\n    try\t{\n      int i, j;\n\n      if(proxy==null){\n        InputStream in;\n        OutputStream out;\n\tif(socket_factory==null){\n          socket=Util.createSocket(host, port, connectTimeout);\n\t  in=socket.getInputStream();\n\t  out=socket.getOutputStream();\n\t}\n\telse{\n          socket=socket_factory.createSocket(host, port);\n\t  in=socket_factory.getInputStream(socket);\n\t  out=socket_factory.getOutputStream(socket);\n\t}\n\t//if(timeout>0){ socket.setSoTimeout(timeout); }\n        socket.setTcpNoDelay(true);\n        io.setInputStream(in);\n        io.setOutputStream(out);\n      }\n      else{\n\tsynchronized(proxy){\n          proxy.connect(socket_factory, host, port, connectTimeout);\n\t  io.setInputStream(proxy.getInputStream());\n\t  io.setOutputStream(proxy.getOutputStream());\n          socket=proxy.getSocket();\n\t}\n      }\n\n      if(connectTimeout>0 && socket!=null){\n        socket.setSoTimeout(connectTimeout);\n      }\n\n      isConnected=true;\n\n      if(JSch.getLogger().isEnabled(Logger.INFO)){\n        JSch.getLogger().log(Logger.INFO, \n                             \"Connection established\");\n      }\n\n      jsch.addSession(this);\n\n      {\n\t// Some Cisco devices will miss to read '\\n' if it is sent separately.\n\tbyte[] foo=new byte[V_C.length+1];\n\tSystem.arraycopy(V_C, 0, foo, 0, V_C.length);\n\tfoo[foo.length-1]=(byte)'\\n';\n\tio.put(foo, 0, foo.length);\n      }\n\n      while(true){\n        i=0;\n        j=0;\n        while(i<buf.buffer.length){\n          j=io.getByte();\n          if(j<0)break;\n          buf.buffer[i]=(byte)j; i++; \n          if(j==10)break;\n        }\n        if(j<0){\n          throw new JSchException(\"connection is closed by foreign host\");\n        }\n\n        if(buf.buffer[i-1]==10){    // 0x0a\n          i--;\n          if(i>0 && buf.buffer[i-1]==13){  // 0x0d\n            i--;\n          }\n        }\n\n        if(i<=3 || \n           ((i!=buf.buffer.length) &&\n            (buf.buffer[0]!='S'||buf.buffer[1]!='S'||\n             buf.buffer[2]!='H'||buf.buffer[3]!='-'))){\n          // It must not start with 'SSH-'\n          //System.err.println(new String(buf.buffer, 0, i);\n          continue;\n        }\n\n        if(i==buf.buffer.length ||\n           i<7 ||                                      // SSH-1.99 or SSH-2.0\n           (buf.buffer[4]=='1' && buf.buffer[6]!='9')  // SSH-1.5\n           ){\n          throw new JSchException(\"invalid server's version string\");\n        }\n        break;\n      }\n\n      V_S=new byte[i]; System.arraycopy(buf.buffer, 0, V_S, 0, i);\n      //System.err.println(\"V_S: (\"+i+\") [\"+new String(V_S)+\"]\");\n\n      if(JSch.getLogger().isEnabled(Logger.INFO)){\n        JSch.getLogger().log(Logger.INFO, \n                             \"Remote version string: \"+Util.byte2str(V_S));\n        JSch.getLogger().log(Logger.INFO, \n                             \"Local version string: \"+Util.byte2str(V_C));\n      }\n\n      send_kexinit();\n\n      buf=read(buf);\n      if(buf.getCommand()!=SSH_MSG_KEXINIT){\n        in_kex=false;\n\tthrow new JSchException(\"invalid protocol: \"+buf.getCommand());\n      }\n\n      if(JSch.getLogger().isEnabled(Logger.INFO)){\n        JSch.getLogger().log(Logger.INFO, \n                             \"SSH_MSG_KEXINIT received\");\n      }\n\n      KeyExchange kex=receive_kexinit(buf);\n\n      while(true){\n\tbuf=read(buf);\n\tif(kex.getState()==buf.getCommand()){\n          kex_start_time=System.currentTimeMillis();\n          boolean result=kex.next(buf);\n\t  if(!result){\n\t    //System.err.println(\"verify: \"+result);\n            in_kex=false;\n\t    throw new JSchException(\"verify: \"+result);\n\t  }\n\t}\n\telse{\n          in_kex=false;\n\t  throw new JSchException(\"invalid protocol(kex): \"+buf.getCommand());\n\t}\n\tif(kex.getState()==KeyExchange.STATE_END){\n\t  break;\n\t}\n      }\n\n      try{ checkHost(host, port, kex); }\n      catch(JSchException ee){\n        in_kex=false;\n        throw ee;\n      }\n\n      send_newkeys();\n\n      // receive SSH_MSG_NEWKEYS(21)\n      buf=read(buf);\n      //System.err.println(\"read: 21 ? \"+buf.getCommand());\n      if(buf.getCommand()==SSH_MSG_NEWKEYS){\n\n        if(JSch.getLogger().isEnabled(Logger.INFO)){\n          JSch.getLogger().log(Logger.INFO, \n                               \"SSH_MSG_NEWKEYS received\");\n        }\n\n\treceive_newkeys(buf, kex);\n      }\n      else{\n        in_kex=false;\n\tthrow new JSchException(\"invalid protocol(newkyes): \"+buf.getCommand());\n      }\n\n      try{\n        String s = getConfig(\"MaxAuthTries\");\n        if(s!=null){\n          max_auth_tries = Integer.parseInt(s);\n        }\n      }\n      catch(NumberFormatException e){\n        throw new JSchException(\"MaxAuthTries: \"+getConfig(\"MaxAuthTries\"), e);\n      }\n\n      boolean auth=false;\n      boolean auth_cancel=false;\n\n      UserAuth ua=null;\n      try{\n\tClass c=Class.forName(getConfig(\"userauth.none\"));\n        ua=(UserAuth)(c.newInstance());\n      }\n      catch(Exception e){ \n        throw new JSchException(e.toString(), e);\n      }\n\n      auth=ua.start(this);\n\n      String cmethods=getConfig(\"PreferredAuthentications\");\n\n      String[] cmethoda=Util.split(cmethods, \",\");\n\n      String smethods=null;\n      if(!auth){\n        smethods=((UserAuthNone)ua).getMethods();\n        if(smethods!=null){\n          smethods=smethods.toLowerCase();\n        }\n        else{\n          // methods: publickey,password,keyboard-interactive\n          //smethods=\"publickey,password,keyboard-interactive\";\n          smethods=cmethods;\n        }\n      }\n\n      String[] smethoda=Util.split(smethods, \",\");\n\n      int methodi=0;\n\n      loop:\n      while(true){\n\n\twhile(!auth && \n\t      cmethoda!=null && methodi<cmethoda.length){\n\n          String method=cmethoda[methodi++];\n          boolean acceptable=false;\n          for(int k=0; k<smethoda.length; k++){\n            if(smethoda[k].equals(method)){\n              acceptable=true;\n              break;\n            }\n          }\n          if(!acceptable){\n            continue;\n          }\n\n          //System.err.println(\"  method: \"+method);\n\n          if(JSch.getLogger().isEnabled(Logger.INFO)){\n            String str=\"Authentications that can continue: \";\n            for(int k=methodi-1; k<cmethoda.length; k++){\n              str+=cmethoda[k];\n              if(k+1<cmethoda.length)\n                str+=\",\";\n            }\n            JSch.getLogger().log(Logger.INFO, \n                                 str);\n            JSch.getLogger().log(Logger.INFO, \n                                 \"Next authentication method: \"+method);\n          }\n\n\t  ua=null;\n          try{\n            Class c=null;\n            if(getConfig(\"userauth.\"+method)!=null){\n              c=Class.forName(getConfig(\"userauth.\"+method));\n              ua=(UserAuth)(c.newInstance());\n            }\n          }\n          catch(Exception e){\n            if(JSch.getLogger().isEnabled(Logger.WARN)){\n              JSch.getLogger().log(Logger.WARN, \n                                   \"failed to load \"+method+\" method\");\n            }\n          }\n\n\t  if(ua!=null){\n            auth_cancel=false;\n\t    try{ \n\t      auth=ua.start(this); \n              if(auth && \n                 JSch.getLogger().isEnabled(Logger.INFO)){\n                JSch.getLogger().log(Logger.INFO, \n                                     \"Authentication succeeded (\"+method+\").\");\n              }\n\t    }\n\t    catch(JSchAuthCancelException ee){\n\t      auth_cancel=true;\n\t    }\n\t    catch(JSchPartialAuthException ee){\n              String tmp = smethods;\n              smethods=ee.getMethods();\n              smethoda=Util.split(smethods, \",\");\n              if(!tmp.equals(smethods)){\n                methodi=0;\n              }\n\t      //System.err.println(\"PartialAuth: \"+methods);\n\t      auth_cancel=false;\n\t      continue loop;\n\t    }\n\t    catch(RuntimeException ee){\n\t      throw ee;\n\t    }\n\t    catch(JSchException ee){\n              throw ee;\n\t    }\n\t    catch(Exception ee){\n\t      //System.err.println(\"ee: \"+ee); // SSH_MSG_DISCONNECT: 2 Too many authentication failures\n              if(JSch.getLogger().isEnabled(Logger.WARN)){\n                JSch.getLogger().log(Logger.WARN, \n                                     \"an exception during authentication\\n\"+ee.toString());\n              }\n              break loop;\n\t    }\n\t  }\n\t}\n        break;\n      }\n\n      if(!auth){\n        if(auth_failures >= max_auth_tries){\n          if(JSch.getLogger().isEnabled(Logger.INFO)){\n            JSch.getLogger().log(Logger.INFO, \n                                 \"Login trials exceeds \"+max_auth_tries);\n          }\n        }\n        if(auth_cancel)\n          throw new JSchException(\"Auth cancel\");\n        throw new JSchException(\"Auth fail\");\n      }\n\n      if(socket!=null && (connectTimeout>0 || timeout>0)){\n        socket.setSoTimeout(timeout);\n      }\n\n      isAuthed=true;\n\n      synchronized(lock){\n        if(isConnected){\n          connectThread=new Thread(this);\n          connectThread.setName(\"Connect thread \"+host+\" session\");\n          if(daemon_thread){\n            connectThread.setDaemon(daemon_thread);\n          }\n          connectThread.start();\n\n          requestPortForwarding();\n        }\n        else{\n          // The session has been already down and\n          // we don't have to start new thread.\n        }\n      }\n    }\n    catch(Exception e) {\n      in_kex=false;\n      try{\n        if(isConnected){\n          String message = e.toString();\n          packet.reset();\n          buf.checkFreeSize(1+4*3+message.length()+2+buffer_margin);\n          buf.putByte((byte)SSH_MSG_DISCONNECT);\n          buf.putInt(3);\n          buf.putString(Util.str2byte(message));\n          buf.putString(Util.str2byte(\"en\"));\n          write(packet);\n        }\n      }\n      catch(Exception ee){}\n      try{ disconnect(); } catch(Exception ee){ }\n      isConnected=false;\n      //e.printStackTrace();\n      if(e instanceof RuntimeException) throw (RuntimeException)e;\n      if(e instanceof JSchException) throw (JSchException)e;\n      throw new JSchException(\"Session.connect: \"+e);\n    }\n    finally{\n      Util.bzero(this.password);\n      this.password=null;\n    }\n  }\n\n  private KeyExchange receive_kexinit(Buffer buf) throws Exception {\n    int j=buf.getInt();\n    if(j!=buf.getLength()){    // packet was compressed and\n      buf.getByte();           // j is the size of deflated packet.\n      I_S=new byte[buf.index-5];\n    }\n    else{\n      I_S=new byte[j-1-buf.getByte()];\n    }\n   System.arraycopy(buf.buffer, buf.s, I_S, 0, I_S.length);\n\n   if(!in_kex){     // We are in rekeying activated by the remote!\n     send_kexinit();\n   }\n\n    guess=KeyExchange.guess(I_S, I_C);\n    if(guess==null){\n      throw new JSchException(\"Algorithm negotiation fail\");\n    }\n\n    if(!isAuthed &&\n       (guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS].equals(\"none\") ||\n        (guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC].equals(\"none\")))){\n      throw new JSchException(\"NONE Cipher should not be chosen before authentification is successed.\");\n    }\n\n    KeyExchange kex=null;\n    try{\n      Class c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_KEX_ALGS]));\n      kex=(KeyExchange)(c.newInstance());\n    }\n    catch(Exception e){ \n      throw new JSchException(e.toString(), e);\n    }\n\n    kex.init(this, V_S, V_C, I_S, I_C);\n    return kex;\n  }\n\n  private volatile boolean in_kex=false;\n  public void rekey() throws Exception {\n    send_kexinit();\n  }\n  private void send_kexinit() throws Exception {\n    if(in_kex)\n      return;\n\n    String cipherc2s=getConfig(\"cipher.c2s\");\n    String ciphers2c=getConfig(\"cipher.s2c\");\n\n    String[] not_available_ciphers=checkCiphers(getConfig(\"CheckCiphers\"));\n    if(not_available_ciphers!=null && not_available_ciphers.length>0){\n      cipherc2s=Util.diffString(cipherc2s, not_available_ciphers);\n      ciphers2c=Util.diffString(ciphers2c, not_available_ciphers);\n      if(cipherc2s==null || ciphers2c==null){\n        throw new JSchException(\"There are not any available ciphers.\");\n      }\n    }\n\n    String kex=getConfig(\"kex\");\n    String[] not_available_kexes=checkKexes(getConfig(\"CheckKexes\"));\n    if(not_available_kexes!=null && not_available_kexes.length>0){\n      kex=Util.diffString(kex, not_available_kexes);\n      if(kex==null){\n        throw new JSchException(\"There are not any available kexes.\");\n      }\n    }\n\n    String server_host_key = getConfig(\"server_host_key\");\n    String[] not_available_shks =\n      checkSignatures(getConfig(\"CheckSignatures\"));\n    if(not_available_shks!=null && not_available_shks.length>0){\n      server_host_key=Util.diffString(server_host_key, not_available_shks);\n      if(server_host_key==null){\n        throw new JSchException(\"There are not any available sig algorithm.\");\n      }\n    }\n\n    in_kex=true;\n    kex_start_time=System.currentTimeMillis();\n\n    // byte      SSH_MSG_KEXINIT(20)\n    // byte[16]  cookie (random bytes)\n    // string    kex_algorithms\n    // string    server_host_key_algorithms\n    // string    encryption_algorithms_client_to_server\n    // string    encryption_algorithms_server_to_client\n    // string    mac_algorithms_client_to_server\n    // string    mac_algorithms_server_to_client\n    // string    compression_algorithms_client_to_server\n    // string    compression_algorithms_server_to_client\n    // string    languages_client_to_server\n    // string    languages_server_to_client\n    Buffer buf = new Buffer();                // send_kexinit may be invoked\n    Packet packet = new Packet(buf);          // by user thread.\n    packet.reset();\n    buf.putByte((byte) SSH_MSG_KEXINIT);\n    synchronized(random){\n      random.fill(buf.buffer, buf.index, 16); buf.skip(16);\n    }\n    buf.putString(Util.str2byte(kex));\n    buf.putString(Util.str2byte(server_host_key));\n    buf.putString(Util.str2byte(cipherc2s));\n    buf.putString(Util.str2byte(ciphers2c));\n    buf.putString(Util.str2byte(getConfig(\"mac.c2s\")));\n    buf.putString(Util.str2byte(getConfig(\"mac.s2c\")));\n    buf.putString(Util.str2byte(getConfig(\"compression.c2s\")));\n    buf.putString(Util.str2byte(getConfig(\"compression.s2c\")));\n    buf.putString(Util.str2byte(getConfig(\"lang.c2s\")));\n    buf.putString(Util.str2byte(getConfig(\"lang.s2c\")));\n    buf.putByte((byte)0);\n    buf.putInt(0);\n\n    buf.setOffSet(5);\n    I_C=new byte[buf.getLength()];\n    buf.getByte(I_C);\n\n    write(packet);\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"SSH_MSG_KEXINIT sent\");\n    }\n  }\n\n  private void send_newkeys() throws Exception {\n    // send SSH_MSG_NEWKEYS(21)\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_NEWKEYS);\n    write(packet);\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"SSH_MSG_NEWKEYS sent\");\n    }\n  }\n\n  private void checkHost(String chost, int port, KeyExchange kex) throws JSchException {\n    String shkc=getConfig(\"StrictHostKeyChecking\");\n\n    if(hostKeyAlias!=null){\n      chost=hostKeyAlias;\n    }\n\n    //System.err.println(\"shkc: \"+shkc);\n\n    byte[] K_S=kex.getHostKey();\n    String key_type=kex.getKeyType();\n    String key_fprint=kex.getFingerPrint();\n\n    if(hostKeyAlias==null && port!=22){\n      chost=(\"[\"+chost+\"]:\"+port);\n    }\n\n    HostKeyRepository hkr=getHostKeyRepository();\n\n    String hkh=getConfig(\"HashKnownHosts\");\n    if(hkh.equals(\"yes\") && (hkr instanceof KnownHosts)){\n      hostkey=((KnownHosts)hkr).createHashedHostKey(chost, K_S);\n    }\n    else{\n      hostkey=new HostKey(chost, K_S);\n    }\n\n    int i=0;\n    synchronized(hkr){\n      i=hkr.check(chost, K_S);\n    }\n\n    boolean insert=false;\n    if((shkc.equals(\"ask\") || shkc.equals(\"yes\")) &&\n       i==HostKeyRepository.CHANGED){\n      String file=null;\n      synchronized(hkr){\n\tfile=hkr.getKnownHostsRepositoryID();\n      }\n      if(file==null){file=\"known_hosts\";}\n\n      boolean b=false;\n\n      if(userinfo!=null){\n        String message=\n\"WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\\n\"+\n\"IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\\n\"+\n\"Someone could be eavesdropping on you right now (man-in-the-middle attack)!\\n\"+\n\"It is also possible that the \"+key_type+\" host key has just been changed.\\n\"+\n\"The fingerprint for the \"+key_type+\" key sent by the remote host \"+chost+\" is\\n\"+\nkey_fprint+\".\\n\"+\n\"Please contact your system administrator.\\n\"+\n\"Add correct host key in \"+file+\" to get rid of this message.\";\n\n        if(shkc.equals(\"ask\")){\n          b=userinfo.promptYesNo(message+\n                                 \"\\nDo you want to delete the old key and insert the new key?\");\n        }\n        else{  // shkc.equals(\"yes\")\n          userinfo.showMessage(message);\n        }\n      }\n\n      if(!b){\n        throw new JSchException(\"HostKey has been changed: \"+chost);\n      }\n\n      synchronized(hkr){\n        hkr.remove(chost, \n                   kex.getKeyAlgorithName(),\n                   null);\n        insert=true;\n      }\n    }\n\n    if((shkc.equals(\"ask\") || shkc.equals(\"yes\")) &&\n       (i!=HostKeyRepository.OK) && !insert){\n      if(shkc.equals(\"yes\")){\n\tthrow new JSchException(\"reject HostKey: \"+host);\n      }\n      //System.err.println(\"finger-print: \"+key_fprint);\n      if(userinfo!=null){\n\tboolean foo=userinfo.promptYesNo(\n\"The authenticity of host '\"+host+\"' can't be established.\\n\"+\nkey_type+\" key fingerprint is \"+key_fprint+\".\\n\"+\n\"Are you sure you want to continue connecting?\"\n\t\t\t\t\t );\n\tif(!foo){\n\t  throw new JSchException(\"reject HostKey: \"+host);\n\t}\n\tinsert=true;\n      }\n      else{\n\tif(i==HostKeyRepository.NOT_INCLUDED) \n\t  throw new JSchException(\"UnknownHostKey: \"+host+\". \"+key_type+\" key fingerprint is \"+key_fprint);\n\telse \n          throw new JSchException(\"HostKey has been changed: \"+host);\n      }\n    }\n\n    if(shkc.equals(\"no\") && \n       HostKeyRepository.NOT_INCLUDED==i){\n      insert=true;\n    }\n\n    if(i==HostKeyRepository.OK){\n      HostKey[] keys =\n        hkr.getHostKey(chost, kex.getKeyAlgorithName());\n      String _key= Util.byte2str(Util.toBase64(K_S, 0, K_S.length));\n      for(int j=0; j< keys.length; j++){\n        if(keys[i].getKey().equals(_key) &&\n           keys[j].getMarker().equals(\"@revoked\")){\n          if(userinfo!=null){\n            userinfo.showMessage(\n\"The \"+ key_type +\" host key for \"+ host +\" is marked as revoked.\\n\"+\n\"This could mean that a stolen key is being used to \"+\n\"impersonate this host.\");\n          }\n          if(JSch.getLogger().isEnabled(Logger.INFO)){\n            JSch.getLogger().log(Logger.INFO, \n                                 \"Host '\"+host+\"' has provided revoked key.\");\n          }\n          throw new JSchException(\"revoked HostKey: \"+host);\n        }\n      }\n    }\n\n    if(i==HostKeyRepository.OK &&\n       JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"Host '\"+host+\"' is known and matches the \"+key_type+\" host key\");\n    }\n\n    if(insert &&\n       JSch.getLogger().isEnabled(Logger.WARN)){\n      JSch.getLogger().log(Logger.WARN, \n                           \"Permanently added '\"+host+\"' (\"+key_type+\") to the list of known hosts.\");\n    }\n\n    if(insert){\n      synchronized(hkr){\n\thkr.add(hostkey, userinfo);\n      }\n    }\n  }\n\n//public void start(){ (new Thread(this)).start();  }\n\n  public Channel openChannel(String type) throws JSchException{\n    if(!isConnected){\n      throw new JSchException(\"session is down\");\n    }\n    try{\n      Channel channel=Channel.getChannel(type);\n      addChannel(channel);\n      channel.init();\n      if(channel instanceof ChannelSession){\n        applyConfigChannel((ChannelSession)channel);\n      }\n      return channel;\n    }\n    catch(Exception e){\n      //e.printStackTrace();\n    }\n    return null;\n  }\n\n  // encode will bin invoked in write with synchronization.\n  public void encode(Packet packet) throws Exception{\n//System.err.println(\"encode: \"+packet.buffer.getCommand());\n//System.err.println(\"        \"+packet.buffer.index);\n//if(packet.buffer.getCommand()==96){\n//Thread.dumpStack();\n//}\n    if(deflater!=null){\n      compress_len[0]=packet.buffer.index;\n      packet.buffer.buffer=deflater.compress(packet.buffer.buffer, \n                                             5, compress_len);\n      packet.buffer.index=compress_len[0];\n    }\n    if(c2scipher!=null){\n      //packet.padding(c2scipher.getIVSize());\n      packet.padding(c2scipher_size);\n      int pad=packet.buffer.buffer[4];\n      synchronized(random){\n\trandom.fill(packet.buffer.buffer, packet.buffer.index-pad, pad);\n      }\n    }\n    else{\n      packet.padding(8);\n    }\n\n    if(c2smac!=null){\n      c2smac.update(seqo);\n      c2smac.update(packet.buffer.buffer, 0, packet.buffer.index);\n      c2smac.doFinal(packet.buffer.buffer, packet.buffer.index);\n    }\n    if(c2scipher!=null){\n      byte[] buf=packet.buffer.buffer;\n      c2scipher.update(buf, 0, packet.buffer.index, buf, 0);\n    }\n    if(c2smac!=null){\n      packet.buffer.skip(c2smac.getBlockSize());\n    }\n  }\n\n  int[] uncompress_len=new int[1];\n  int[] compress_len=new int[1];\n\n  private int s2ccipher_size=8;\n  private int c2scipher_size=8;\n  public Buffer read(Buffer buf) throws Exception{\n    int j=0;\n    while(true){\n      buf.reset();\n      io.getByte(buf.buffer, buf.index, s2ccipher_size); \n      buf.index+=s2ccipher_size;\n      if(s2ccipher!=null){\n        s2ccipher.update(buf.buffer, 0, s2ccipher_size, buf.buffer, 0);\n      }\n      j=((buf.buffer[0]<<24)&0xff000000)|\n        ((buf.buffer[1]<<16)&0x00ff0000)|\n        ((buf.buffer[2]<< 8)&0x0000ff00)|\n        ((buf.buffer[3]    )&0x000000ff);\n      // RFC 4253 6.1. Maximum Packet Length\n      if(j<5 || j>PACKET_MAX_SIZE){\n        start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE);\n      }\n      int need = j+4-s2ccipher_size;\n      //if(need<0){\n      //  throw new IOException(\"invalid data\");\n      //}\n      if((buf.index+need)>buf.buffer.length){\n        byte[] foo=new byte[buf.index+need];\n        System.arraycopy(buf.buffer, 0, foo, 0, buf.index);\n        buf.buffer=foo;\n      }\n\n      if((need%s2ccipher_size)!=0){\n        String message=\"Bad packet length \"+need;\n        if(JSch.getLogger().isEnabled(Logger.FATAL)){\n          JSch.getLogger().log(Logger.FATAL, message); \n        }\n        start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE-s2ccipher_size);\n      }\n\n      if(need>0){\n\tio.getByte(buf.buffer, buf.index, need); buf.index+=(need);\n\tif(s2ccipher!=null){\n\t  s2ccipher.update(buf.buffer, s2ccipher_size, need, buf.buffer, s2ccipher_size);\n\t}\n      }\n\n      if(s2cmac!=null){\n\ts2cmac.update(seqi);\n\ts2cmac.update(buf.buffer, 0, buf.index);\n\n        s2cmac.doFinal(s2cmac_result1, 0);\n\tio.getByte(s2cmac_result2, 0, s2cmac_result2.length);\n        if(!java.util.Arrays.equals(s2cmac_result1, s2cmac_result2)){\n          if(need > PACKET_MAX_SIZE){\n            throw new IOException(\"MAC Error\");\n          }\n          start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE-need);\n          continue;\n\t}\n      }\n\n      seqi++;\n\n      if(inflater!=null){\n        //inflater.uncompress(buf);\n\tint pad=buf.buffer[4];\n\tuncompress_len[0]=buf.index-5-pad;\n\tbyte[] foo=inflater.uncompress(buf.buffer, 5, uncompress_len);\n\tif(foo!=null){\n\t  buf.buffer=foo;\n\t  buf.index=5+uncompress_len[0];\n\t}\n\telse{\n\t  System.err.println(\"fail in inflater\");\n\t  break;\n\t}\n      }\n\n      int type=buf.getCommand()&0xff;\n      //System.err.println(\"read: \"+type);\n      if(type==SSH_MSG_DISCONNECT){\n        buf.rewind();\n        buf.getInt();buf.getShort();\n\tint reason_code=buf.getInt();\n\tbyte[] description=buf.getString();\n\tbyte[] language_tag=buf.getString();\n\tthrow new JSchException(\"SSH_MSG_DISCONNECT: \"+\n\t\t\t\t    reason_code+\n\t\t\t\t\" \"+Util.byte2str(description)+\n\t\t\t\t\" \"+Util.byte2str(language_tag));\n\t//break;\n      }\n      else if(type==SSH_MSG_IGNORE){\n      }\n      else if(type==SSH_MSG_UNIMPLEMENTED){\n        buf.rewind();\n        buf.getInt();buf.getShort();\n\tint reason_id=buf.getInt();\n        if(JSch.getLogger().isEnabled(Logger.INFO)){\n          JSch.getLogger().log(Logger.INFO, \n                               \"Received SSH_MSG_UNIMPLEMENTED for \"+reason_id);\n        }\n      }\n      else if(type==SSH_MSG_DEBUG){\n        buf.rewind();\n        buf.getInt();buf.getShort();\n/*\n\tbyte always_display=(byte)buf.getByte();\n\tbyte[] message=buf.getString();\n\tbyte[] language_tag=buf.getString();\n\tSystem.err.println(\"SSH_MSG_DEBUG:\"+\n\t\t\t   \" \"+Util.byte2str(message)+\n\t\t\t   \" \"+Util.byte2str(language_tag));\n*/\n      }\n      else if(type==SSH_MSG_CHANNEL_WINDOW_ADJUST){\n          buf.rewind();\n          buf.getInt();buf.getShort();\n\t  Channel c=Channel.getChannel(buf.getInt(), this);\n\t  if(c==null){\n\t  }\n\t  else{\n\t    c.addRemoteWindowSize(buf.getUInt()); \n\t  }\n      }\n      else if(type==UserAuth.SSH_MSG_USERAUTH_SUCCESS){\n        isAuthed=true;\n        if(inflater==null && deflater==null){\n          String method;\n          method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS];\n          initDeflater(method);\n          method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC];\n          initInflater(method);\n        }\n        break;\n      }\n      else{\n        break;\n      }\n    }\n    buf.rewind();\n    return buf;\n  }\n\n  private void start_discard(Buffer buf, Cipher cipher, MAC mac, \n                             int packet_length, int discard) throws JSchException, IOException{\n    MAC discard_mac = null;\n\n    if(!cipher.isCBC()){\n      throw new JSchException(\"Packet corrupt\");\n    }\n\n    if(packet_length!=PACKET_MAX_SIZE && mac != null){\n      discard_mac = mac;\n    }\n\n    discard -= buf.index;\n\n    while(discard>0){\n      buf.reset();\n      int len = discard>buf.buffer.length ? buf.buffer.length : discard;\n      io.getByte(buf.buffer, 0, len);\n      if(discard_mac!=null){\n        discard_mac.update(buf.buffer, 0, len);\n      }\n      discard -= len;\n    }\n\n    if(discard_mac!=null){\n      discard_mac.doFinal(buf.buffer, 0);\n    }\n\n    throw new JSchException(\"Packet corrupt\");\n  }\n\n  byte[] getSessionId(){\n    return session_id;\n  }\n\n  private void receive_newkeys(Buffer buf, KeyExchange kex) throws Exception {\n    updateKeys(kex);\n    in_kex=false;\n  }\n  private void updateKeys(KeyExchange kex) throws Exception{\n    byte[] K=kex.getK();\n    byte[] H=kex.getH();\n    HASH hash=kex.getHash();\n\n    if(session_id==null){\n      session_id=new byte[H.length];\n      System.arraycopy(H, 0, session_id, 0, H.length);\n    }\n\n    /*\n      Initial IV client to server:     HASH (K || H || \"A\" || session_id)\n      Initial IV server to client:     HASH (K || H || \"B\" || session_id)\n      Encryption key client to server: HASH (K || H || \"C\" || session_id)\n      Encryption key server to client: HASH (K || H || \"D\" || session_id)\n      Integrity key client to server:  HASH (K || H || \"E\" || session_id)\n      Integrity key server to client:  HASH (K || H || \"F\" || session_id)\n    */\n\n    buf.reset();\n    buf.putMPInt(K);\n    buf.putByte(H);\n    buf.putByte((byte)0x41);\n    buf.putByte(session_id);\n    hash.update(buf.buffer, 0, buf.index);\n    IVc2s=hash.digest();\n\n    int j=buf.index-session_id.length-1;\n\n    buf.buffer[j]++;\n    hash.update(buf.buffer, 0, buf.index);\n    IVs2c=hash.digest();\n\n    buf.buffer[j]++;\n    hash.update(buf.buffer, 0, buf.index);\n    Ec2s=hash.digest();\n\n    buf.buffer[j]++;\n    hash.update(buf.buffer, 0, buf.index);\n    Es2c=hash.digest();\n\n    buf.buffer[j]++;\n    hash.update(buf.buffer, 0, buf.index);\n    MACc2s=hash.digest();\n\n    buf.buffer[j]++;\n    hash.update(buf.buffer, 0, buf.index);\n    MACs2c=hash.digest();\n\n    try{\n      Class c;\n      String method;\n  \n      method=guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC];\n      c=Class.forName(getConfig(method));\n      s2ccipher=(Cipher)(c.newInstance());\n      while(s2ccipher.getBlockSize()>Es2c.length){\n        buf.reset();\n        buf.putMPInt(K);\n        buf.putByte(H);\n        buf.putByte(Es2c);\n        hash.update(buf.buffer, 0, buf.index);\n        byte[] foo=hash.digest();\n        byte[] bar=new byte[Es2c.length+foo.length];\n\tSystem.arraycopy(Es2c, 0, bar, 0, Es2c.length);\n\tSystem.arraycopy(foo, 0, bar, Es2c.length, foo.length);\n\tEs2c=bar;\n      }\n      s2ccipher.init(Cipher.DECRYPT_MODE, Es2c, IVs2c);\n      s2ccipher_size=s2ccipher.getIVSize();\n\n      method=guess[KeyExchange.PROPOSAL_MAC_ALGS_STOC];\n      c=Class.forName(getConfig(method));\n      s2cmac=(MAC)(c.newInstance());\n      MACs2c = expandKey(buf, K, H, MACs2c, hash, s2cmac.getBlockSize());\n      s2cmac.init(MACs2c);\n      //mac_buf=new byte[s2cmac.getBlockSize()];\n      s2cmac_result1=new byte[s2cmac.getBlockSize()];\n      s2cmac_result2=new byte[s2cmac.getBlockSize()];\n\n      method=guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS];\n      c=Class.forName(getConfig(method));\n      c2scipher=(Cipher)(c.newInstance());\n      while(c2scipher.getBlockSize()>Ec2s.length){\n        buf.reset();\n        buf.putMPInt(K);\n        buf.putByte(H);\n        buf.putByte(Ec2s);\n        hash.update(buf.buffer, 0, buf.index);\n        byte[] foo=hash.digest();\n        byte[] bar=new byte[Ec2s.length+foo.length];\n\tSystem.arraycopy(Ec2s, 0, bar, 0, Ec2s.length);\n\tSystem.arraycopy(foo, 0, bar, Ec2s.length, foo.length);\n\tEc2s=bar;\n      }\n      c2scipher.init(Cipher.ENCRYPT_MODE, Ec2s, IVc2s);\n      c2scipher_size=c2scipher.getIVSize();\n\n      method=guess[KeyExchange.PROPOSAL_MAC_ALGS_CTOS];\n      c=Class.forName(getConfig(method));\n      c2smac=(MAC)(c.newInstance());\n      MACc2s = expandKey(buf, K, H, MACc2s, hash, c2smac.getBlockSize());\n      c2smac.init(MACc2s);\n\n      method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS];\n      initDeflater(method);\n\n      method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC];\n      initInflater(method);\n    }\n    catch(Exception e){ \n      if(e instanceof JSchException)\n        throw e;\n      throw new JSchException(e.toString(), e);\n      //System.err.println(\"updatekeys: \"+e); \n    }\n  }\n\n\n  /*\n   * RFC 4253  7.2. Output from Key Exchange\n   * If the key length needed is longer than the output of the HASH, the\n   * key is extended by computing HASH of the concatenation of K and H and\n   * the entire key so far, and appending the resulting bytes (as many as\n   * HASH generates) to the key.  This process is repeated until enough\n   * key material is available; the key is taken from the beginning of\n   * this value.  In other words:\n   *   K1 = HASH(K || H || X || session_id)   (X is e.g., \"A\")\n   *   K2 = HASH(K || H || K1)\n   *   K3 = HASH(K || H || K1 || K2)\n   *   ...\n   *   key = K1 || K2 || K3 || ...\n   */\n  private byte[] expandKey(Buffer buf, byte[] K, byte[] H, byte[] key,\n                           HASH hash, int required_length) throws Exception {\n    byte[] result = key;\n    int size = hash.getBlockSize();\n    while(result.length < required_length){\n      buf.reset();\n      buf.putMPInt(K);\n      buf.putByte(H);\n      buf.putByte(result);\n      hash.update(buf.buffer, 0, buf.index);\n      byte[] tmp = new byte[result.length+size];\n      System.arraycopy(result, 0, tmp, 0, result.length);\n      System.arraycopy(hash.digest(), 0, tmp, result.length, size);\n      Util.bzero(result);\n      result = tmp;\n    }\n    return result;\n  }\n\n  /*public*/ /*synchronized*/ void write(Packet packet, Channel c, int length) throws Exception{\n    long t = getTimeout();\n    while(true){\n      if(in_kex){\n        if(t>0L && (System.currentTimeMillis()-kex_start_time)>t){\n          throw new JSchException(\"timeout in wating for rekeying process.\");\n        }\n        try{Thread.sleep(10);}\n        catch(java.lang.InterruptedException e){};\n        continue;\n      }\n      synchronized(c){\n\n        if(c.rwsize<length){\n          try{ \n            c.notifyme++;\n            c.wait(100); \n          }\n          catch(java.lang.InterruptedException e){\n          }\n          finally{\n            c.notifyme--;\n          }\n        }\n\n        if(in_kex){\n          continue;\n        }\n\n        if(c.rwsize>=length){\n          c.rwsize-=length;\n          break;\n        }\n\n      }\n      if(c.close || !c.isConnected()){\n\tthrow new IOException(\"channel is broken\");\n      }\n\n      boolean sendit=false;\n      int s=0;\n      byte command=0;\n      int recipient=-1;\n      synchronized(c){\n\tif(c.rwsize>0){\n\t  long len=c.rwsize;\n          if(len>length){\n            len=length;\n          }\n          if(len!=length){\n            s=packet.shift((int)len, \n                           (c2scipher!=null ? c2scipher_size : 8),\n                           (c2smac!=null ? c2smac.getBlockSize() : 0));\n          }\n\t  command=packet.buffer.getCommand();\n\t  recipient=c.getRecipient();\n\t  length-=len;\n\t  c.rwsize-=len;\n\t  sendit=true;\n\t}\n      }\n      if(sendit){\n\t_write(packet);\n        if(length==0){\n          return;\n        }\n\tpacket.unshift(command, recipient, s, length);\n      }\n\n      synchronized(c){\n        if(in_kex){\n          continue;\n        }\n        if(c.rwsize>=length){\n          c.rwsize-=length;\n          break;\n        }\n\n        //try{ \n        //System.out.println(\"1wait: \"+c.rwsize);\n        //  c.notifyme++;\n        //  c.wait(100); \n        //}\n        //catch(java.lang.InterruptedException e){\n        //}\n        //finally{\n        //  c.notifyme--;\n        //}\n      }\n    }\n    _write(packet);\n  }\n\n  public void write(Packet packet) throws Exception{\n    // System.err.println(\"in_kex=\"+in_kex+\" \"+(packet.buffer.getCommand()));\n    long t = getTimeout();\n    while(in_kex){\n      if(t>0L && (System.currentTimeMillis()-kex_start_time)>t){\n        throw new JSchException(\"timeout in wating for rekeying process.\");\n      }\n      byte command=packet.buffer.getCommand();\n      //System.err.println(\"command: \"+command);\n      if(command==SSH_MSG_KEXINIT ||\n         command==SSH_MSG_NEWKEYS ||\n         command==SSH_MSG_KEXDH_INIT ||\n         command==SSH_MSG_KEXDH_REPLY ||\n         command==SSH_MSG_KEX_DH_GEX_GROUP ||\n         command==SSH_MSG_KEX_DH_GEX_INIT ||\n         command==SSH_MSG_KEX_DH_GEX_REPLY ||\n         command==SSH_MSG_KEX_DH_GEX_REQUEST ||\n         command==SSH_MSG_DISCONNECT){\n        break;\n      }\n      try{Thread.sleep(10);}\n      catch(java.lang.InterruptedException e){};\n    }\n    _write(packet);\n  }\n\n  private void _write(Packet packet) throws Exception{\n    synchronized(lock){\n      encode(packet);\n      if(io!=null){\n        io.put(packet);\n        seqo++;\n      }\n    }\n  }\n\n  Runnable thread;\n  public void run(){\n    thread=this;\n\n    byte[] foo;\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n    int i=0;\n    Channel channel;\n    int[] start=new int[1];\n    int[] length=new int[1];\n    KeyExchange kex=null;\n\n    int stimeout=0;\n    try{\n      while(isConnected &&\n\t    thread!=null){\n        try{\n          buf=read(buf);\n          stimeout=0;\n        }\n        catch(InterruptedIOException/*SocketTimeoutException*/ ee){\n          if(!in_kex && stimeout<serverAliveCountMax){\n            sendKeepAliveMsg();\n            stimeout++;\n            continue;\n          }\n          else if(in_kex && stimeout<serverAliveCountMax){\n            stimeout++;\n            continue;\n          }\n          throw ee;\n        }\n\n\tint msgType=buf.getCommand()&0xff;\n\n\tif(kex!=null && kex.getState()==msgType){\n          kex_start_time=System.currentTimeMillis();\n\t  boolean result=kex.next(buf);\n\t  if(!result){\n\t    throw new JSchException(\"verify: \"+result);\n\t  }\n\t  continue;\n\t}\n\n        switch(msgType){\n\tcase SSH_MSG_KEXINIT:\n//System.err.println(\"KEXINIT\");\n\t  kex=receive_kexinit(buf);\n\t  break;\n\n\tcase SSH_MSG_NEWKEYS:\n//System.err.println(\"NEWKEYS\");\n          send_newkeys();\n\t  receive_newkeys(buf, kex);\n\t  kex=null;\n\t  break;\n\n\tcase SSH_MSG_CHANNEL_DATA:\n          buf.getInt(); \n          buf.getByte(); \n          buf.getByte(); \n          i=buf.getInt(); \n\t  channel=Channel.getChannel(i, this);\n\t  foo=buf.getString(start, length);\n\t  if(channel==null){\n\t    break;\n\t  }\n\n          if(length[0]==0){\n\t    break;\n          }\n\ntry{\n\t  channel.write(foo, start[0], length[0]);\n}\ncatch(Exception e){\n//System.err.println(e);\n  try{channel.disconnect();}catch(Exception ee){}\nbreak;\n}\n\t  int len=length[0];\n\t  channel.setLocalWindowSize(channel.lwsize-len);\n \t  if(channel.lwsize<channel.lwsize_max/2){\n            packet.reset();\n\t    buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);\n\t    buf.putInt(channel.getRecipient());\n\t    buf.putInt(channel.lwsize_max-channel.lwsize);\n            synchronized(channel){\n              if(!channel.close)\n                write(packet);\n            }\n\t    channel.setLocalWindowSize(channel.lwsize_max);\n\t  }\n\t  break;\n\n        case SSH_MSG_CHANNEL_EXTENDED_DATA:\n          buf.getInt();\n\t  buf.getShort();\n\t  i=buf.getInt();\n\t  channel=Channel.getChannel(i, this);\n\t  buf.getInt();                   // data_type_code == 1\n\t  foo=buf.getString(start, length);\n\t  //System.err.println(\"stderr: \"+new String(foo,start[0],length[0]));\n\t  if(channel==null){\n\t    break;\n\t  }\n\n          if(length[0]==0){\n\t    break;\n          }\n\n\t  channel.write_ext(foo, start[0], length[0]);\n\n\t  len=length[0];\n\t  channel.setLocalWindowSize(channel.lwsize-len);\n \t  if(channel.lwsize<channel.lwsize_max/2){\n            packet.reset();\n\t    buf.putByte((byte)SSH_MSG_CHANNEL_WINDOW_ADJUST);\n\t    buf.putInt(channel.getRecipient());\n\t    buf.putInt(channel.lwsize_max-channel.lwsize);\n            synchronized(channel){\n              if(!channel.close)\n                write(packet);\n            }\n\t    channel.setLocalWindowSize(channel.lwsize_max);\n\t  }\n\t  break;\n\n\tcase SSH_MSG_CHANNEL_WINDOW_ADJUST:\n          buf.getInt(); \n\t  buf.getShort(); \n\t  i=buf.getInt(); \n\t  channel=Channel.getChannel(i, this);\n\t  if(channel==null){\n\t    break;\n\t  }\n\t  channel.addRemoteWindowSize(buf.getUInt()); \n\t  break;\n\n\tcase SSH_MSG_CHANNEL_EOF:\n          buf.getInt(); \n          buf.getShort(); \n          i=buf.getInt(); \n\t  channel=Channel.getChannel(i, this);\n\t  if(channel!=null){\n\t    //channel.eof_remote=true;\n\t    //channel.eof();\n\t    channel.eof_remote();\n\t  }\n\t  /*\n\t  packet.reset();\n\t  buf.putByte((byte)SSH_MSG_CHANNEL_EOF);\n\t  buf.putInt(channel.getRecipient());\n\t  write(packet);\n\t  */\n\t  break;\n\tcase SSH_MSG_CHANNEL_CLOSE:\n          buf.getInt(); \n\t  buf.getShort(); \n\t  i=buf.getInt(); \n\t  channel=Channel.getChannel(i, this);\n\t  if(channel!=null){\n//\t      channel.close();\n\t    channel.disconnect();\n\t  }\n\t  /*\n          if(Channel.pool.size()==0){\n\t    thread=null;\n\t  }\n\t  */\n\t  break;\n\tcase SSH_MSG_CHANNEL_OPEN_CONFIRMATION:\n          buf.getInt(); \n\t  buf.getShort(); \n\t  i=buf.getInt(); \n\t  channel=Channel.getChannel(i, this);\n          int r=buf.getInt();\n          long rws=buf.getUInt();\n          int rps=buf.getInt();\n          if(channel!=null){\n            channel.setRemoteWindowSize(rws);\n            channel.setRemotePacketSize(rps);\n            channel.open_confirmation=true;\n            channel.setRecipient(r);\n          }\n          break;\n\tcase SSH_MSG_CHANNEL_OPEN_FAILURE:\n          buf.getInt(); \n\t  buf.getShort(); \n\t  i=buf.getInt(); \n\t  channel=Channel.getChannel(i, this);\n          if(channel!=null){\n            int reason_code=buf.getInt(); \n            //foo=buf.getString();  // additional textual information\n            //foo=buf.getString();  // language tag \n            channel.setExitStatus(reason_code);\n            channel.close=true;\n            channel.eof_remote=true;\n            channel.setRecipient(0);\n          }\n\t  break;\n\tcase SSH_MSG_CHANNEL_REQUEST:\n          buf.getInt(); \n\t  buf.getShort(); \n\t  i=buf.getInt(); \n\t  foo=buf.getString(); \n          boolean reply=(buf.getByte()!=0);\n\t  channel=Channel.getChannel(i, this);\n\t  if(channel!=null){\n\t    byte reply_type=(byte)SSH_MSG_CHANNEL_FAILURE;\n\t    if((Util.byte2str(foo)).equals(\"exit-status\")){\n\t      i=buf.getInt();             // exit-status\n\t      channel.setExitStatus(i);\n\t      reply_type=(byte)SSH_MSG_CHANNEL_SUCCESS;\n\t    }\n\t    if(reply){\n\t      packet.reset();\n\t      buf.putByte(reply_type);\n\t      buf.putInt(channel.getRecipient());\n\t      write(packet);\n\t    }\n\t  }\n\t  else{\n\t  }\n\t  break;\n\tcase SSH_MSG_CHANNEL_OPEN:\n          buf.getInt(); \n\t  buf.getShort(); \n\t  foo=buf.getString(); \n\t  String ctyp=Util.byte2str(foo);\n          if(!\"forwarded-tcpip\".equals(ctyp) &&\n\t     !(\"x11\".equals(ctyp) && x11_forwarding) &&\n\t     !(\"auth-agent@openssh.com\".equals(ctyp) && agent_forwarding)){\n            //System.err.println(\"Session.run: CHANNEL OPEN \"+ctyp); \n\t    //throw new IOException(\"Session.run: CHANNEL OPEN \"+ctyp);\n\t    packet.reset();\n\t    buf.putByte((byte)SSH_MSG_CHANNEL_OPEN_FAILURE);\n\t    buf.putInt(buf.getInt());\n \t    buf.putInt(Channel.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED);\n\t    buf.putString(Util.empty);\n\t    buf.putString(Util.empty);\n\t    write(packet);\n\t  }\n\t  else{\n\t    channel=Channel.getChannel(ctyp);\n\t    addChannel(channel);\n\t    channel.getData(buf);\n\t    channel.init();\n\n\t    Thread tmp=new Thread(channel);\n\t    tmp.setName(\"Channel \"+ctyp+\" \"+host);\n            if(daemon_thread){\n              tmp.setDaemon(daemon_thread);\n            }\n\t    tmp.start();\n\t  }\n          break;\n\tcase SSH_MSG_CHANNEL_SUCCESS:\n          buf.getInt(); \n\t  buf.getShort(); \n\t  i=buf.getInt(); \n\t  channel=Channel.getChannel(i, this);\n\t  if(channel==null){\n\t    break;\n\t  }\n\t  channel.reply=1;\n\t  break;\n\tcase SSH_MSG_CHANNEL_FAILURE:\n\t  buf.getInt(); \n\t  buf.getShort(); \n\t  i=buf.getInt(); \n\t  channel=Channel.getChannel(i, this);\n\t  if(channel==null){\n\t    break;\n\t  }\n\t  channel.reply=0;\n\t  break;\n\tcase SSH_MSG_GLOBAL_REQUEST:\n\t  buf.getInt(); \n\t  buf.getShort(); \n\t  foo=buf.getString();       // request name\n\t  reply=(buf.getByte()!=0);\n\t  if(reply){\n\t    packet.reset();\n\t    buf.putByte((byte)SSH_MSG_REQUEST_FAILURE);\n\t    write(packet);\n\t  }\n\t  break;\n\tcase SSH_MSG_REQUEST_FAILURE:\n\tcase SSH_MSG_REQUEST_SUCCESS:\n          Thread t=grr.getThread();\n          if(t!=null){\n            grr.setReply(msgType==SSH_MSG_REQUEST_SUCCESS? 1 : 0);\n            if(msgType==SSH_MSG_REQUEST_SUCCESS && grr.getPort()==0){\n              buf.getInt(); \n              buf.getShort(); \n              grr.setPort(buf.getInt());\n            }\n            t.interrupt();\n          }\n\t  break;\n\tdefault:\n          //System.err.println(\"Session.run: unsupported type \"+msgType); \n\t  throw new IOException(\"Unknown SSH message type \"+msgType);\n\t}\n      }\n    }\n    catch(Exception e){\n      in_kex=false;\n      if(JSch.getLogger().isEnabled(Logger.INFO)){\n        JSch.getLogger().log(Logger.INFO,\n                             \"Caught an exception, leaving main loop due to \" + e.getMessage());\n      }\n      //System.err.println(\"# Session.run\");\n      //e.printStackTrace();\n    }\n    try{\n      disconnect();\n    }\n    catch(NullPointerException e){\n      //System.err.println(\"@1\");\n      //e.printStackTrace();\n    }\n    catch(Exception e){\n      //System.err.println(\"@2\");\n      //e.printStackTrace();\n    }\n    isConnected=false;\n  }\n\n  public void disconnect(){\n    if(!isConnected) return;\n    //System.err.println(this+\": disconnect\");\n    //Thread.dumpStack();\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO,\n                           \"Disconnecting from \"+host+\" port \"+port);\n    }\n    /*\n    for(int i=0; i<Channel.pool.size(); i++){\n      try{\n        Channel c=((Channel)(Channel.pool.elementAt(i)));\n\tif(c.session==this) c.eof();\n      }\n      catch(Exception e){\n      }\n    } \n    */\n\n    Channel.disconnect(this);\n\n    isConnected=false;\n\n    PortWatcher.delPort(this);\n    ChannelForwardedTCPIP.delPort(this);\n    ChannelX11.removeFakedCookie(this);\n\n    synchronized(lock){\n      if(connectThread!=null){\n        Thread.yield();\n        connectThread.interrupt();\n        connectThread=null;\n      }\n    }\n    thread=null;\n    try{\n      if(io!=null){\n\tif(io.in!=null) io.in.close();\n\tif(io.out!=null) io.out.close();\n\tif(io.out_ext!=null) io.out_ext.close();\n      }\n      if(proxy==null){\n        if(socket!=null)\n\t  socket.close();\n      }\n      else{\n\tsynchronized(proxy){\n\t  proxy.close();\t  \n\t}\n\tproxy=null;\n      }\n    }\n    catch(Exception e){\n//      e.printStackTrace();\n    }\n    io=null;\n    socket=null;\n//    synchronized(jsch.pool){\n//      jsch.pool.removeElement(this);\n//    }\n\n    jsch.removeSession(this);\n\n    //System.gc();\n  }\n\n  /**\n   * Registers the local port forwarding for loop-back interface.\n   * If <code>lport</code> is <code>0</code>, the tcp port will be allocated.\n   * @param lport local port for local port forwarding \n   * @param host host address for local port forwarding\n   * @param rport remote port number for local port forwarding\n   * @return an allocated local TCP port number\n   * @see #setPortForwardingL(String bind_address, int lport, String host, int rport, ServerSocketFactory ssf, int connectTimeout)\n   */\n  public int setPortForwardingL(int lport, String host, int rport) throws JSchException{\n    return setPortForwardingL(\"127.0.0.1\", lport, host, rport);\n  }\n\n  /**\n   * Registers the local port forwarding.  If <code>bind_address</code> is an empty string\n   * or '*', the port should be available from all interfaces.\n   * If <code>bind_address</code> is <code>\"localhost\"</code> or\n   * <code>null</code>, the listening port will be bound for local use only.\n   * If <code>lport</code> is <code>0</code>, the tcp port will be allocated.\n   * @param bind_address bind address for local port forwarding\n   * @param lport local port for local port forwarding \n   * @param host host address for local port forwarding\n   * @param rport remote port number for local port forwarding\n   * @return an allocated local TCP port number\n   * @see #setPortForwardingL(String bind_address, int lport, String host, int rport, ServerSocketFactory ssf, int connectTimeout)\n   */\n  public int setPortForwardingL(String bind_address, int lport, String host, int rport) throws JSchException{\n    return setPortForwardingL(bind_address, lport, host, rport, null);\n  }\n\n  /**\n   * Registers the local port forwarding.\n   * If <code>bind_address</code> is an empty string or <code>\"*\"</code>,\n   * the port should be available from all interfaces.\n   * If <code>bind_address</code> is <code>\"localhost\"</code> or\n   * <code>null</code>, the listening port will be bound for local use only.\n   * If <code>lport</code> is <code>0</code>, the tcp port will be allocated.\n   * @param bind_address bind address for local port forwarding\n   * @param lport local port for local port forwarding \n   * @param host host address for local port forwarding\n   * @param rport remote port number for local port forwarding\n   * @param ssf socket factory\n   * @return an allocated local TCP port number\n   * @see #setPortForwardingL(String bind_address, int lport, String host, int rport, ServerSocketFactory ssf, int connectTimeout)\n   */\n  public int setPortForwardingL(String bind_address, int lport, String host, int rport, ServerSocketFactory ssf) throws JSchException{\n    return setPortForwardingL(bind_address, lport, host, rport, ssf, 0);\n  }\n\n  /**\n   * Registers the local port forwarding.\n   * If <code>bind_address</code> is an empty string\n   * or <code>\"*\"</code>, the port should be available from all interfaces.\n   * If <code>bind_address</code> is <code>\"localhost\"</code> or\n   * <code>null</code>, the listening port will be bound for local use only.\n   * If <code>lport</code> is <code>0</code>, the tcp port will be allocated.\n   * @param bind_address bind address for local port forwarding\n   * @param lport local port for local port forwarding \n   * @param host host address for local port forwarding\n   * @param rport remote port number for local port forwarding\n   * @param ssf socket factory\n   * @param connectTimeout timeout for establishing port connection\n   * @return an allocated local TCP port number \n   */\n  public int setPortForwardingL(String bind_address, int lport, String host, int rport, ServerSocketFactory ssf, int connectTimeout) throws JSchException{\n    PortWatcher pw=PortWatcher.addPort(this, bind_address, lport, host, rport, ssf);\n    pw.setConnectTimeout(connectTimeout);\n    Thread tmp=new Thread(pw);\n    tmp.setName(\"PortWatcher Thread for \"+host);\n    if(daemon_thread){\n      tmp.setDaemon(daemon_thread);\n    }\n    tmp.start();\n    return pw.lport;\n  }\n\n  /**\n   * Cancels the local port forwarding assigned\n   * at local TCP port <code>lport</code> on loopback interface.\n   *\n   * @param lport local TCP port\n   */\n  public void delPortForwardingL(int lport) throws JSchException{\n    delPortForwardingL(\"127.0.0.1\", lport);\n  }\n\n  /**\n   * Cancels the local port forwarding assigned\n   * at local TCP port <code>lport</code> on <code>bind_address</code> interface.\n   *\n   * @param bind_address bind_address of network interfaces\n   * @param lport local TCP port\n   */\n  public void delPortForwardingL(String bind_address, int lport) throws JSchException{\n    PortWatcher.delPort(this, bind_address, lport);\n  }\n\n  /**\n   * Lists the registered local port forwarding.\n   *\n   * @return a list of \"lport:host:hostport\"\n   */\n  public String[] getPortForwardingL() throws JSchException{\n    return PortWatcher.getPortForwarding(this);\n  }\n\n  /**\n   * Registers the remote port forwarding for the loopback interface\n   * of the remote.\n   *\n   * @param rport remote port\n   * @param host host address\n   * @param lport local port\n   * @see #setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf)\n   */\n  public void setPortForwardingR(int rport, String host, int lport) throws JSchException{\n    setPortForwardingR(null, rport, host, lport, (SocketFactory)null);\n  }\n\n  /**\n   * Registers the remote port forwarding.\n   * If <code>bind_address</code> is an empty string or <code>\"*\"</code>,\n   * the port should be available from all interfaces.\n   * If <code>bind_address</code> is <code>\"localhost\"</code> or is not given,\n   * the listening port will be bound for local use only.\n   * Note that if <code>GatewayPorts</code> is <code>\"no\"</code> on the\n   * remote, <code>\"localhost\"</code> is always used as a bind_address.\n   *\n   * @param bind_address bind address\n   * @param rport remote port\n   * @param host host address\n   * @param lport local port\n   * @see #setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf)\n   */\n  public void setPortForwardingR(String bind_address, int rport, String host, int lport) throws JSchException{\n    setPortForwardingR(bind_address, rport, host, lport, (SocketFactory)null);\n  }\n\n  /**\n   * Registers the remote port forwarding for the loopback interface\n   * of the remote.\n   *\n   * @param rport remote port\n   * @param host host address\n   * @param lport local port\n   * @param sf socket factory\n   * @see #setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf)\n   */\n  public void setPortForwardingR(int rport, String host, int lport, SocketFactory sf) throws JSchException{\n    setPortForwardingR(null, rport, host, lport, sf);\n  }\n\n  // TODO: This method should return the integer value as the assigned port.\n  /**\n   * Registers the remote port forwarding.\n   * If <code>bind_address</code> is an empty string or <code>\"*\"</code>,\n   * the port should be available from all interfaces.\n   * If <code>bind_address</code> is <code>\"localhost\"</code> or is not given,\n   * the listening port will be bound for local use only.\n   * Note that if <code>GatewayPorts</code> is <code>\"no\"</code> on the\n   * remote, <code>\"localhost\"</code> is always used as a bind_address.\n   * If <code>rport</code> is <code>0</code>, the TCP port will be allocated on the remote.\n   *\n   * @param bind_address bind address\n   * @param rport remote port\n   * @param host host address\n   * @param lport local port\n   * @param sf socket factory\n   */\n  public void setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf) throws JSchException{\n    int allocated=_setPortForwardingR(bind_address, rport);\n    ChannelForwardedTCPIP.addPort(this, bind_address,\n                                  rport, allocated, host, lport, sf);\n  }\n\n  /**\n   * Registers the remote port forwarding for the loopback interface\n   * of the remote.\n   * The TCP connection to <code>rport</code> on the remote will be\n   * forwarded to an instance of the class <code>daemon</code>.\n   * The class specified by <code>daemon</code> must implement\n   * <code>ForwardedTCPIPDaemon</code>.\n   *\n   * @param rport remote port\n   * @param daemon class name, which implements \"ForwardedTCPIPDaemon\"\n   * @see #setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg)\n   */\n  public void setPortForwardingR(int rport, String daemon) throws JSchException{\n    setPortForwardingR(null, rport, daemon, null);\n  }\n\n  /**\n   * Registers the remote port forwarding for the loopback interface\n   * of the remote.\n   * The TCP connection to <code>rport</code> on the remote will be\n   * forwarded to an instance of the class <code>daemon</code> with\n   * the argument <code>arg</code>.\n   * The class specified by <code>daemon</code> must implement <code>ForwardedTCPIPDaemon</code>.\n   *\n   * @param rport remote port\n   * @param daemon class name, which implements \"ForwardedTCPIPDaemon\"\n   * @param arg arguments for \"daemon\"\n   * @see #setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg)\n   */\n  public void setPortForwardingR(int rport, String daemon, Object[] arg) throws JSchException{\n    setPortForwardingR(null, rport, daemon, arg);\n  }\n\n  /**\n   * Registers the remote port forwarding.\n   * If <code>bind_address</code> is an empty string\n   * or <code>\"*\"</code>, the port should be available from all interfaces.\n   * If <code>bind_address</code> is <code>\"localhost\"</code> or is not given,\n   * the listening port will be bound for local use only.\n   * Note that if <code>GatewayPorts</code> is <code>\"no\"</code> on the\n   * remote, <code>\"localhost\"</code> is always used as a bind_address.\n   * The TCP connection to <code>rport</code> on the remote will be\n   * forwarded to an instance of the class <code>daemon</code> with the\n   * argument <code>arg</code>. \n   * The class specified by <code>daemon</code> must implement <code>ForwardedTCPIPDaemon</code>.\n   *\n   * @param bind_address bind address\n   * @param rport remote port\n   * @param daemon class name, which implements \"ForwardedTCPIPDaemon\"\n   * @param arg arguments for \"daemon\"\n   * @see #setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg)\n   */\n  public void setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg) throws JSchException{\n    int allocated = _setPortForwardingR(bind_address, rport);\n    ChannelForwardedTCPIP.addPort(this, bind_address,\n                                  rport, allocated, daemon, arg);\n  }\n\n  /**\n   * Lists the registered remote port forwarding.\n   *\n   * @return a list of \"rport:host:hostport\"\n   */\n  public String[] getPortForwardingR() throws JSchException{\n    return ChannelForwardedTCPIP.getPortForwarding(this);\n  }\n\n  private class Forwarding {\n    String bind_address = null;\n    int port = -1;\n    String host = null;\n    int hostport = -1;\n  }\n\n  /**\n   * The given argument may be \"[bind_address:]port:host:hostport\" or\n   * \"[bind_address:]port host:hostport\", which is from LocalForward command of\n   * ~/.ssh/config .\n   */\n  private Forwarding parseForwarding(String conf) throws JSchException {\n    String[] tmp = conf.split(\" \");\n    if(tmp.length>1){   // \"[bind_address:]port host:hostport\"\n      Vector foo = new Vector();\n      for(int i=0; i<tmp.length; i++){\n        if(tmp[i].length()==0) continue;\n        foo.addElement(tmp[i].trim());\n      }\n      StringBuffer sb = new StringBuffer(); // join\n      for(int i=0; i<foo.size(); i++){\n        sb.append((String)(foo.elementAt(i)));\n        if(i+1<foo.size())\n          sb.append(\":\");\n      }\n      conf = sb.toString(); \n    }\n\n    String org = conf;\n    Forwarding f = new Forwarding();\n    try {\n      if(conf.lastIndexOf(\":\") == -1)\n        throw new JSchException (\"parseForwarding: \"+org);\n      f.hostport = Integer.parseInt(conf.substring(conf.lastIndexOf(\":\")+1));\n      conf = conf.substring(0, conf.lastIndexOf(\":\"));\n      if(conf.lastIndexOf(\":\") == -1)\n        throw new JSchException (\"parseForwarding: \"+org);\n      f.host = conf.substring(conf.lastIndexOf(\":\")+1);\n      conf = conf.substring(0, conf.lastIndexOf(\":\"));\n      if(conf.lastIndexOf(\":\") != -1){\n        f.port = Integer.parseInt(conf.substring(conf.lastIndexOf(\":\")+1));\n        conf = conf.substring(0, conf.lastIndexOf(\":\"));\n        if(conf.length() ==0 || conf.equals(\"*\")) conf=\"0.0.0.0\";\n        if(conf.equals(\"localhost\")) conf=\"127.0.0.1\";\n        f.bind_address = conf;\n      }\n      else {\n        f.port = Integer.parseInt(conf);\n        f.bind_address = \"127.0.0.1\";\n      }\n    }\n    catch(NumberFormatException e){\n      throw new JSchException (\"parseForwarding: \"+e.toString());\n    }\n    return f;\n  }\n\n  /**\n   * Registers the local port forwarding.  The argument should be\n   * in the format like \"[bind_address:]port:host:hostport\".\n   * If <code>bind_address</code> is an empty string or <code>\"*\"</code>,\n   * the port should be available from all interfaces.\n   * If <code>bind_address</code> is <code>\"localhost\"</code> or is not given,\n   * the listening port will be bound for local use only.\n   *\n   * @param conf configuration of local port forwarding\n   * @return an assigned port number\n   * @see #setPortForwardingL(String bind_address, int lport, String host, int rport)\n   */\n  public int setPortForwardingL(String conf) throws JSchException {\n    Forwarding f = parseForwarding(conf);\n    return setPortForwardingL(f.bind_address, f.port, f.host, f.hostport);\n  }\n\n  /**\n   * Registers the remote port forwarding.  The argument should be\n   * in the format like \"[bind_address:]port:host:hostport\".  If the \n   * bind_address is not given, the default is to only bind to loopback\n   * addresses.  If the bind_address is <code>\"*\"</code> or an empty string,\n   * then the forwarding is requested to listen on all interfaces.\n   * Note that if <code>GatewayPorts</code> is <code>\"no\"</code> on the remote,\n   * <code>\"localhost\"</code> is always used for bind_address.\n   * If the specified remote is <code>\"0\"</code>,\n   * the TCP port will be allocated on the remote.\n   *\n   * @param conf configuration of remote port forwarding\n   * @return an allocated TCP port on the remote.\n   * @see #setPortForwardingR(String bind_address, int rport, String host, int rport)\n   */\n  public int setPortForwardingR(String conf) throws JSchException {\n    Forwarding f = parseForwarding(conf);\n    int allocated = _setPortForwardingR(f.bind_address, f.port);\n    ChannelForwardedTCPIP.addPort(this, f.bind_address,\n                                  f.port, allocated, f.host, f.hostport, null);\n    return allocated;\n  }\n\n  /**\n   * Instantiates an instance of stream-forwarder to <code>host</code>:<code>port</code>.\n   * Set I/O stream to the given channel, and then invoke Channel#connect() method.\n   *\n   * @param host remote host, which the given stream will be plugged to.\n   * @param port remote port, which the given stream will be plugged to.\n   */\n  public Channel getStreamForwarder(String host, int port) throws JSchException {\n    ChannelDirectTCPIP channel = new ChannelDirectTCPIP();\n    channel.init();\n    this.addChannel(channel);\n    channel.setHost(host);\n    channel.setPort(port);\n    return channel;\n  } \n\n  private class GlobalRequestReply{\n    private Thread thread=null;\n    private int reply=-1;\n    private int port=0;\n    void setThread(Thread thread){\n      this.thread=thread;\n      this.reply=-1;\n    }\n    Thread getThread(){ return thread; }\n    void setReply(int reply){ this.reply=reply; }\n    int getReply(){ return this.reply; }\n    int getPort(){ return this.port; }\n    void setPort(int port){ this.port=port; }\n  }\n  private GlobalRequestReply grr=new GlobalRequestReply();\n  private int _setPortForwardingR(String bind_address, int rport) throws JSchException{\n    synchronized(grr){\n    Buffer buf=new Buffer(100); // ??\n    Packet packet=new Packet(buf);\n\n    String address_to_bind=ChannelForwardedTCPIP.normalize(bind_address);\n\n    grr.setThread(Thread.currentThread());\n    grr.setPort(rport);\n\n    try{\n      // byte SSH_MSG_GLOBAL_REQUEST 80\n      // string \"tcpip-forward\"\n      // boolean want_reply\n      // string  address_to_bind\n      // uint32  port number to bind\n      packet.reset();\n      buf.putByte((byte) SSH_MSG_GLOBAL_REQUEST);\n      buf.putString(Util.str2byte(\"tcpip-forward\"));\n      buf.putByte((byte)1);\n      buf.putString(Util.str2byte(address_to_bind));\n      buf.putInt(rport);\n      write(packet);\n    }\n    catch(Exception e){\n      grr.setThread(null);\n      if(e instanceof Throwable)\n        throw new JSchException(e.toString(), (Throwable)e);\n      throw new JSchException(e.toString());\n    }\n\n    int count = 0;\n    int reply = grr.getReply();\n    while(count < 10 && reply == -1){\n      try{ Thread.sleep(1000); }\n      catch(Exception e){\n      }\n      count++; \n      reply = grr.getReply();\n    }\n    grr.setThread(null);\n    if(reply != 1){\n      throw new JSchException(\"remote port forwarding failed for listen port \"+rport);\n    }\n    rport=grr.getPort();\n    }\n    return rport;\n  }\n\n  /**\n   * Cancels the remote port forwarding assigned at remote TCP port <code>rport</code>.\n   *\n   * @param rport remote TCP port\n   */\n  public void delPortForwardingR(int rport) throws JSchException{\n    this.delPortForwardingR(null, rport);\n  }\n\n  /**\n   * Cancels the remote port forwarding assigned at\n   * remote TCP port <code>rport</code> bound on the interface at\n   * <code>bind_address</code>.\n   *\n   * @param bind_address bind address of the interface on the remote\n   * @param rport remote TCP port\n   */\n  public void delPortForwardingR(String bind_address, int rport) throws JSchException{\n    ChannelForwardedTCPIP.delPort(this, bind_address, rport);\n  }\n\n  private void initDeflater(String method) throws JSchException{\n    if(method.equals(\"none\")){\n      deflater=null;\n      return;\n    }\n    String foo=getConfig(method);\n    if(foo!=null){\n      if(method.equals(\"zlib\") ||\n         (isAuthed && method.equals(\"zlib@openssh.com\"))){\n        try{\n          Class c=Class.forName(foo);\n          deflater=(Compression)(c.newInstance());\n          int level=6;\n          try{ level=Integer.parseInt(getConfig(\"compression_level\"));}\n          catch(Exception ee){ }\n          deflater.init(Compression.DEFLATER, level);\n        }\n        catch(NoClassDefFoundError ee){\n          throw new JSchException(ee.toString(), ee);\n        }\n        catch(Exception ee){\n          throw new JSchException(ee.toString(), ee);\n          //System.err.println(foo+\" isn't accessible.\");\n        }\n      }\n    }\n  }\n  private void initInflater(String method) throws JSchException{\n    if(method.equals(\"none\")){\n      inflater=null;\n      return;\n    }\n    String foo=getConfig(method);\n    if(foo!=null){\n      if(method.equals(\"zlib\") ||\n         (isAuthed && method.equals(\"zlib@openssh.com\"))){\n        try{\n          Class c=Class.forName(foo);\n          inflater=(Compression)(c.newInstance());\n          inflater.init(Compression.INFLATER, 0);\n        }\n        catch(Exception ee){\n          throw new JSchException(ee.toString(), ee);\n\t    //System.err.println(foo+\" isn't accessible.\");\n        }\n      }\n    }\n  }\n\n  void addChannel(Channel channel){\n    channel.setSession(this);\n  }\n\n  public void setProxy(Proxy proxy){ this.proxy=proxy; }\n  public void setHost(String host){ this.host=host; }\n  public void setPort(int port){ this.port=port; }\n  void setUserName(String username){ this.username=username; }\n  public void setUserInfo(UserInfo userinfo){ this.userinfo=userinfo; }\n  public UserInfo getUserInfo(){ return userinfo; }\n  public void setInputStream(InputStream in){ this.in=in; }\n  public void setOutputStream(OutputStream out){ this.out=out; }\n  public void setX11Host(String host){ ChannelX11.setHost(host); }\n  public void setX11Port(int port){ ChannelX11.setPort(port); }\n  public void setX11Cookie(String cookie){ ChannelX11.setCookie(cookie); }\n  public void setPassword(String password){\n    if(password!=null)\n      this.password=Util.str2byte(password);\n  }\n  public void setPassword(byte[] password){ \n    if(password!=null){\n      this.password=new byte[password.length];\n      System.arraycopy(password, 0, this.password, 0, password.length);\n    }\n  }\n\n  public void setConfig(java.util.Properties newconf){\n    setConfig((java.util.Hashtable)newconf);\n  }\n \n  public void setConfig(java.util.Hashtable newconf){\n    synchronized(lock){\n      if(config==null) \n        config=new java.util.Hashtable();\n      for(java.util.Enumeration e=newconf.keys() ; e.hasMoreElements() ;) {\n        String key=(String)(e.nextElement());\n        config.put(key, (String)(newconf.get(key)));\n      }\n    }\n  }\n\n  public void setConfig(String key, String value){\n    synchronized(lock){ \n      if(config==null){\n        config=new java.util.Hashtable();\n      }\n      config.put(key, value);\n    }\n  }\n\n  @SuppressWarnings({\"static\"}) public String getConfig(String key){\n    Object foo=null;\n    if(config!=null){\n      foo=config.get(key);\n      if(foo instanceof String) return (String)foo;\n    }\n    foo=jsch.getConfig(key);\n    if(foo instanceof String) return (String)foo;\n    return null;\n  }\n\n  public void setSocketFactory(SocketFactory sfactory){ \n    socket_factory=sfactory;\n  }\n  public boolean isConnected(){ return isConnected; }\n  public int getTimeout(){ return timeout; }\n  public void setTimeout(int timeout) throws JSchException {\n    if(socket==null){\n      if(timeout<0){\n        throw new JSchException(\"invalid timeout value\");\n      }\n      this.timeout=timeout;\n      return;\n    }\n    try{\n      socket.setSoTimeout(timeout);\n      this.timeout=timeout;\n    }\n    catch(Exception e){\n      if(e instanceof Throwable)\n        throw new JSchException(e.toString(), (Throwable)e);\n      throw new JSchException(e.toString());\n    }\n  }\n  public String getServerVersion(){\n    return Util.byte2str(V_S);\n  }\n  public String getClientVersion(){\n    return Util.byte2str(V_C);\n  }\n  public void setClientVersion(String cv){\n    V_C=Util.str2byte(cv);\n  }\n\n  public void sendIgnore() throws Exception{\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_IGNORE);\n    write(packet);\n  }\n\n  private static final byte[] keepalivemsg=Util.str2byte(\"keepalive@jcraft.com\");\n  public void sendKeepAliveMsg() throws Exception{\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_GLOBAL_REQUEST);\n    buf.putString(keepalivemsg);\n    buf.putByte((byte)1);\n    write(packet);\n  }\n\n  private static final byte[] nomoresessions=Util.str2byte(\"no-more-sessions@openssh.com\");\n  public void noMoreSessionChannels() throws Exception{\n    Buffer buf=new Buffer();\n    Packet packet=new Packet(buf);\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_GLOBAL_REQUEST);\n    buf.putString(nomoresessions);\n    buf.putByte((byte)0);\n    write(packet);\n  }\n  \n  private HostKey hostkey=null;\n  public HostKey getHostKey(){ return hostkey; }\n  public String getHost(){return host;}\n  public String getUserName(){return username;}\n  public int getPort(){return port;}\n  public void setHostKeyAlias(String hostKeyAlias){\n    this.hostKeyAlias=hostKeyAlias;\n  }\n  public String getHostKeyAlias(){\n    return hostKeyAlias;\n  }\n\n  /**\n   * Sets the interval to send a keep-alive message.  If zero is\n   * specified, any keep-alive message must not be sent.  The default interval\n   * is zero.\n   *\n   * @param interval the specified interval, in milliseconds.\n   * @see #getServerAliveInterval()\n   */\n  public void setServerAliveInterval(int interval) throws JSchException {\n    setTimeout(interval);\n    this.serverAliveInterval=interval;\n  }\n\n  /**\n   * Returns setting for the interval to send a keep-alive message.\n   *\n   * @see #setServerAliveInterval(int)\n   */\n  public int getServerAliveInterval(){\n    return this.serverAliveInterval;\n  }\n\n  /**\n   * Sets the number of keep-alive messages which may be sent without\n   * receiving any messages back from the server.  If this threshold is\n   * reached while keep-alive messages are being sent, the connection will\n   * be disconnected.  The default value is one.\n   *\n   * @param count the specified count\n   * @see #getServerAliveCountMax()\n   */\n  public void setServerAliveCountMax(int count){\n    this.serverAliveCountMax=count;\n  }\n\n  /**\n   * Returns setting for the threshold to send keep-alive messages.\n   *\n   * @see #setServerAliveCountMax(int)\n   */\n  public int getServerAliveCountMax(){\n    return this.serverAliveCountMax;\n  }\n\n  public void setDaemonThread(boolean enable){\n    this.daemon_thread=enable;\n  }\n\n  private String[] checkCiphers(String ciphers){\n    if(ciphers==null || ciphers.length()==0)\n      return null;\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"CheckCiphers: \"+ciphers);\n    }\n\n    String cipherc2s=getConfig(\"cipher.c2s\");\n    String ciphers2c=getConfig(\"cipher.s2c\");\n\n    Vector result=new Vector();\n    String[] _ciphers=Util.split(ciphers, \",\");\n    for(int i=0; i<_ciphers.length; i++){\n      String cipher=_ciphers[i];\n      if(ciphers2c.indexOf(cipher) == -1 && cipherc2s.indexOf(cipher) == -1)\n        continue;\n      if(!checkCipher(getConfig(cipher))){\n        result.addElement(cipher);\n      }\n    }\n    if(result.size()==0)\n      return null;\n    String[] foo=new String[result.size()];\n    System.arraycopy(result.toArray(), 0, foo, 0, result.size());\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      for(int i=0; i<foo.length; i++){\n        JSch.getLogger().log(Logger.INFO, \n                             foo[i]+\" is not available.\");\n      }\n    }\n\n    return foo;\n  }\n\n  static boolean checkCipher(String cipher){\n    try{\n      Class c=Class.forName(cipher);\n      Cipher _c=(Cipher)(c.newInstance());\n      _c.init(Cipher.ENCRYPT_MODE,\n              new byte[_c.getBlockSize()],\n              new byte[_c.getIVSize()]);\n      return true;\n    }\n    catch(Exception e){\n      return false;\n    }\n  }\n\n  private String[] checkKexes(String kexes){\n    if(kexes==null || kexes.length()==0)\n      return null;\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"CheckKexes: \"+kexes);\n    }\n\n    java.util.Vector result=new java.util.Vector();\n    String[] _kexes=Util.split(kexes, \",\");\n    for(int i=0; i<_kexes.length; i++){\n      if(!checkKex(this, getConfig(_kexes[i]))){\n        result.addElement(_kexes[i]);\n      }\n    }\n    if(result.size()==0)\n      return null;\n    String[] foo=new String[result.size()];\n    System.arraycopy(result.toArray(), 0, foo, 0, result.size());\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      for(int i=0; i<foo.length; i++){\n        JSch.getLogger().log(Logger.INFO, \n                             foo[i]+\" is not available.\");\n      }\n    }\n\n    return foo;\n  }\n\n  static boolean checkKex(Session s, String kex){\n    try{\n      Class c=Class.forName(kex);\n      KeyExchange _c=(KeyExchange)(c.newInstance());\n      _c.init(s ,null, null, null, null);\n      return true;\n    }\n    catch(Exception e){ return false; }\n  }\n\n  @SuppressWarnings({\"static\"}) private String[] checkSignatures(String sigs){\n    if(sigs==null || sigs.length()==0)\n      return null;\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"CheckSignatures: \"+sigs);\n    }\n\n    java.util.Vector result=new java.util.Vector();\n    String[] _sigs=Util.split(sigs, \",\");\n    for(int i=0; i<_sigs.length; i++){\n      try{      \n        Class c=Class.forName((String)jsch.getConfig(_sigs[i]));\n        final Signature sig=(Signature)(c.newInstance());\n        sig.init();\n      }\n      catch(Exception e){\n        result.addElement(_sigs[i]);\n      }\n   }\n   if(result.size()==0)\n      return null;\n   String[] foo=new String[result.size()];\n    System.arraycopy(result.toArray(), 0, foo, 0, result.size());\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      for(int i=0; i<foo.length; i++){\n        JSch.getLogger().log(Logger.INFO, \n                             foo[i]+\" is not available.\");\n      }\n    }\n    return foo;\n  }\n\n  /**\n   * Sets the identityRepository, which will be referred\n   * in the public key authentication.  The default value is <code>null</code>.\n   *\n   * @param identityRepository \n   * @see #getIdentityRepository()\n   */\n  public void setIdentityRepository(IdentityRepository identityRepository){\n    this.identityRepository = identityRepository;\n  }\n\n  /**\n   * Gets the identityRepository.\n   * If this.identityRepository is <code>null</code>,\n   * JSch#getIdentityRepository() will be invoked.\n   *\n   * @see JSch#getIdentityRepository()\n   */\n  IdentityRepository getIdentityRepository(){\n    if(identityRepository == null)\n      return jsch.getIdentityRepository();\n    return identityRepository;\n  }\n\n  /**\n   * Sets the hostkeyRepository, which will be referred in checking host keys. \n   *\n   * @param hostkeyRepository \n   * @see #getHostKeyRepository()\n   */\n  public void setHostKeyRepository(HostKeyRepository hostkeyRepository){\n    this.hostkeyRepository = hostkeyRepository;\n  }\n\n  /**\n   * Gets the hostkeyRepository.\n   * If this.hostkeyRepository is <code>null</code>,\n   * JSch#getHostKeyRepository() will be invoked.\n   *\n   * @see JSch#getHostKeyRepository()\n   */\n  public HostKeyRepository getHostKeyRepository(){\n    if(hostkeyRepository == null)\n      return jsch.getHostKeyRepository();\n    return hostkeyRepository;\n  }\n\n  /*\n  // setProxyCommand(\"ssh -l user2 host2 -o 'ProxyCommand ssh user1@host1 nc host2 22' nc %h %p\") \n  public void setProxyCommand(String command){\n    setProxy(new ProxyCommand(command));\n  }\n\n  class ProxyCommand implements Proxy {\n    String command;\n    Process p = null;\n    InputStream in = null;\n    OutputStream out = null;\n    ProxyCommand(String command){\n      this.command = command;\n    }\n    public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws Exception {\n      String _command = command.replace(\"%h\", host);\n      _command = _command.replace(\"%p\", new Integer(port).toString());\n      p = Runtime.getRuntime().exec(_command);\n      in = p.getInputStream();\n      out = p.getOutputStream();\n    }\n    public Socket getSocket() { return null; }\n    public InputStream getInputStream() { return in; }\n    public OutputStream getOutputStream() { return out; }\n    public void close() {\n      try{\n        if(p!=null){\n          p.getErrorStream().close();\n          p.getOutputStream().close();\n          p.getInputStream().close();\n          p.destroy();\n          p=null;\n        }\n      }\n      catch(IOException e){\n      }\n    }\n  }\n  */\n\n  private void applyConfig() throws JSchException {\n    ConfigRepository configRepository = jsch.getConfigRepository();\n    if(configRepository == null){\n      return;\n    }\n\n    ConfigRepository.Config config =\n      configRepository.getConfig(org_host);\n\n    String value = null;\n\n    value = config.getUser();\n    if(value != null)\n      username = value;\n\n    value = config.getHostname();\n    if(value != null)\n      host = value;\n\n    int port = config.getPort();\n    if(port != -1)\n      this.port = port;\n\n    checkConfig(config, \"kex\");\n    checkConfig(config, \"server_host_key\");\n\n    checkConfig(config, \"cipher.c2s\");\n    checkConfig(config, \"cipher.s2c\");\n    checkConfig(config, \"mac.c2s\");\n    checkConfig(config, \"mac.s2c\");\n    checkConfig(config, \"compression.c2s\");\n    checkConfig(config, \"compression.s2c\");\n    checkConfig(config, \"compression_level\");\n\n    checkConfig(config, \"StrictHostKeyChecking\");\n    checkConfig(config, \"HashKnownHosts\");\n    checkConfig(config, \"PreferredAuthentications\");\n    checkConfig(config, \"MaxAuthTries\");\n    checkConfig(config, \"ClearAllForwardings\");\n\n    value = config.getValue(\"HostKeyAlias\");\n    if(value != null)\n      this.setHostKeyAlias(value);\n\n    value = config.getValue(\"UserKnownHostsFile\");\n    if(value != null) {\n      KnownHosts kh = new KnownHosts(jsch);\n      kh.setKnownHosts(value);\n      this.setHostKeyRepository(kh);\n    }\n\n    String[] values = config.getValues(\"IdentityFile\");\n    if(values != null) {\n      String[] global =\n        configRepository.getConfig(\"\").getValues(\"IdentityFile\");\n      if(global != null){\n        for(int i = 0; i < global.length; i++){\n          jsch.addIdentity(global[i]);\n        }\n      }\n      else {\n        global = new String[0];\n      }\n      if(values.length - global.length > 0){\n        IdentityRepository.Wrapper ir =\n          new IdentityRepository.Wrapper(jsch.getIdentityRepository(), true);\n        for(int i = 0; i < values.length; i++){\n          String ifile = values[i];\n          for(int j = 0; j < global.length; j++){\n            if(!ifile.equals(global[j]))\n              continue;\n            ifile = null;\n            break;\n          }\n          if(ifile == null)\n            continue;\n          Identity identity =\n            IdentityFile.newInstance(ifile, null, jsch);\n          ir.add(identity);\n        }\n        this.setIdentityRepository(ir);\n      }\n    }\n\n    value = config.getValue(\"ServerAliveInterval\");\n    if(value != null) {\n      try {\n        this.setServerAliveInterval(Integer.parseInt(value));\n      }\n      catch(NumberFormatException e){\n      }\n    }\n\n    value = config.getValue(\"ConnectTimeout\");\n    if(value != null) {\n      try {\n        setTimeout(Integer.parseInt(value));\n      }\n      catch(NumberFormatException e){\n      }\n    }\n\n    value = config.getValue(\"MaxAuthTries\");\n    if(value != null) {\n      setConfig(\"MaxAuthTries\", value);\n    }\n\n    value = config.getValue(\"ClearAllForwardings\");\n    if(value != null) {\n      setConfig(\"ClearAllForwardings\", value);\n    }\n\n  }\n\n  private void applyConfigChannel(ChannelSession channel) throws JSchException {\n    ConfigRepository configRepository = jsch.getConfigRepository();\n    if(configRepository == null){\n      return;\n    }\n\n    ConfigRepository.Config config =\n      configRepository.getConfig(org_host);\n\n    String value = null;\n\n    value = config.getValue(\"ForwardAgent\");\n    if(value != null){\n      channel.setAgentForwarding(value.equals(\"yes\"));\n    }\n\n    value = config.getValue(\"RequestTTY\");\n    if(value != null){\n      channel.setPty(value.equals(\"yes\"));\n    }\n  }\n\n  private void requestPortForwarding() throws JSchException {\n\n    if(getConfig(\"ClearAllForwardings\").equals(\"yes\"))\n      return;\n\n    ConfigRepository configRepository = jsch.getConfigRepository();\n    if(configRepository == null){\n      return;\n    }\n\n    ConfigRepository.Config config =\n      configRepository.getConfig(org_host);\n\n    String[] values = config.getValues(\"LocalForward\");\n    if(values != null){\n      for(int i = 0; i < values.length; i++) {\n        setPortForwardingL(values[i]);\n      }\n    }\n\n    values = config.getValues(\"RemoteForward\");\n    if(values != null){\n      for(int i = 0; i < values.length; i++) {\n        setPortForwardingR(values[i]);\n      }\n    }\n  }\n\n  private void checkConfig(ConfigRepository.Config config, String key){\n    String value = config.getValue(key);\n    if(value != null)\n      this.setConfig(key, value);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/SftpATTRS.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/*\n  uint32   flags\n  uint64   size           present only if flag SSH_FILEXFER_ATTR_SIZE\n  uint32   uid            present only if flag SSH_FILEXFER_ATTR_UIDGID\n  uint32   gid            present only if flag SSH_FILEXFER_ATTR_UIDGID\n  uint32   permissions    present only if flag SSH_FILEXFER_ATTR_PERMISSIONS\n  uint32   atime          present only if flag SSH_FILEXFER_ACMODTIME\n  uint32   mtime          present only if flag SSH_FILEXFER_ACMODTIME\n  uint32   extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED\n  string   extended_type\n  string   extended_data\n    ...      more extended data (extended_type - extended_data pairs),\n             so that number of pairs equals extended_count\n*/\npublic class SftpATTRS {\n\n  static final int S_ISUID = 04000; // set user ID on execution\n  static final int S_ISGID = 02000; // set group ID on execution\n  static final int S_ISVTX = 01000; // sticky bit   ****** NOT DOCUMENTED *****\n\n  static final int S_IRUSR = 00400; // read by owner\n  static final int S_IWUSR = 00200; // write by owner\n  static final int S_IXUSR = 00100; // execute/search by owner\n  static final int S_IREAD = 00400; // read by owner\n  static final int S_IWRITE= 00200; // write by owner\n  static final int S_IEXEC = 00100; // execute/search by owner\n\n  static final int S_IRGRP = 00040; // read by group\n  static final int S_IWGRP = 00020; // write by group\n  static final int S_IXGRP = 00010; // execute/search by group\n\n  static final int S_IROTH = 00004; // read by others\n  static final int S_IWOTH = 00002; // write by others\n  static final int S_IXOTH = 00001; // execute/search by others\n\n  private static final int pmask = 0xFFF;\n\n  public String getPermissionsString() {\n    StringBuffer buf = new StringBuffer(10);\n\n    if(isDir()) buf.append('d');\n    else if(isLink()) buf.append('l');\n    else buf.append('-');\n\n    if((permissions & S_IRUSR)!=0) buf.append('r');\n    else buf.append('-');\n\n    if((permissions & S_IWUSR)!=0) buf.append('w');\n    else buf.append('-');\n\n    if((permissions & S_ISUID)!=0) buf.append('s');\n    else if ((permissions & S_IXUSR)!=0) buf.append('x');\n    else buf.append('-');\n\n    if((permissions & S_IRGRP)!=0) buf.append('r');\n    else buf.append('-');\n\n    if((permissions & S_IWGRP)!=0) buf.append('w');\n    else buf.append('-');\n\n    if((permissions & S_ISGID)!=0) buf.append('s');\n    else if((permissions & S_IXGRP)!=0) buf.append('x');\n    else buf.append('-');\n\n    if((permissions & S_IROTH) != 0) buf.append('r');\n    else buf.append('-');\n\n    if((permissions & S_IWOTH) != 0) buf.append('w');\n    else buf.append('-');\n\n    if((permissions & S_IXOTH) != 0) buf.append('x');\n    else buf.append('-');\n    return (buf.toString());\n  }\n\n  public String  getAtimeString(){\n    Date date= new Date(((long)atime)*1000L);\n    return (date.toString());\n  }\n\n  public String  getMtimeString(){\n    Date date= new Date(((long)mtime)*1000L);\n    return (date.toString());\n  }\n\n  public static final int SSH_FILEXFER_ATTR_SIZE=         0x00000001;\n  public static final int SSH_FILEXFER_ATTR_UIDGID=       0x00000002;\n  public static final int SSH_FILEXFER_ATTR_PERMISSIONS=  0x00000004;\n  public static final int SSH_FILEXFER_ATTR_ACMODTIME=    0x00000008;\n  public static final int SSH_FILEXFER_ATTR_EXTENDED=     0x80000000;\n\n  static final int S_IFMT=0xf000;\n  static final int S_IFIFO=0x1000;\n  static final int S_IFCHR=0x2000;\n  static final int S_IFDIR=0x4000;\n  static final int S_IFBLK=0x6000;\n  static final int S_IFREG=0x8000;\n  static final int S_IFLNK=0xa000;\n  static final int S_IFSOCK=0xc000;\n\n  int flags=0;\n  long size;\n  int uid;\n  int gid;\n  int permissions;\n  int atime;\n  int mtime;\n  String[] extended=null;\n\n  private SftpATTRS(){\n  }\n\n  static SftpATTRS getATTR(Buffer buf){\n    SftpATTRS attr=new SftpATTRS();\t\n    attr.flags=buf.getInt();\n    if((attr.flags&SSH_FILEXFER_ATTR_SIZE)!=0){ attr.size=buf.getLong(); }\n    if((attr.flags&SSH_FILEXFER_ATTR_UIDGID)!=0){\n      attr.uid=buf.getInt(); attr.gid=buf.getInt();\n    }\n    if((attr.flags&SSH_FILEXFER_ATTR_PERMISSIONS)!=0){ \n      attr.permissions=buf.getInt();\n    }\n    if((attr.flags&SSH_FILEXFER_ATTR_ACMODTIME)!=0){ \n      attr.atime=buf.getInt();\n    }\n    if((attr.flags&SSH_FILEXFER_ATTR_ACMODTIME)!=0){ \n      attr.mtime=buf.getInt(); \n    }\n    if((attr.flags&SSH_FILEXFER_ATTR_EXTENDED)!=0){\n      int count=buf.getInt();\n      if(count>0){\n\tattr.extended=new String[count*2];\n\tfor(int i=0; i<count; i++){\n\t  attr.extended[i*2]=Util.byte2str(buf.getString());\n\t  attr.extended[i*2+1]=Util.byte2str(buf.getString());\n\t}\n      }\n    }\n    return attr;\n  } \n\n  int length(){\n    int len=4;\n\n    if((flags&SSH_FILEXFER_ATTR_SIZE)!=0){ len+=8; }\n    if((flags&SSH_FILEXFER_ATTR_UIDGID)!=0){ len+=8; }\n    if((flags&SSH_FILEXFER_ATTR_PERMISSIONS)!=0){ len+=4; }\n    if((flags&SSH_FILEXFER_ATTR_ACMODTIME)!=0){ len+=8; }\n    if((flags&SSH_FILEXFER_ATTR_EXTENDED)!=0){\n      len+=4;\n      int count=extended.length/2;\n      if(count>0){\n\tfor(int i=0; i<count; i++){\n\t  len+=4; len+=extended[i*2].length();\n\t  len+=4; len+=extended[i*2+1].length();\n\t}\n      }\n    }\n    return len;\n  }\n\n  void dump(Buffer buf){\n    buf.putInt(flags);\n    if((flags&SSH_FILEXFER_ATTR_SIZE)!=0){ buf.putLong(size); }\n    if((flags&SSH_FILEXFER_ATTR_UIDGID)!=0){\n      buf.putInt(uid); buf.putInt(gid);\n    }\n    if((flags&SSH_FILEXFER_ATTR_PERMISSIONS)!=0){ \n      buf.putInt(permissions);\n    }\n    if((flags&SSH_FILEXFER_ATTR_ACMODTIME)!=0){ buf.putInt(atime); }\n    if((flags&SSH_FILEXFER_ATTR_ACMODTIME)!=0){ buf.putInt(mtime); }\n    if((flags&SSH_FILEXFER_ATTR_EXTENDED)!=0){\n      int count=extended.length/2;\n      if(count>0){\n\tfor(int i=0; i<count; i++){\n\t  buf.putString(Util.str2byte(extended[i*2]));\n\t  buf.putString(Util.str2byte(extended[i*2+1]));\n\t}\n      }\n    }\n  }\n  void setFLAGS(int flags){\n    this.flags=flags;\n  }\n  public void setSIZE(long size){\n    flags|=SSH_FILEXFER_ATTR_SIZE;\n    this.size=size;\n  }\n  public void setUIDGID(int uid, int gid){\n    flags|=SSH_FILEXFER_ATTR_UIDGID;\n    this.uid=uid;\n    this.gid=gid;\n  }\n  public void setACMODTIME(int atime, int mtime){\n    flags|=SSH_FILEXFER_ATTR_ACMODTIME;\n    this.atime=atime;\n    this.mtime=mtime;\n  }\n  public void setPERMISSIONS(int permissions){\n    flags|=SSH_FILEXFER_ATTR_PERMISSIONS;\n    permissions=(this.permissions&~pmask)|(permissions&pmask);\n    this.permissions=permissions;\n  }\n\n  private boolean isType(int mask) {\n    return (flags&SSH_FILEXFER_ATTR_PERMISSIONS)!=0 &&\n           (permissions&S_IFMT)==mask;\n  }\n\n  public boolean isReg(){\n    return isType(S_IFREG);\n  }\n\n  public boolean isDir(){\n    return isType(S_IFDIR);\n  }      \n\n  public boolean isChr(){\n    return isType(S_IFCHR);\n  }      \n\n  public boolean isBlk(){\n    return isType(S_IFBLK);\n  }      \n\n  public boolean isFifo(){\n    return isType(S_IFIFO);\n  }      \n\n  public boolean isLink(){\n    return isType(S_IFLNK);\n  }\n\n  public boolean isSock(){\n    return isType(S_IFSOCK);\n  }\n\n  public int getFlags() { return flags; }\n  public long getSize() { return size; }\n  public int getUId() { return uid; }\n  public int getGId() { return gid; }\n  public int getPermissions() { return permissions; }\n  public int getATime() { return atime; }\n  public int getMTime() { return mtime; }\n  public String[] getExtended() { return extended; }\n\n  public String toString() {\n    return (getPermissionsString()+\" \"+getUId()+\" \"+getGId()+\" \"+getSize()+\" \"+getMtimeString());\n  }\n  /*\n  public String toString(){\n    return (((flags&SSH_FILEXFER_ATTR_SIZE)!=0) ? (\"size:\"+size+\" \") : \"\")+\n           (((flags&SSH_FILEXFER_ATTR_UIDGID)!=0) ? (\"uid:\"+uid+\",gid:\"+gid+\" \") : \"\")+\n           (((flags&SSH_FILEXFER_ATTR_PERMISSIONS)!=0) ? (\"permissions:0x\"+Integer.toHexString(permissions)+\" \") : \"\")+\n           (((flags&SSH_FILEXFER_ATTR_ACMODTIME)!=0) ? (\"atime:\"+atime+\",mtime:\"+mtime+\" \") : \"\")+\n           (((flags&SSH_FILEXFER_ATTR_EXTENDED)!=0) ? (\"extended:?\"+\" \") : \"\");\n  }\n  */\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/SftpException.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class SftpException extends Exception{\n  //private static final long serialVersionUID=-5616888495583253811L;\n  public int id;\n  private Throwable cause=null;\n  public SftpException (int id, String message) {\n    super(message);\n    this.id=id;\n  }\n  public SftpException (int id, String message, Throwable e) {\n    super(message);\n    this.id=id;\n    this.cause=e;\n  }\n  public String toString(){\n    return id+\": \"+getMessage();\n  }\n  public Throwable getCause(){\n    return this.cause;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/SftpProgressMonitor.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface SftpProgressMonitor{\n  public static final int PUT=0;\n  public static final int GET=1;\n  public static final long UNKNOWN_SIZE = -1L;\n  void init(int op, String src, String dest, long max);\n  boolean count(long count);\n  void end();\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/SftpStatVFS.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\npublic class SftpStatVFS {\n\n  /*\n   It seems data is serializsed according to sys/statvfs.h; for example,\n   http://pubs.opengroup.org/onlinepubs/009604499/basedefs/sys/statvfs.h.html  \n  */\n\n  private long bsize;\n  private long frsize;\n  private long blocks;\n  private long bfree;\n  private long bavail;\n  private long files;\n  private long ffree;\n  private long favail;\n  private long fsid;\n  private long flag;\n  private long namemax;\n\n  int flags=0;\n  long size;\n  int uid;\n  int gid;\n  int permissions;\n  int atime;\n  int mtime;\n  String[] extended=null;\n\n  private SftpStatVFS(){\n  }\n\n  static SftpStatVFS getStatVFS(Buffer buf){\n    SftpStatVFS statvfs=new SftpStatVFS();\n\n    statvfs.bsize = buf.getLong();\n    statvfs.frsize = buf.getLong();\n    statvfs.blocks = buf.getLong();\n    statvfs.bfree = buf.getLong();\n    statvfs.bavail = buf.getLong();\n    statvfs.files = buf.getLong();\n    statvfs.ffree = buf.getLong();\n    statvfs.favail = buf.getLong();\n    statvfs.fsid = buf.getLong();\n    int flag = (int)buf.getLong();\n    statvfs.namemax = buf.getLong();\n\n    statvfs.flag =\n      (flag & 1/*SSH2_FXE_STATVFS_ST_RDONLY*/) != 0 ? 1/*ST_RDONLY*/ : 0;\n    statvfs.flag |=\n      (flag & 2/*SSH2_FXE_STATVFS_ST_NOSUID*/) != 0 ? 2/*ST_NOSUID*/ : 0;\n\n    return statvfs;\n  } \n\n  public long getBlockSize() { return bsize; }\n  public long getFragmentSize() { return frsize; }\n  public long getBlocks() { return blocks; }\n  public long getFreeBlocks() { return bfree; }\n  public long getAvailBlocks() { return bavail; }\n  public long getINodes() { return files; }\n  public long getFreeINodes() { return ffree; }\n  public long getAvailINodes() { return favail; }\n  public long getFileSystemID() { return fsid; }\n  public long getMountFlag() { return flag; }\n  public long getMaximumFilenameLength() { return namemax; }\n\n  public long getSize(){\n    return getFragmentSize()*getBlocks()/1024;\n  }\n\n  public long getUsed(){\n    return getFragmentSize()*(getBlocks()-getFreeBlocks())/1024;\n  }\n\n  public long getAvailForNonRoot(){\n    return getFragmentSize()*getAvailBlocks()/1024;\n  }\n\n  public long getAvail(){\n    return getFragmentSize()*getFreeBlocks()/1024;\n  }\n\n  public int getCapacity(){\n    return (int)(100*(getBlocks()-getFreeBlocks())/getBlocks()); \n  }\n\n//  public String toString() { return \"\"; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/Signature.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2012-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface Signature{\n  void init() throws Exception;\n  void update(byte[] H) throws Exception;\n  boolean verify(byte[] sig) throws Exception;\n  byte[] sign() throws Exception;\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/SignatureDSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface SignatureDSA extends Signature {\n  void setPubKey(byte[] y, byte[] p, byte[] q, byte[] g) throws Exception;\n  void setPrvKey(byte[] x, byte[] p, byte[] q, byte[] g) throws Exception;\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/SignatureECDSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface SignatureECDSA extends Signature {\n  void setPubKey(byte[] r, byte[] s) throws Exception;\n  void setPrvKey(byte[] s) throws Exception;\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/SignatureRSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface SignatureRSA extends Signature {\n  void setPubKey(byte[] e, byte[] n) throws Exception;\n  void setPrvKey(byte[] d, byte[] n) throws Exception;\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/SocketFactory.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.net.*;\nimport java.io.*;\n\npublic interface SocketFactory{\n  public Socket createSocket(String host, int port)throws IOException,\n\t\t\t\t\t\t\t  UnknownHostException;\n  public InputStream getInputStream(Socket socket)throws IOException;\n  public OutputStream getOutputStream(Socket socket)throws IOException;\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/UIKeyboardInteractive.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface UIKeyboardInteractive{\n  String[] promptKeyboardInteractive(String destination,\n\t\t\t\t     String name,\n\t\t\t\t     String instruction,\n\t\t\t\t     String[] prompt,\n\t\t\t\t     boolean[] echo);\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/UserAuth.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic abstract class UserAuth{\n  protected static final int SSH_MSG_USERAUTH_REQUEST=               50;\n  protected static final int SSH_MSG_USERAUTH_FAILURE=               51;\n  protected static final int SSH_MSG_USERAUTH_SUCCESS=               52;\n  protected static final int SSH_MSG_USERAUTH_BANNER=                53;\n  protected static final int SSH_MSG_USERAUTH_INFO_REQUEST=          60;\n  protected static final int SSH_MSG_USERAUTH_INFO_RESPONSE=         61;\n  protected static final int SSH_MSG_USERAUTH_PK_OK=                 60;\n\n  protected UserInfo userinfo;\n  protected Packet packet;\n  protected Buffer buf;\n  protected String username;\n\n  public boolean start(Session session) throws Exception{\n    this.userinfo=session.getUserInfo();\n    this.packet=session.packet;\n    this.buf=packet.getBuffer();\n    this.username=session.getUserName();\n    return true;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/UserAuthGSSAPIWithMIC.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING\nNEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic class UserAuthGSSAPIWithMIC extends UserAuth {\n  private static final int SSH_MSG_USERAUTH_GSSAPI_RESPONSE=         60;\n  private static final int SSH_MSG_USERAUTH_GSSAPI_TOKEN=            61;\n  private static final int SSH_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE=63;\n  private static final int SSH_MSG_USERAUTH_GSSAPI_ERROR=            64;\n  private static final int SSH_MSG_USERAUTH_GSSAPI_ERRTOK=           65;\n  private static final int SSH_MSG_USERAUTH_GSSAPI_MIC=              66;\n\n  private static final byte[][] supported_oid={\n    // OID 1.2.840.113554.1.2.2 in DER\n    {(byte)0x6,(byte)0x9,(byte)0x2a,(byte)0x86,(byte)0x48,\n     (byte)0x86,(byte)0xf7,(byte)0x12,(byte)0x1,(byte)0x2,\n     (byte)0x2}\n  };\n\n  private static final String[] supported_method={\n    \"gssapi-with-mic.krb5\"\n  };\n\n  public boolean start(Session session)throws Exception{\n    super.start(session);\n\n    byte[] _username=Util.str2byte(username);\n\n    packet.reset();\n\n    // byte            SSH_MSG_USERAUTH_REQUEST(50)\n    // string          user name(in ISO-10646 UTF-8 encoding)\n    // string          service name(in US-ASCII)\n    // string          \"gssapi\"(US-ASCII)\n    // uint32          n, the number of OIDs client supports\n    // string[n]       mechanism OIDS\n    buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST);\n    buf.putString(_username);\n    buf.putString(Util.str2byte(\"ssh-connection\"));\n    buf.putString(Util.str2byte(\"gssapi-with-mic\"));\n    buf.putInt(supported_oid.length);\n    for(int i=0; i<supported_oid.length; i++){\n      buf.putString(supported_oid[i]);\n    }\n    session.write(packet);\n\n    String method=null;\n    int command;\n    while(true){\n      buf=session.read(buf);\n      command=buf.getCommand()&0xff;\n\n      if(command==SSH_MSG_USERAUTH_FAILURE){\n        return false;\n      }\n      \n      if(command==SSH_MSG_USERAUTH_GSSAPI_RESPONSE){\n        buf.getInt(); buf.getByte(); buf.getByte();\n        byte[] message=buf.getString();\n\n        for(int i=0; i<supported_oid.length; i++){\n          if(Util.array_equals(message, supported_oid[i])){\n            method=supported_method[i];\n            break;\n          }\n        }\n\n        if(method==null){\n          return false;\n        }\n\n        break; // success\n      }\n\n      if(command==SSH_MSG_USERAUTH_BANNER){\n        buf.getInt(); buf.getByte(); buf.getByte();\n        byte[] _message=buf.getString();\n        byte[] lang=buf.getString();\n        String message=Util.byte2str(_message);\n        if(userinfo!=null){\n          userinfo.showMessage(message);\n        }\n        continue;\n      }\n      return false;\n    }\n\n    GSSContext context=null;\n    try{\n      Class c=Class.forName(session.getConfig(method));\n      context=(GSSContext)(c.newInstance());\n    }\n    catch(Exception e){ \n      return false;\n    }\n\n    try{\n      context.create(username, session.host);\n    }\n    catch(JSchException e){\n      return false;\n    }\n\n    byte[] token=new byte[0];\n\n    while(!context.isEstablished()){\n      try{\n        token=context.init(token, 0, token.length);\n      }\n      catch(JSchException e){\n        // TODO\n        // ERRTOK should be sent?\n        // byte        SSH_MSG_USERAUTH_GSSAPI_ERRTOK\n        // string      error token\n        return false;\n      }\n\n      if(token!=null){\n        packet.reset();\n        buf.putByte((byte)SSH_MSG_USERAUTH_GSSAPI_TOKEN);\n        buf.putString(token);\n        session.write(packet);\n      }\n\n      if(!context.isEstablished()){\n        buf=session.read(buf);\n        command=buf.getCommand()&0xff;\n        if(command==SSH_MSG_USERAUTH_GSSAPI_ERROR){\n          // uint32    major_status\n          // uint32    minor_status\n          // string    message\n          // string    language tag\n\n          buf=session.read(buf);\n          command=buf.getCommand()&0xff;\n          //return false;\n        }\n        else if(command==SSH_MSG_USERAUTH_GSSAPI_ERRTOK){\n          // string error token\n\n          buf=session.read(buf);\n          command=buf.getCommand()&0xff;\n          //return false;\n        }\n\n        if(command==SSH_MSG_USERAUTH_FAILURE){\n          return false;\n        }\n\n        buf.getInt(); buf.getByte(); buf.getByte();\n        token=buf.getString();\n      }\n    }\n\n    Buffer mbuf=new Buffer();\n    // string    session identifier\n    // byte      SSH_MSG_USERAUTH_REQUEST\n    // string    user name\n    // string    service\n    // string    \"gssapi-with-mic\"\n    mbuf.putString(session.getSessionId());\n    mbuf.putByte((byte)SSH_MSG_USERAUTH_REQUEST);\n    mbuf.putString(_username);\n    mbuf.putString(Util.str2byte(\"ssh-connection\"));\n    mbuf.putString(Util.str2byte(\"gssapi-with-mic\"));\n\n    byte[] mic=context.getMIC(mbuf.buffer, 0, mbuf.getLength());\n\n    if(mic==null){\n      return false;\n    }\n\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_USERAUTH_GSSAPI_MIC);\n    buf.putString(mic);\n    session.write(packet);\n\n    context.dispose();\n\n    buf=session.read(buf);\n    command=buf.getCommand()&0xff;\n\n    if(command==SSH_MSG_USERAUTH_SUCCESS){\n      return true;\n    }\n    else if(command==SSH_MSG_USERAUTH_FAILURE){\n      buf.getInt(); buf.getByte(); buf.getByte(); \n      byte[] foo=buf.getString();\n      int partial_success=buf.getByte();\n      //System.err.println(new String(foo)+\n      //\t\t \" partial_success:\"+(partial_success!=0));\n      if(partial_success!=0){\n        throw new JSchPartialAuthException(Util.byte2str(foo));\n      }\n    }\n    return false;\n  }\n}\n\n\n"
  },
  {
    "path": "java/com/jcraft/jsch/UserAuthKeyboardInteractive.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass UserAuthKeyboardInteractive extends UserAuth{\n  public boolean start(Session session) throws Exception{\n    super.start(session);\n\n    if(userinfo!=null && !(userinfo instanceof UIKeyboardInteractive)){\n      return false;\n    }\n\n    String dest=username+\"@\"+session.host;\n    if(session.port!=22){\n      dest+=(\":\"+session.port);\n    }\n    byte[] password=session.password;\n\n    boolean cancel=false;\n\n    byte[] _username=null;\n    _username=Util.str2byte(username);\n\n    while(true){\n\n      if(session.auth_failures >= session.max_auth_tries){\n\treturn false;\n      }\n\n      // send\n      // byte      SSH_MSG_USERAUTH_REQUEST(50)\n      // string    user name (ISO-10646 UTF-8, as defined in [RFC-2279])\n      // string    service name (US-ASCII) \"ssh-userauth\" ? \"ssh-connection\"\n      // string    \"keyboard-interactive\" (US-ASCII)\n      // string    language tag (as defined in [RFC-3066])\n      // string    submethods (ISO-10646 UTF-8)\n      packet.reset();\n      buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST);\n      buf.putString(_username);\n      buf.putString(Util.str2byte(\"ssh-connection\"));\n      //buf.putString(\"ssh-userauth\".getBytes());\n      buf.putString(Util.str2byte(\"keyboard-interactive\"));\n      buf.putString(Util.empty);\n      buf.putString(Util.empty);\n      session.write(packet);\n\n      boolean firsttime=true;\n      loop:\n      while(true){\n        buf=session.read(buf);\n        int command=buf.getCommand()&0xff;\n\n\tif(command==SSH_MSG_USERAUTH_SUCCESS){\n\t  return true;\n\t}\n\tif(command==SSH_MSG_USERAUTH_BANNER){\n\t  buf.getInt(); buf.getByte(); buf.getByte();\n\t  byte[] _message=buf.getString();\n\t  byte[] lang=buf.getString();\n\t  String message=Util.byte2str(_message);\n\t  if(userinfo!=null){\n\t    userinfo.showMessage(message);\n\t  }\n\t  continue loop;\n\t}\n\tif(command==SSH_MSG_USERAUTH_FAILURE){\n\t  buf.getInt(); buf.getByte(); buf.getByte(); \n\t  byte[] foo=buf.getString();\n\t  int partial_success=buf.getByte();\n//\t  System.err.println(new String(foo)+\n//\t\t\t     \" partial_success:\"+(partial_success!=0));\n\n\t  if(partial_success!=0){\n\t    throw new JSchPartialAuthException(Util.byte2str(foo));\n\t  }\n\n\t  if(firsttime){\n\t    return false;\n\t    //throw new JSchException(\"USERAUTH KI is not supported\");\n\t    //cancel=true;  // ??\n\t  }\n          session.auth_failures++;\n\t  break;\n\t}\n\tif(command==SSH_MSG_USERAUTH_INFO_REQUEST){\n\t  firsttime=false;\n\t  buf.getInt(); buf.getByte(); buf.getByte();\n\t  String name=Util.byte2str(buf.getString());\n\t  String instruction=Util.byte2str(buf.getString());\n\t  String languate_tag=Util.byte2str(buf.getString());\n\t  int num=buf.getInt();\n\t  String[] prompt=new String[num];\n\t  boolean[] echo=new boolean[num];\n\t  for(int i=0; i<num; i++){\n\t    prompt[i]=Util.byte2str(buf.getString());\n\t    echo[i]=(buf.getByte()!=0);\n\t  }\n\n\t  byte[][] response=null;\n\n          if(password!=null && \n             prompt.length==1 &&\n             !echo[0] &&\n             prompt[0].toLowerCase().indexOf(\"password:\") >= 0){\n            response=new byte[1][];\n            response[0]=password;\n            password=null;\n          }\n          else if(num>0\n\t     ||(name.length()>0 || instruction.length()>0)\n\t     ){\n\t    if(userinfo!=null){\n              UIKeyboardInteractive kbi=(UIKeyboardInteractive)userinfo;\n              String[] _response=kbi.promptKeyboardInteractive(dest,\n                                                               name,\n                                                               instruction,\n                                                               prompt,\n                                                               echo);\n              if(_response!=null){\n                response=new byte[_response.length][];\n                for(int i=0; i<_response.length; i++){\n                  response[i]=Util.str2byte(_response[i]);\n                }\n              }\n\t    }\n\t  }\n\n\t  // byte      SSH_MSG_USERAUTH_INFO_RESPONSE(61)\n\t  // int       num-responses\n\t  // string    response[1] (ISO-10646 UTF-8)\n\t  // ...\n\t  // string    response[num-responses] (ISO-10646 UTF-8)\n\t  packet.reset();\n\t  buf.putByte((byte)SSH_MSG_USERAUTH_INFO_RESPONSE);\n\t  if(num>0 &&\n\t     (response==null ||  // cancel\n\t      num!=response.length)){\n\n            if(response==null){  \n              // working around the bug in OpenSSH ;-<\n              buf.putInt(num);\n              for(int i=0; i<num; i++){\n                buf.putString(Util.empty);\n              }\n            }\n            else{\n              buf.putInt(0);\n            }\n\n\t    if(response==null)\n\t      cancel=true;\n\t  }\n\t  else{\n\t    buf.putInt(num);\n\t    for(int i=0; i<num; i++){\n\t      buf.putString(response[i]);\n\t    }\n\t  }\n\t  session.write(packet);\n          /*\n\t  if(cancel)\n\t    break;\n          */\n\t  continue loop;\n\t}\n\t//throw new JSchException(\"USERAUTH fail (\"+command+\")\");\n\treturn false;\n      }\n      if(cancel){\n\tthrow new JSchAuthCancelException(\"keyboard-interactive\");\n\t//break;\n      }\n    }\n    //return false;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/UserAuthNone.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass UserAuthNone extends UserAuth{\n  private static final int SSH_MSG_SERVICE_ACCEPT=                  6;\n  private String methods=null;\n\n  public boolean start(Session session) throws Exception{\n    super.start(session);\n\n\n    // send\n    // byte      SSH_MSG_SERVICE_REQUEST(5)\n    // string    service name \"ssh-userauth\"\n    packet.reset();\n    buf.putByte((byte)Session.SSH_MSG_SERVICE_REQUEST);\n    buf.putString(Util.str2byte(\"ssh-userauth\"));\n    session.write(packet);\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"SSH_MSG_SERVICE_REQUEST sent\");\n    }\n\n    // receive\n    // byte      SSH_MSG_SERVICE_ACCEPT(6)\n    // string    service name\n    buf=session.read(buf);\n    int command=buf.getCommand();\n\n    boolean result=(command==SSH_MSG_SERVICE_ACCEPT);\n\n    if(JSch.getLogger().isEnabled(Logger.INFO)){\n      JSch.getLogger().log(Logger.INFO, \n                           \"SSH_MSG_SERVICE_ACCEPT received\");\n    }\n    if(!result)\n      return false;\n\n    byte[] _username=null;\n    _username=Util.str2byte(username);\n\n    // send\n    // byte      SSH_MSG_USERAUTH_REQUEST(50)\n    // string    user name\n    // string    service name (\"ssh-connection\")\n    // string    \"none\"\n    packet.reset();\n    buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST);\n    buf.putString(_username);\n    buf.putString(Util.str2byte(\"ssh-connection\"));\n    buf.putString(Util.str2byte(\"none\"));\n    session.write(packet);\n\n    loop:\n    while(true){\n      buf=session.read(buf);\n      command=buf.getCommand()&0xff;\n\n      if(command==SSH_MSG_USERAUTH_SUCCESS){\n\treturn true;\n      }\n      if(command==SSH_MSG_USERAUTH_BANNER){\n\tbuf.getInt(); buf.getByte(); buf.getByte();\n\tbyte[] _message=buf.getString();\n\tbyte[] lang=buf.getString();\n\tString message=Util.byte2str(_message);\n\tif(userinfo!=null){\n          try{\n            userinfo.showMessage(message);\n          }\n          catch(RuntimeException ee){\n          }\n\t}\n\tcontinue loop;\n      }\n      if(command==SSH_MSG_USERAUTH_FAILURE){\n\tbuf.getInt(); buf.getByte(); buf.getByte(); \n\tbyte[] foo=buf.getString();\n\tint partial_success=buf.getByte();\n\tmethods=Util.byte2str(foo);\n//System.err.println(\"UserAuthNONE: \"+methods+\n//\t\t   \" partial_success:\"+(partial_success!=0));\n//\tif(partial_success!=0){\n//\t  throw new JSchPartialAuthException(new String(foo));\n//\t}\n\n        break;\n      }\n      else{\n//      System.err.println(\"USERAUTH fail (\"+command+\")\");\n\tthrow new JSchException(\"USERAUTH fail (\"+command+\")\");\n      }\n    }\n   //throw new JSchException(\"USERAUTH fail\");\n    return false;\n  }\n  String getMethods(){\n    return methods;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/UserAuthPassword.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nclass UserAuthPassword extends UserAuth{\n  private final int SSH_MSG_USERAUTH_PASSWD_CHANGEREQ=60;\n\n  public boolean start(Session session) throws Exception{\n    super.start(session);\n\n    byte[] password=session.password;\n    String dest=username+\"@\"+session.host;\n    if(session.port!=22){\n      dest+=(\":\"+session.port);\n    }\n\n    try{\n\n    while(true){\n\n      if(session.auth_failures >= session.max_auth_tries){\n        return false;\n      }\n\n      if(password==null){\n\tif(userinfo==null){\n\t  //throw new JSchException(\"USERAUTH fail\");\n\t  return false;\n\t}\n\tif(!userinfo.promptPassword(\"Password for \"+dest)){\n\t  throw new JSchAuthCancelException(\"password\");\n\t  //break;\n\t}\n\n\tString _password=userinfo.getPassword();\n\tif(_password==null){\n\t  throw new JSchAuthCancelException(\"password\");\n\t  //break;\n\t}\n        password=Util.str2byte(_password);\n      }\n\n      byte[] _username=null;\n      _username=Util.str2byte(username);\n\n      // send\n      // byte      SSH_MSG_USERAUTH_REQUEST(50)\n      // string    user name\n      // string    service name (\"ssh-connection\")\n      // string    \"password\"\n      // boolen    FALSE\n      // string    plaintext password (ISO-10646 UTF-8)\n      packet.reset();\n      buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST);\n      buf.putString(_username);\n      buf.putString(Util.str2byte(\"ssh-connection\"));\n      buf.putString(Util.str2byte(\"password\"));\n      buf.putByte((byte)0);\n      buf.putString(password);\n      session.write(packet);\n\n      loop:\n      while(true){\n\tbuf=session.read(buf);\n        int command=buf.getCommand()&0xff;\n\n\tif(command==SSH_MSG_USERAUTH_SUCCESS){\n\t  return true;\n\t}\n\tif(command==SSH_MSG_USERAUTH_BANNER){\n\t  buf.getInt(); buf.getByte(); buf.getByte();\n\t  byte[] _message=buf.getString();\n\t  byte[] lang=buf.getString();\n          String message=Util.byte2str(_message);\n\t  if(userinfo!=null){\n\t    userinfo.showMessage(message);\n\t  }\n\t  continue loop;\n\t}\n\tif(command==SSH_MSG_USERAUTH_PASSWD_CHANGEREQ){\n\t  buf.getInt(); buf.getByte(); buf.getByte(); \n\t  byte[] instruction=buf.getString();\n\t  byte[] tag=buf.getString();\n\t  if(userinfo==null || \n             !(userinfo instanceof UIKeyboardInteractive)){\n            if(userinfo!=null){\n              userinfo.showMessage(\"Password must be changed.\");\n            }\n            return false;\n          }\n\n          UIKeyboardInteractive kbi=(UIKeyboardInteractive)userinfo;\n          String[] response;\n          String name=\"Password Change Required\";\n          String[] prompt={\"New Password: \"};\n          boolean[] echo={false};\n          response=kbi.promptKeyboardInteractive(dest,\n                                                 name,\n                                                 Util.byte2str(instruction),\n                                                 prompt,\n                                                 echo);\n          if(response==null){\n            throw new JSchAuthCancelException(\"password\");\n          }\n\n          byte[] newpassword=Util.str2byte(response[0]);\n\n          // send\n          // byte      SSH_MSG_USERAUTH_REQUEST(50)\n          // string    user name\n          // string    service name (\"ssh-connection\")\n          // string    \"password\"\n          // boolen    TRUE\n          // string    plaintext old password (ISO-10646 UTF-8)\n          // string    plaintext new password (ISO-10646 UTF-8)\n          packet.reset();\n          buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST);\n          buf.putString(_username);\n          buf.putString(Util.str2byte(\"ssh-connection\"));\n          buf.putString(Util.str2byte(\"password\"));\n          buf.putByte((byte)1);\n          buf.putString(password);\n          buf.putString(newpassword);\n          Util.bzero(newpassword);\n          response=null;\n          session.write(packet);\n\t  continue loop;\n        }\n\tif(command==SSH_MSG_USERAUTH_FAILURE){\n\t  buf.getInt(); buf.getByte(); buf.getByte(); \n\t  byte[] foo=buf.getString();\n\t  int partial_success=buf.getByte();\n\t  //System.err.println(new String(foo)+\n\t  //\t\t \" partial_success:\"+(partial_success!=0));\n\t  if(partial_success!=0){\n\t    throw new JSchPartialAuthException(Util.byte2str(foo));\n\t  }\n          session.auth_failures++;\n\t  break;\n\t}\n\telse{\n          //System.err.println(\"USERAUTH fail (\"+buf.getCommand()+\")\");\n//\t  throw new JSchException(\"USERAUTH fail (\"+buf.getCommand()+\")\");\n\t  return false;\n\t}\n      }\n\n      if(password!=null){\n        Util.bzero(password);\n        password=null;\n      }\n\n    }\n\n    }\n    finally{\n      if(password!=null){\n        Util.bzero(password);\n        password=null;\n      }\n    }\n\n    //throw new JSchException(\"USERAUTH fail\");\n    //return false;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/UserAuthPublicKey.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\nimport java.util.Vector;\n\nclass UserAuthPublicKey extends UserAuth{\n\n  public boolean start(Session session) throws Exception{\n    super.start(session);\n\n    Vector identities=session.getIdentityRepository().getIdentities();\n\n    byte[] passphrase=null;\n    byte[] _username=null;\n\n    int command;\n\n    synchronized(identities){\n      if(identities.size()<=0){\n        return false;\n      }\n\n      _username=Util.str2byte(username);\n\n      for(int i=0; i<identities.size(); i++){\n\n        if(session.auth_failures >= session.max_auth_tries){\n          return false;\n        }\n\n        Identity identity=(Identity)(identities.elementAt(i));\n        byte[] pubkeyblob=identity.getPublicKeyBlob();\n\n        if(pubkeyblob!=null){\n          // send\n          // byte      SSH_MSG_USERAUTH_REQUEST(50)\n          // string    user name\n          // string    service name (\"ssh-connection\")\n          // string    \"publickey\"\n          // boolen    FALSE\n          // string    public key algorithm name\n          // string    public key blob\n          packet.reset();\n          buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST);\n          buf.putString(_username);\n          buf.putString(Util.str2byte(\"ssh-connection\"));\n          buf.putString(Util.str2byte(\"publickey\"));\n          buf.putByte((byte)0);\n          buf.putString(Util.str2byte(identity.getAlgName()));\n          buf.putString(pubkeyblob);\n          session.write(packet);\n\n          loop1:\n          while(true){\n            buf=session.read(buf);\n            command=buf.getCommand()&0xff;\n\n            if(command==SSH_MSG_USERAUTH_PK_OK){\n              break;\n            }\n            else if(command==SSH_MSG_USERAUTH_FAILURE){\n              break;\n            }\n            else if(command==SSH_MSG_USERAUTH_BANNER){\n              buf.getInt(); buf.getByte(); buf.getByte();\n              byte[] _message=buf.getString();\n              byte[] lang=buf.getString();\n              String message=Util.byte2str(_message);\n              if(userinfo!=null){\n                userinfo.showMessage(message);\n              }\n              continue loop1;\n            }\n            else{\n\t    //System.err.println(\"USERAUTH fail (\"+command+\")\");\n\t    //throw new JSchException(\"USERAUTH fail (\"+command+\")\");\n              break;\n            }\n          }\n\n          if(command!=SSH_MSG_USERAUTH_PK_OK){\n            continue;\n          }\n        }\n\n//System.err.println(\"UserAuthPublicKey: identity.isEncrypted()=\"+identity.isEncrypted());\n\n        int count=5;\n        while(true){\n          if((identity.isEncrypted() && passphrase==null)){\n            if(userinfo==null) throw new JSchException(\"USERAUTH fail\");\n            if(identity.isEncrypted() &&\n               !userinfo.promptPassphrase(\"Passphrase for \"+identity.getName())){\n              throw new JSchAuthCancelException(\"publickey\");\n              //throw new JSchException(\"USERAUTH cancel\");\n              //break;\n            }\n            String _passphrase=userinfo.getPassphrase();\n            if(_passphrase!=null){\n              passphrase=Util.str2byte(_passphrase);\n            }\n          }\n\n          if(!identity.isEncrypted() || passphrase!=null){\n            if(identity.setPassphrase(passphrase)){\n              if(passphrase!=null &&\n                 (session.getIdentityRepository() instanceof IdentityRepository.Wrapper)){\n                ((IdentityRepository.Wrapper)session.getIdentityRepository()).check();\n              }\n              break;\n            }\n          }\n          Util.bzero(passphrase);\n          passphrase=null;\n          count--;\n          if(count==0)break;\n        }\n\n        Util.bzero(passphrase);\n        passphrase=null;\n//System.err.println(\"UserAuthPublicKey: identity.isEncrypted()=\"+identity.isEncrypted());\n\n        if(identity.isEncrypted()) continue;\n        if(pubkeyblob==null) pubkeyblob=identity.getPublicKeyBlob();\n\n//System.err.println(\"UserAuthPublicKey: pubkeyblob=\"+pubkeyblob);\n\n        if(pubkeyblob==null) continue;\n\n        // send\n        // byte      SSH_MSG_USERAUTH_REQUEST(50)\n        // string    user name\n        // string    service name (\"ssh-connection\")\n        // string    \"publickey\"\n        // boolen    TRUE\n        // string    public key algorithm name\n        // string    public key blob\n        // string    signature\n        packet.reset();\n        buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST);\n        buf.putString(_username);\n        buf.putString(Util.str2byte(\"ssh-connection\"));\n        buf.putString(Util.str2byte(\"publickey\"));\n        buf.putByte((byte)1);\n        buf.putString(Util.str2byte(identity.getAlgName()));\n        buf.putString(pubkeyblob);\n\n//      byte[] tmp=new byte[buf.index-5];\n//      System.arraycopy(buf.buffer, 5, tmp, 0, tmp.length);\n//      buf.putString(signature);\n\n        byte[] sid=session.getSessionId();\n        int sidlen=sid.length;\n        byte[] tmp=new byte[4+sidlen+buf.index-5];\n        tmp[0]=(byte)(sidlen>>>24);\n        tmp[1]=(byte)(sidlen>>>16);\n        tmp[2]=(byte)(sidlen>>>8);\n        tmp[3]=(byte)(sidlen);\n        System.arraycopy(sid, 0, tmp, 4, sidlen);\n        System.arraycopy(buf.buffer, 5, tmp, 4+sidlen, buf.index-5);\n        byte[] signature=identity.getSignature(tmp);\n        if(signature==null){  // for example, too long key length.\n          break;\n        }\n        buf.putString(signature);\n        session.write(packet);\n\n        loop2:\n        while(true){\n          buf=session.read(buf);\n          command=buf.getCommand()&0xff;\n\n          if(command==SSH_MSG_USERAUTH_SUCCESS){\n            return true;\n          }\n          else if(command==SSH_MSG_USERAUTH_BANNER){\n            buf.getInt(); buf.getByte(); buf.getByte();\n            byte[] _message=buf.getString();\n            byte[] lang=buf.getString();\n            String message=Util.byte2str(_message);\n            if(userinfo!=null){\n              userinfo.showMessage(message);\n            }\n            continue loop2;\n          }\n          else if(command==SSH_MSG_USERAUTH_FAILURE){\n            buf.getInt(); buf.getByte(); buf.getByte(); \n            byte[] foo=buf.getString();\n            int partial_success=buf.getByte();\n\t  //System.err.println(new String(foo)+\n\t  //                   \" partial_success:\"+(partial_success!=0));\n            if(partial_success!=0){\n              throw new JSchPartialAuthException(Util.byte2str(foo));\n            }\n            session.auth_failures++;\n            break;\n          }\n          //System.err.println(\"USERAUTH fail (\"+command+\")\");\n          //throw new JSchException(\"USERAUTH fail (\"+command+\")\");\n          break;\n        }\n      }\n    }\n    return false;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/UserInfo.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\n\npublic interface UserInfo{\n  String getPassphrase();\n  String getPassword();\n  boolean promptPassword(String message);\n  boolean promptPassphrase(String message);\n  boolean promptYesNo(String message);\n  void showMessage(String message);\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/Util.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch;\nimport java.net.Socket;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.IOException;\n\nclass Util{\n\n  private static final byte[] b64 =Util.str2byte(\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\");\n  private static byte val(byte foo){\n    if(foo == '=') return 0;\n    for(int j=0; j<b64.length; j++){\n      if(foo==b64[j]) return (byte)j;\n    }\n    return 0;\n  }\n  static byte[] fromBase64(byte[] buf, int start, int length) throws JSchException {\n    try {\n      byte[] foo=new byte[length];\n      int j=0;\n      for (int i=start;i<start+length;i+=4){\n        foo[j]=(byte)((val(buf[i])<<2)|((val(buf[i+1])&0x30)>>>4));\n        if(buf[i+2]==(byte)'='){ j++; break;}\n        foo[j+1]=(byte)(((val(buf[i+1])&0x0f)<<4)|((val(buf[i+2])&0x3c)>>>2));\n        if(buf[i+3]==(byte)'='){ j+=2; break;}\n        foo[j+2]=(byte)(((val(buf[i+2])&0x03)<<6)|(val(buf[i+3])&0x3f));\n        j+=3;\n      }\n      byte[] bar=new byte[j];\n      System.arraycopy(foo, 0, bar, 0, j);\n      return bar;\n    }\n    catch(ArrayIndexOutOfBoundsException e) {\n      throw new JSchException(\"fromBase64: invalid base64 data\", e);\n    }\n  }\n  static byte[] toBase64(byte[] buf, int start, int length){\n\n    byte[] tmp=new byte[length*2];\n    int i,j,k;\n    \n    int foo=(length/3)*3+start;\n    i=0;\n    for(j=start; j<foo; j+=3){\n      k=(buf[j]>>>2)&0x3f;\n      tmp[i++]=b64[k];\n      k=(buf[j]&0x03)<<4|(buf[j+1]>>>4)&0x0f;\n      tmp[i++]=b64[k];\n      k=(buf[j+1]&0x0f)<<2|(buf[j+2]>>>6)&0x03;\n      tmp[i++]=b64[k];\n      k=buf[j+2]&0x3f;\n      tmp[i++]=b64[k];\n    }\n\n    foo=(start+length)-foo;\n    if(foo==1){\n      k=(buf[j]>>>2)&0x3f;\n      tmp[i++]=b64[k];\n      k=((buf[j]&0x03)<<4)&0x3f;\n      tmp[i++]=b64[k];\n      tmp[i++]=(byte)'=';\n      tmp[i++]=(byte)'=';\n    }\n    else if(foo==2){\n      k=(buf[j]>>>2)&0x3f;\n      tmp[i++]=b64[k];\n      k=(buf[j]&0x03)<<4|(buf[j+1]>>>4)&0x0f;\n      tmp[i++]=b64[k];\n      k=((buf[j+1]&0x0f)<<2)&0x3f;\n      tmp[i++]=b64[k];\n      tmp[i++]=(byte)'=';\n    }\n    byte[] bar=new byte[i];\n    System.arraycopy(tmp, 0, bar, 0, i);\n    return bar;\n\n//    return sun.misc.BASE64Encoder().encode(buf);\n  }\n\n  static String[] split(String foo, String split){\n    if(foo==null)\n      return null;\n    byte[] buf=Util.str2byte(foo);\n    java.util.Vector bar=new java.util.Vector();\n    int start=0;\n    int index;\n    while(true){\n      index=foo.indexOf(split, start);\n      if(index>=0){\n\tbar.addElement(Util.byte2str(buf, start, index-start));\n\tstart=index+1;\n\tcontinue;\n      }\n      bar.addElement(Util.byte2str(buf, start, buf.length-start));\n      break;\n    }\n    String[] result=new String[bar.size()];\n    for(int i=0; i<result.length; i++){\n      result[i]=(String)(bar.elementAt(i));\n    }\n    return result;\n  }\n  static boolean glob(byte[] pattern, byte[] name){\n    return glob0(pattern, 0, name, 0);\n  }\n  static private boolean glob0(byte[] pattern, int pattern_index,\n\t\t\t      byte[] name, int name_index){\n    if(name.length>0 && name[0]=='.'){\n      if(pattern.length>0 && pattern[0]=='.'){\n        if(pattern.length==2 && pattern[1]=='*') return true;\n        return glob(pattern, pattern_index+1, name, name_index+1);\n      }\n      return false;\n    }\n    return glob(pattern, pattern_index, name, name_index);\n  }\n  static private boolean glob(byte[] pattern, int pattern_index,\n\t\t\t      byte[] name, int name_index){\n    //System.err.println(\"glob: \"+new String(pattern)+\", \"+pattern_index+\" \"+new String(name)+\", \"+name_index);\n\n    int patternlen=pattern.length;\n    if(patternlen==0)\n      return false;\n\n    int namelen=name.length;\n    int i=pattern_index;\n    int j=name_index;\n\n    while(i<patternlen && j<namelen){\n      if(pattern[i]=='\\\\'){\n\tif(i+1==patternlen)\n\t  return false;\n\ti++;\n\tif(pattern[i]!=name[j]) \n          return false;\n        i+=skipUTF8Char(pattern[i]);\n        j+=skipUTF8Char(name[j]);\n\tcontinue;\n      }\n\n      if(pattern[i]=='*'){\n        while(i<patternlen){\n          if(pattern[i]=='*'){\n            i++;\n            continue;\n          }\n          break;\n        }\n\tif(patternlen==i)\n          return true;\n\n\tbyte foo=pattern[i];\n        if(foo=='?'){\n          while(j<namelen){\n\t    if(glob(pattern, i, name, j)){\n\t      return true;\n            }\n            j+=skipUTF8Char(name[j]);\n          }\n          return false;\n        }\n        else if(foo=='\\\\'){\n          if(i+1==patternlen)\n            return false;\n          i++;\n          foo=pattern[i];\n          while(j<namelen){\n            if(foo==name[j]){\n              if(glob(pattern, i+skipUTF8Char(foo),\n                      name, j+skipUTF8Char(name[j]))){\n                return true;\n              }\n            }\n            j+=skipUTF8Char(name[j]);\n          }\n          return false;\n        }\n\n\twhile(j<namelen){\n\t  if(foo==name[j]){\n\t    if(glob(pattern, i, name, j)){\n\t      return true;\n\t    }\n\t  }\n          j+=skipUTF8Char(name[j]);\n\t}\n\treturn false;\n      }\n\n      if(pattern[i]=='?'){\n        i++;\n        j+=skipUTF8Char(name[j]);\n\tcontinue;\n      }\n\n      if(pattern[i]!=name[j])\n        return false;\n\n      i+=skipUTF8Char(pattern[i]);\n      j+=skipUTF8Char(name[j]);\n\n      if(!(j<namelen)){         // name is end\n        if(!(i<patternlen)){    // pattern is end\n\t  return true;\n\t}\n\tif(pattern[i]=='*'){    \n          break;\n\t}\n      }\n      continue;\n    }\n\n    if(i==patternlen && j==namelen) \n      return true;\n\n    if(!(j<namelen) &&  // name is end\n       pattern[i]=='*'){\n      boolean ok=true;\n      while(i<patternlen){\n        if(pattern[i++]!='*'){\n          ok=false;\n          break;\n        }\n      }\n      return ok;\n    }\n\n    return false;\n  }\n\n  static String quote(String path){\n    byte[] _path=str2byte(path);\n    int count=0;\n    for(int i=0;i<_path.length; i++){\n      byte b=_path[i];\n      if(b=='\\\\' || b=='?' || b=='*')\n        count++;\n    }\n    if(count==0)\n      return path;\n    byte[] _path2=new byte[_path.length+count];\n    for(int i=0, j=0; i<_path.length; i++){\n      byte b=_path[i];\n      if(b=='\\\\' || b=='?' || b=='*'){\n        _path2[j++]='\\\\';\n      }\n      _path2[j++]=b;\n    }\n    return byte2str(_path2);\n  }\n\n  static String unquote(String path){\n    byte[] foo=str2byte(path);\n    byte[] bar=unquote(foo);\n    if(foo.length==bar.length)\n      return path;\n    return byte2str(bar);\n  }\n  static byte[] unquote(byte[] path){\n    int pathlen=path.length;\n    int i=0;\n    while(i<pathlen){\n      if(path[i]=='\\\\'){\n        if(i+1==pathlen)\n          break;\n        System.arraycopy(path, i+1, path, i, path.length-(i+1));\n        pathlen--;\n        i++;\n        continue;\n      }\n      i++;\n    }\n    if(pathlen==path.length)\n      return path;\n    byte[] foo=new byte[pathlen];\n    System.arraycopy(path, 0, foo, 0, pathlen);\n    return foo;\n  }\n\n  private static String[] chars={\n    \"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\", \"a\",\"b\",\"c\",\"d\",\"e\",\"f\"\n  };\n  static String getFingerPrint(HASH hash, byte[] data){\n    try{\n      hash.init();\n      hash.update(data, 0, data.length);\n      byte[] foo=hash.digest();\n      StringBuffer sb=new StringBuffer();\n      int bar;\n      for(int i=0; i<foo.length;i++){\n        bar=foo[i]&0xff;\n        sb.append(chars[(bar>>>4)&0xf]);\n        sb.append(chars[(bar)&0xf]);\n        if(i+1<foo.length)\n          sb.append(\":\");\n      }\n      return sb.toString();\n    }\n    catch(Exception e){\n      return \"???\";\n    }\n  }\n  static boolean array_equals(byte[] foo, byte bar[]){\n    int i=foo.length;\n    if(i!=bar.length) return false;\n    for(int j=0; j<i; j++){ if(foo[j]!=bar[j]) return false; }\n    //try{while(true){i--; if(foo[i]!=bar[i])return false;}}catch(Exception e){}\n    return true;\n  }\n  static Socket createSocket(String host, int port, int timeout) throws JSchException{\n    Socket socket=null;\n    if(timeout==0){\n      try{\n        socket=new Socket(host, port);\n        return socket;\n      }\n      catch(Exception e){\n        String message=e.toString();\n        if(e instanceof Throwable)\n          throw new JSchException(message, (Throwable)e);\n        throw new JSchException(message);\n      }\n    }\n    final String _host=host;\n    final int _port=port;\n    final Socket[] sockp=new Socket[1];\n    final Exception[] ee=new Exception[1];\n    String message=\"\";\n    Thread tmp=new Thread(new Runnable(){\n        public void run(){\n          sockp[0]=null;\n          try{\n            sockp[0]=new Socket(_host, _port);\n          }\n          catch(Exception e){\n            ee[0]=e;\n            if(sockp[0]!=null && sockp[0].isConnected()){\n              try{\n                sockp[0].close();\n              }\n              catch(Exception eee){}\n            }\n            sockp[0]=null;\n          }\n        }\n      });\n    tmp.setName(\"Opening Socket \"+host);\n    tmp.start();\n    try{ \n      tmp.join(timeout);\n      message=\"timeout: \";\n    }\n    catch(java.lang.InterruptedException eee){\n    }\n    if(sockp[0]!=null && sockp[0].isConnected()){\n      socket=sockp[0];\n    }\n    else{\n      message+=\"socket is not established\";\n      if(ee[0]!=null){\n        message=ee[0].toString();\n      }\n      tmp.interrupt();\n      tmp=null;\n      throw new JSchException(message, ee[0]);\n    }\n    return socket;\n  } \n\n  static byte[] str2byte(String str, String encoding){\n    if(str==null) \n      return null;\n    try{ return str.getBytes(encoding); }\n    catch(java.io.UnsupportedEncodingException e){\n      return str.getBytes();\n    }\n  }\n\n  static byte[] str2byte(String str){\n    return str2byte(str, \"UTF-8\");\n  }\n\n  static String byte2str(byte[] str, String encoding){\n    return byte2str(str, 0, str.length, encoding);\n  }\n\n  static String byte2str(byte[] str, int s, int l, String encoding){\n    try{ return new String(str, s, l, encoding); }\n    catch(java.io.UnsupportedEncodingException e){\n      return new String(str, s, l);\n    }\n  }\n\n  static String byte2str(byte[] str){\n    return byte2str(str, 0, str.length, \"UTF-8\");\n  }\n\n  static String byte2str(byte[] str, int s, int l){\n    return byte2str(str, s, l, \"UTF-8\");\n  }\n\n  static String toHex(byte[] str){\n    StringBuffer sb = new StringBuffer();\n    for(int i = 0; i<str.length; i++){\n      String foo = Integer.toHexString(str[i]&0xff);\n      sb.append(\"0x\"+(foo.length() == 1 ? \"0\" : \"\")+foo);\n      if(i+1<str.length)\n        sb.append(\":\");\n    }\n    return sb.toString();\n  }\n\n  static final byte[] empty = str2byte(\"\");\n\n  /*\n  static byte[] char2byte(char[] foo){\n    int len=0;\n    for(int i=0; i<foo.length; i++){\n      if((foo[i]&0xff00)==0) len++;\n      else len+=2;\n    }\n    byte[] bar=new byte[len];\n    for(int i=0, j=0; i<foo.length; i++){\n      if((foo[i]&0xff00)==0){\n        bar[j++]=(byte)foo[i];\n      }\n      else{\n        bar[j++]=(byte)(foo[i]>>>8);\n        bar[j++]=(byte)foo[i];\n      }\n    }\n    return bar;\n  }\n  */\n  static void bzero(byte[] foo){\n    if(foo==null)\n      return;\n    for(int i=0; i<foo.length; i++)\n      foo[i]=0;\n  }\n\n  static String diffString(String str, String[] not_available){\n    String[] stra=Util.split(str, \",\");\n    String result=null;\n    loop:\n    for(int i=0; i<stra.length; i++){\n      for(int j=0; j<not_available.length; j++){\n        if(stra[i].equals(not_available[j])){\n          continue loop;\n        }\n      }\n      if(result==null){ result=stra[i]; }\n      else{ result=result+\",\"+stra[i]; }\n    }\n    return result;\n  }\n\n  static String checkTilde(String str){\n    try{\n      if(str.startsWith(\"~\")){\n        str = str.replace(\"~\", System.getProperty(\"user.home\"));\n      }\n    }\n    catch(SecurityException e){\n    }\n    return str;\n  }\n\n  private static int skipUTF8Char(byte b){\n    if((byte)(b&0x80)==0) return 1;\n    if((byte)(b&0xe0)==(byte)0xc0) return 2;\n    if((byte)(b&0xf0)==(byte)0xe0) return 3;\n    return 1;\n  }\n\n  static byte[] fromFile(String _file) throws IOException {\n    _file = checkTilde(_file);\n    File file = new File(_file);\n    FileInputStream fis = new FileInputStream(_file);\n    try {\n      byte[] result = new byte[(int)(file.length())];\n      int len=0;\n      while(true){\n        int i=fis.read(result, len, result.length-len);\n        if(i<=0)\n          break;\n        len+=i;\n      }\n      fis.close();\n      return result;\n    }\n    finally {\n      if(fis!=null)\n        fis.close();\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/AES128CBC.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2005-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.spec.*;\n\npublic class AES128CBC implements Cipher{\n  private static final int ivsize=16;\n  private static final int bsize=16;\n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    String pad=\"NoPadding\";      \n    byte[] tmp;\n    if(iv.length>ivsize){\n      tmp=new byte[ivsize];\n      System.arraycopy(iv, 0, tmp, 0, tmp.length);\n      iv=tmp;\n    }\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n\n    try{\n      SecretKeySpec keyspec=new SecretKeySpec(key, \"AES\");\n      cipher=javax.crypto.Cipher.getInstance(\"AES/CBC/\"+pad);\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    keyspec, new IvParameterSpec(iv));\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n\n  public boolean isCBC(){return true; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/AES128CTR.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2008-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.spec.*;\n\npublic class AES128CTR implements Cipher{\n  private static final int ivsize=16;\n  private static final int bsize=16;\n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    String pad=\"NoPadding\";      \n    byte[] tmp;\n    if(iv.length>ivsize){\n      tmp=new byte[ivsize];\n      System.arraycopy(iv, 0, tmp, 0, tmp.length);\n      iv=tmp;\n    }\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n\n    try{\n      SecretKeySpec keyspec=new SecretKeySpec(key, \"AES\");\n      cipher=javax.crypto.Cipher.getInstance(\"AES/CTR/\"+pad);\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    keyspec, new IvParameterSpec(iv));\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n\n  public boolean isCBC(){return false; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/AES192CBC.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2005-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.spec.*;\n\npublic class AES192CBC implements Cipher{\n  private static final int ivsize=16;\n  private static final int bsize=24;\n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    String pad=\"NoPadding\";      \n    byte[] tmp;\n    if(iv.length>ivsize){\n      tmp=new byte[ivsize];\n      System.arraycopy(iv, 0, tmp, 0, tmp.length);\n      iv=tmp;\n    }\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n    try{\n      SecretKeySpec keyspec=new SecretKeySpec(key, \"AES\");\n      cipher=javax.crypto.Cipher.getInstance(\"AES/CBC/\"+pad);\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    keyspec, new IvParameterSpec(iv));\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n  public boolean isCBC(){return true; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/AES192CTR.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2008-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.spec.*;\n\npublic class AES192CTR implements Cipher{\n  private static final int ivsize=16;\n  private static final int bsize=24;\n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    String pad=\"NoPadding\";      \n    byte[] tmp;\n    if(iv.length>ivsize){\n      tmp=new byte[ivsize];\n      System.arraycopy(iv, 0, tmp, 0, tmp.length);\n      iv=tmp;\n    }\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n    try{\n      SecretKeySpec keyspec=new SecretKeySpec(key, \"AES\");\n      cipher=javax.crypto.Cipher.getInstance(\"AES/CTR/\"+pad);\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    keyspec, new IvParameterSpec(iv));\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n  public boolean isCBC(){return false; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/AES256CBC.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2005-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.spec.*;\n\npublic class AES256CBC implements Cipher{\n  private static final int ivsize=16;\n  private static final int bsize=32;\n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    String pad=\"NoPadding\";      \n    byte[] tmp;\n    if(iv.length>ivsize){\n      tmp=new byte[ivsize];\n      System.arraycopy(iv, 0, tmp, 0, tmp.length);\n      iv=tmp;\n    }\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n    try{\n      SecretKeySpec keyspec=new SecretKeySpec(key, \"AES\");\n      cipher=javax.crypto.Cipher.getInstance(\"AES/CBC/\"+pad);\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    keyspec, new IvParameterSpec(iv));\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n  public boolean isCBC(){return true; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/AES256CTR.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2008-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.spec.*;\n\npublic class AES256CTR implements Cipher{\n  private static final int ivsize=16;\n  private static final int bsize=32;\n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    String pad=\"NoPadding\";      \n    byte[] tmp;\n    if(iv.length>ivsize){\n      tmp=new byte[ivsize];\n      System.arraycopy(iv, 0, tmp, 0, tmp.length);\n      iv=tmp;\n    }\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n    try{\n      SecretKeySpec keyspec=new SecretKeySpec(key, \"AES\");\n      cipher=javax.crypto.Cipher.getInstance(\"AES/CTR/\"+pad);\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    keyspec, new IvParameterSpec(iv));\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n  public boolean isCBC(){return false; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/ARCFOUR.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2008-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.*;\nimport javax.crypto.spec.*;\n\npublic class ARCFOUR implements Cipher{\n  private static final int ivsize=8;\n  private static final int bsize=16;\n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    String pad=\"NoPadding\";      \n    byte[] tmp;\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n\n    try{\n      cipher=javax.crypto.Cipher.getInstance(\"RC4\");\n      SecretKeySpec _key = new SecretKeySpec(key, \"RC4\");\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n\t\t    _key);\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n  public boolean isCBC(){return false; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/ARCFOUR128.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2008-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.*;\nimport javax.crypto.spec.*;\n\npublic class ARCFOUR128 implements Cipher{\n  private static final int ivsize=8;\n  private static final int bsize=16;\n  private static final int skip=1536; \n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    byte[] tmp;\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n    try{\n      cipher=javax.crypto.Cipher.getInstance(\"RC4\");\n      SecretKeySpec _key = new SecretKeySpec(key, \"RC4\");\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    _key);\n      }\n      byte[] foo=new byte[1];\n      for(int i=0; i<skip; i++){\n        cipher.update(foo, 0, 1, foo, 0);\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n  public boolean isCBC(){return false; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/ARCFOUR256.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2008-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.*;\nimport javax.crypto.spec.*;\n\npublic class ARCFOUR256 implements Cipher{\n  private static final int ivsize=8;\n  private static final int bsize=32;\n  private static final int skip=1536; \n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    byte[] tmp;\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n    try{\n      cipher=javax.crypto.Cipher.getInstance(\"RC4\");\n      SecretKeySpec _key = new SecretKeySpec(key, \"RC4\");\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    _key);\n      }\n      byte[] foo=new byte[1];\n      for(int i=0; i<skip; i++){\n        cipher.update(foo, 0, 1, foo, 0);\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n  public boolean isCBC(){return false; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/BlowfishCBC.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.spec.*;\n\npublic class BlowfishCBC implements Cipher{\n  private static final int ivsize=8;\n  private static final int bsize=16;\n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    String pad=\"NoPadding\";      \n//  if(padding) pad=\"PKCS5Padding\";\n    byte[] tmp;\n    if(iv.length>ivsize){\n      tmp=new byte[ivsize];\n      System.arraycopy(iv, 0, tmp, 0, tmp.length);\n      iv=tmp;\n    }\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n    try{\n      SecretKeySpec skeySpec = new SecretKeySpec(key, \"Blowfish\");\n      cipher=javax.crypto.Cipher.getInstance(\"Blowfish/CBC/\"+pad);\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    skeySpec, new IvParameterSpec(iv));\n      }\n    }\n    catch(Exception e){\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n  public boolean isCBC(){return true; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/DH.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.math.BigInteger;\nimport java.security.*;\nimport javax.crypto.*;\nimport javax.crypto.spec.*;\nimport com.jcraft.jsch.JSchException;\n\npublic class DH implements com.jcraft.jsch.DH{\n  BigInteger p;\n  BigInteger g;\n  BigInteger e;  // my public key\n  byte[] e_array;\n  BigInteger f;  // your public key\n  BigInteger K;  // shared secret key\n  byte[] K_array;\n\n  private KeyPairGenerator myKpairGen;\n  private KeyAgreement myKeyAgree;\n  public void init() throws Exception{\n    myKpairGen=KeyPairGenerator.getInstance(\"DH\");\n    myKeyAgree=KeyAgreement.getInstance(\"DH\");\n  }\n  public byte[] getE() throws Exception{\n    if(e==null){\n      DHParameterSpec dhSkipParamSpec=new DHParameterSpec(p, g);\n      myKpairGen.initialize(dhSkipParamSpec);\n      KeyPair myKpair=myKpairGen.generateKeyPair();\n      myKeyAgree.init(myKpair.getPrivate());\n      e=((javax.crypto.interfaces.DHPublicKey)(myKpair.getPublic())).getY();\n      e_array=e.toByteArray();\n    }\n    return e_array;\n  }\n  public byte[] getK() throws Exception{\n    if(K==null){\n      KeyFactory myKeyFac=KeyFactory.getInstance(\"DH\");\n      DHPublicKeySpec keySpec=new DHPublicKeySpec(f, p, g);\n      PublicKey yourPubKey=myKeyFac.generatePublic(keySpec);\n      myKeyAgree.doPhase(yourPubKey, true);\n      byte[] mySharedSecret=myKeyAgree.generateSecret();\n      K=new BigInteger(1, mySharedSecret);\n      K_array=K.toByteArray();\n      K_array=mySharedSecret;\n    }\n    return K_array;\n  }\n  public void setP(byte[] p){ setP(new BigInteger(1, p)); }\n  public void setG(byte[] g){ setG(new BigInteger(1, g)); }\n  public void setF(byte[] f){ setF(new BigInteger(1, f)); }\n  void setP(BigInteger p){this.p=p;}\n  void setG(BigInteger g){this.g=g;}\n  void setF(BigInteger f){this.f=f;}\n\n  // e, f must be in [1, p-1].\n  public void checkRange() throws Exception {\n    /*\n    checkRange(e);\n    checkRange(f);\n    */\n  }\n\n  private void checkRange(BigInteger tmp) throws Exception {\n    BigInteger one = BigInteger.ONE;\n    BigInteger p_1 = p.subtract(one);\n    // !(1<tmp && tmp<p-1)  We expect tmp is in the range [2, p-2].\n    if(!(one.compareTo(tmp) < 0 && tmp.compareTo(p_1) < 0)){\n      throw new JSchException(\"invalid DH value\");\n   }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/ECDH256.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n \npublic class ECDH256 extends ECDHN implements com.jcraft.jsch.ECDH {\n  public void init() throws Exception {\n    super.init(256);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/ECDH384.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n \npublic class ECDH384 extends ECDHN implements com.jcraft.jsch.ECDH {\n  public void init() throws Exception {\n    super.init(384);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/ECDH521.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n \npublic class ECDH521 extends ECDHN implements com.jcraft.jsch.ECDH {\n  public void init() throws Exception {\n    super.init(521);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/ECDHN.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.math.BigInteger;\nimport java.security.*;\nimport javax.crypto.*;\nimport java.security.spec.*;\nimport java.security.interfaces.*;\n \npublic class ECDHN implements com.jcraft.jsch.ECDH {\n  byte[] Q_array;\n  ECPublicKey publicKey;\n\n  private KeyAgreement myKeyAgree;\n  public void init(int size) throws Exception{\n    myKeyAgree = KeyAgreement.getInstance(\"ECDH\");\n    KeyPairGenECDSA kpair = new KeyPairGenECDSA();\n    kpair.init(size);\n    publicKey = kpair.getPublicKey();\n    byte[] r = kpair.getR();\n    byte[] s = kpair.getS();\n    Q_array = toPoint(r, s);\n    myKeyAgree.init(kpair.getPrivateKey());\n  }\n\n  public byte[] getQ() throws Exception{\n    return Q_array;\n  }\n\n  public byte[] getSecret(byte[] r, byte[] s) throws Exception{\n\n    KeyFactory kf = KeyFactory.getInstance(\"EC\");\n    ECPoint w = new ECPoint(new BigInteger(1, r), new BigInteger(1, s));\n    ECPublicKeySpec spec = new ECPublicKeySpec(w, publicKey.getParams());\n    PublicKey theirPublicKey = kf.generatePublic(spec);\n    myKeyAgree.doPhase(theirPublicKey, true);\n    return myKeyAgree.generateSecret();\n  }\n\n  private static BigInteger two = BigInteger.ONE.add(BigInteger.ONE);\n  private static BigInteger three = two.add(BigInteger.ONE);\n\n  // SEC 1: Elliptic Curve Cryptography, Version 2.0\n  // http://www.secg.org/sec1-v2.pdf\n  // 3.2.2.1 Elliptic Curve Public Key Validation Primitive\n  public boolean validate(byte[] r, byte[] s) throws Exception{\n    BigInteger x = new BigInteger(1, r);\n    BigInteger y = new BigInteger(1, s);\n\n    // Step.1\n    //   Check that Q != O\n    ECPoint w = new ECPoint(x, y);\n    if(w.equals(ECPoint.POINT_INFINITY)){\n      return false;\n    }\n\n    // Step.2\n    // If T represents elliptic curve domain parameters over Fp,\n    // check that xQ and yQ are integers in the interval [0, p-1],\n    // and that:\n    //   y^2 = x^3 + x*a + b (mod p)\n\n    ECParameterSpec params = publicKey.getParams();\n    EllipticCurve curve = params.getCurve();\n    BigInteger p=((ECFieldFp)curve.getField()).getP(); //nistp should be Fp. \n\n    // xQ and yQ should be integers in the interval [0, p-1]\n    BigInteger p_sub1=p.subtract(BigInteger.ONE);\n    if(!(x.compareTo(p_sub1)<=0 && y.compareTo(p_sub1)<=0)){\n      return false;\n    }\n\n    // y^2 = x^3 + x*a + b (mod p)\n    BigInteger tmp=x.multiply(curve.getA()).\n                     add(curve.getB()).\n                     add(x.modPow(three, p)).\n                     mod(p);\n    BigInteger y_2=y.modPow(two, p);\n    if(!(y_2.equals(tmp))){ \n      return false;\n    }\n\n    // Step.3\n    //   Check that nQ = O.\n    // Unfortunately, JCE does not provide the point multiplication method.\n    /*\n    if(!w.multiply(params.getOrder()).equals(ECPoint.POINT_INFINITY)){\n      return false;\n    }\n    */\n    return true;\n  }\n\n  private byte[] toPoint(byte[] r_array, byte[] s_array) {\n    byte[] tmp = new byte[1+r_array.length+s_array.length];\n    tmp[0]=0x04;\n    System.arraycopy(r_array, 0, tmp, 1, r_array.length);\n    System.arraycopy(s_array, 0, tmp, 1+r_array.length, s_array.length);\n    return tmp;\n  }\n  private byte[] insert0(byte[] buf){\n    if ((buf[0] & 0x80) == 0) return buf;\n    byte[] tmp = new byte[buf.length+1];\n    System.arraycopy(buf, 0, tmp, 1, buf.length);\n    bzero(buf);\n    return tmp;\n  }\n  private byte[] chop0(byte[] buf){\n    if(buf[0]!=0) return buf;\n    byte[] tmp = new byte[buf.length-1];\n    System.arraycopy(buf, 1, tmp, 0, tmp.length);\n    bzero(buf);\n    return tmp;\n  }\n  private void bzero(byte[] buf){\n    for(int i = 0; i<buf.length; i++) buf[i]=0;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/HMAC.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2012-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.MAC;\nimport javax.crypto.*;\nimport javax.crypto.spec.*;\n\nabstract class HMAC implements MAC {\n  protected String name;\n  protected int bsize;\n  protected String algorithm;\n  private Mac mac;\n\n  public int getBlockSize() {\n    return bsize;\n  };\n\n  public void init(byte[] key) throws Exception {\n    if(key.length>bsize){\n      byte[] tmp = new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, bsize);\t  \n      key = tmp;\n    }\n    SecretKeySpec skey = new SecretKeySpec(key, algorithm);\n    mac = Mac.getInstance(algorithm);\n    mac.init(skey);\n  } \n\n  private final byte[] tmp = new byte[4];\n  public void update(int i){\n    tmp[0] = (byte)(i>>>24);\n    tmp[1] = (byte)(i>>>16);\n    tmp[2] = (byte)(i>>>8);\n    tmp[3] = (byte)i;\n    update(tmp, 0, 4);\n  }\n\n  public void update(byte foo[], int s, int l){\n    mac.update(foo, s, l);      \n  }\n\n  public void doFinal(byte[] buf, int offset){\n    try{\n      mac.doFinal(buf, offset);\n    }\n    catch(ShortBufferException e){\n      System.err.println(e);\n    }\n  }\n\n  public String getName(){\n    return name;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/HMACMD5.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.MAC;\nimport javax.crypto.*;\nimport javax.crypto.spec.*;\n\npublic class HMACMD5 extends HMAC {\n  public HMACMD5(){\n    name = \"hmac-md5\";\n    bsize = 16;\n    algorithm = \"HmacMD5\";\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/HMACMD596.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\npublic class HMACMD596 extends HMACMD5 {\n  public HMACMD596(){\n    name=\"hmac-md5-96\";\n  }\n\n  public int getBlockSize(){\n    return 12;\n  };\n\n  private final byte[] _buf16 = new byte[16];\n  public void doFinal(byte[] buf, int offset){\n    super.doFinal(_buf16, 0);\n    System.arraycopy(_buf16, 0, buf, offset, 12);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/HMACSHA1.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\npublic class HMACSHA1 extends HMAC {\n  public HMACSHA1(){\n    name = \"hmac-sha1\";\n    bsize = 20;\n    algorithm = \"HmacSHA1\";\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/HMACSHA196.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\npublic class HMACSHA196 extends HMACSHA1 {\n\n  public HMACSHA196(){\n    name = \"hmac-sha1-96\";\n  }\n\n  public int getBlockSize(){\n    return 12;\n  };\n\n  private final byte[] _buf20 = new byte[20];\n  public void doFinal(byte[] buf, int offset){\n    super.doFinal(_buf20, 0);\n    System.arraycopy(_buf20, 0, buf, offset, 12);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/HMACSHA256.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2012-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\npublic class HMACSHA256 extends HMAC {\n  public HMACSHA256(){\n    name = \"hmac-sha2-256\";\n    bsize = 32;\n    algorithm = \"HmacSHA256\";\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/HMACSHA512.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2012-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\npublic class HMACSHA512 extends HMAC {\n  public HMACSHA512(){\n    name = \"hmac-sha2-512\";\n    bsize = 64;\n    algorithm = \"HmacSHA512\";\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/KeyPairGenDSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.security.*;\nimport java.security.interfaces.*;\n\npublic class KeyPairGenDSA implements com.jcraft.jsch.KeyPairGenDSA{\n  byte[] x;  // private\n  byte[] y;  // public\n  byte[] p;\n  byte[] q;\n  byte[] g;\n\n  public void init(int key_size) throws Exception{\n    KeyPairGenerator keyGen = KeyPairGenerator.getInstance(\"DSA\");\n    keyGen.initialize(key_size, new SecureRandom());\n    KeyPair pair = keyGen.generateKeyPair();\n    PublicKey pubKey=pair.getPublic();\n    PrivateKey prvKey=pair.getPrivate();\n\n    x=((DSAPrivateKey)prvKey).getX().toByteArray();\n    y=((DSAPublicKey)pubKey).getY().toByteArray();\n\n    DSAParams params=((DSAKey)prvKey).getParams();\n    p=params.getP().toByteArray();\n    q=params.getQ().toByteArray();\n    g=params.getG().toByteArray();\n  }\n  public byte[] getX(){return x;}\n  public byte[] getY(){return y;}\n  public byte[] getP(){return p;}\n  public byte[] getQ(){return q;}\n  public byte[] getG(){return g;}\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/KeyPairGenECDSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.security.*;\nimport java.security.interfaces.*;\nimport java.security.spec.*;\nimport com.jcraft.jsch.JSchException;\n\npublic class KeyPairGenECDSA implements com.jcraft.jsch.KeyPairGenECDSA {\n  byte[] d;\n  byte[] r;\n  byte[] s;\n  ECPublicKey pubKey;\n  ECPrivateKey prvKey;\n  ECParameterSpec params;\n  public void init(int key_size) throws Exception {\n    String name=null;\n    if(key_size==256) name=\"secp256r1\";\n    else if(key_size==384) name=\"secp384r1\";\n    else if(key_size==521) name=\"secp521r1\";\n    else throw new JSchException(\"unsupported key size: \"+key_size);\n\n    for(int i = 0; i<1000; i++) {\n      KeyPairGenerator kpg = KeyPairGenerator.getInstance(\"EC\");\n      ECGenParameterSpec ecsp = new ECGenParameterSpec(name);\n      kpg.initialize(ecsp);\n      KeyPair kp = kpg.genKeyPair();\n      prvKey = (ECPrivateKey)kp.getPrivate();\n      pubKey = (ECPublicKey)kp.getPublic();\n      params=pubKey.getParams();\n      d=((ECPrivateKey)prvKey).getS().toByteArray();\n      ECPoint w = pubKey.getW();\n      r = w.getAffineX().toByteArray();\n      s = w.getAffineY().toByteArray();\n\n      if(r.length!=s.length) continue;\n      if(key_size==256 && r.length==32) break;\n      if(key_size==384 && r.length==48) break;\n      if(key_size==521 && r.length==66) break;\n    }\n    if(d.length<r.length){\n      d=insert0(d);\n    }\n  }\n  public byte[] getD(){return d;}\n  public byte[] getR(){return r;}\n  public byte[] getS(){return s;}\n  ECPublicKey getPublicKey(){ return pubKey; }\n  ECPrivateKey getPrivateKey(){ return prvKey; }\n\n  private byte[] insert0(byte[] buf){\n//    if ((buf[0] & 0x80) == 0) return buf;\n    byte[] tmp = new byte[buf.length+1];\n    System.arraycopy(buf, 0, tmp, 1, buf.length);\n    bzero(buf);\n    return tmp;\n  }\n  private byte[] chop0(byte[] buf){\n    if(buf[0]!=0 || (buf[1]&0x80)==0) return buf;\n    byte[] tmp = new byte[buf.length-1];\n    System.arraycopy(buf, 1, tmp, 0, tmp.length);\n    bzero(buf);\n    return tmp;\n  }\n  private void bzero(byte[] buf){\n    for(int i = 0; i<buf.length; i++) buf[i]=0;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/KeyPairGenRSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.security.*;\nimport java.security.interfaces.*;\n\npublic class KeyPairGenRSA implements com.jcraft.jsch.KeyPairGenRSA{\n  byte[] d;  // private\n  byte[] e;  // public\n  byte[] n;\n\n  byte[] c; //  coefficient\n  byte[] ep; // exponent p\n  byte[] eq; // exponent q\n  byte[] p;  // prime p\n  byte[] q;  // prime q\n\n  public void init(int key_size) throws Exception{\n    KeyPairGenerator keyGen = KeyPairGenerator.getInstance(\"RSA\");\n    keyGen.initialize(key_size, new SecureRandom());\n    KeyPair pair = keyGen.generateKeyPair();\n\n    PublicKey pubKey=pair.getPublic();\n    PrivateKey prvKey=pair.getPrivate();\n\n    d=((RSAPrivateKey)prvKey).getPrivateExponent().toByteArray();\n    e=((RSAPublicKey)pubKey).getPublicExponent().toByteArray();\n    n=((RSAPrivateKey)prvKey).getModulus().toByteArray();\n\n    c=((RSAPrivateCrtKey)prvKey).getCrtCoefficient().toByteArray();\n    ep=((RSAPrivateCrtKey)prvKey).getPrimeExponentP().toByteArray();\n    eq=((RSAPrivateCrtKey)prvKey).getPrimeExponentQ().toByteArray();\n    p=((RSAPrivateCrtKey)prvKey).getPrimeP().toByteArray();\n    q=((RSAPrivateCrtKey)prvKey).getPrimeQ().toByteArray();\n  }\n  public byte[] getD(){return d;}\n  public byte[] getE(){return e;}\n  public byte[] getN(){return n;}\n  public byte[] getC(){return c;}\n  public byte[] getEP(){return ep;}\n  public byte[] getEQ(){return eq;}\n  public byte[] getP(){return p;}\n  public byte[] getQ(){return q;}\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/MD5.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.HASH;\n\nimport java.security.*;\n\npublic class MD5 implements HASH{\n  MessageDigest md;\n  public int getBlockSize(){return 16;}\n  public void init() throws Exception{\n    try{ md=MessageDigest.getInstance(\"MD5\"); }\n    catch(Exception e){\n      System.err.println(e);\n    }\n  }\n  public void update(byte[] foo, int start, int len) throws Exception{\n    md.update(foo, start, len);\n  }\n  public byte[] digest() throws Exception{\n    return md.digest();\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/PBKDF.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2013-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.HASH;\n\nimport javax.crypto.spec.PBEKeySpec;\nimport javax.crypto.SecretKeyFactory;\nimport java.security.spec.InvalidKeySpecException;\nimport java.security.NoSuchAlgorithmException;\n\npublic class PBKDF implements com.jcraft.jsch.PBKDF{\n  public byte[] getKey(byte[] _pass, byte[] salt, int iterations, int size){\n    char[] pass=new char[_pass.length];\n    for(int i = 0; i < _pass.length; i++){\n      pass[i]=(char)(_pass[i]&0xff);\n    }\n    try {\n      PBEKeySpec spec =\n        new PBEKeySpec(pass, salt, iterations, size*8);\n      SecretKeyFactory skf =\n        SecretKeyFactory.getInstance(\"PBKDF2WithHmacSHA1\");\n      byte[] key = skf.generateSecret(spec).getEncoded();\n      return key;\n    }\n    catch(InvalidKeySpecException e){\n    }\n    catch(NoSuchAlgorithmException e){\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/Random.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.security.SecureRandom;\n\npublic class Random implements com.jcraft.jsch.Random{\n  private byte[] tmp=new byte[16];\n  private SecureRandom random=null;\n  public Random(){\n\n    // We hope that 'new SecureRandom()' will use NativePRNG algorithm\n    // on Sun's Java5 for GNU/Linux and Solaris.\n    // It seems NativePRNG refers to /dev/urandom and it must not be blocked,\n    // but NativePRNG is slower than SHA1PRNG ;-<\n    // TIPS: By adding option '-Djava.security.egd=file:/dev/./urandom'\n    //       SHA1PRNG will be used instead of NativePRNG.\n    // On MacOSX, 'new SecureRandom()' will use NativePRNG algorithm and\n    // it is also slower than SHA1PRNG.\n    // On Windows, 'new SecureRandom()' will use SHA1PRNG algorithm.\n    random=new SecureRandom();\n\n    /*\n    try{ \n      random=SecureRandom.getInstance(\"SHA1PRNG\"); \n      return;\n    }\n    catch(java.security.NoSuchAlgorithmException e){ \n      // System.err.println(e); \n    }\n\n    // The following code is for IBM's JCE\n    try{ \n      random=SecureRandom.getInstance(\"IBMSecureRandom\"); \n      return;\n    }\n    catch(java.security.NoSuchAlgorithmException ee){ \n      //System.err.println(ee); \n    }\n    */\n  }\n  public void fill(byte[] foo, int start, int len){\n    /*\n    // This case will not become true in our usage.\n    if(start==0 && foo.length==len){\n      random.nextBytes(foo);\n      return;\n    }\n    */\n    if(len>tmp.length){ tmp=new byte[len]; }\n    random.nextBytes(tmp);\n    System.arraycopy(tmp, 0, foo, start, len);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/SHA1.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.HASH;\n\nimport java.security.*;\n\npublic class SHA1 implements HASH{\n  MessageDigest md;\n  public int getBlockSize(){return 20;}\n  public void init() throws Exception{\n    try{ md=MessageDigest.getInstance(\"SHA-1\"); }\n    catch(Exception e){\n      System.err.println(e);\n    }\n  }\n  public void update(byte[] foo, int start, int len) throws Exception{\n    md.update(foo, start, len);\n  }\n  public byte[] digest() throws Exception{\n    return md.digest();\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/SHA256.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.HASH;\n\nimport java.security.*;\n\npublic class SHA256 implements HASH {\n  MessageDigest md;\n  public int getBlockSize(){return 32;}\n  public void init() throws Exception {\n    try{ md=MessageDigest.getInstance(\"SHA-256\"); }\n    catch(Exception e){\n      System.err.println(e);\n    }\n  }\n  public void update(byte[] foo, int start, int len) throws Exception {\n    md.update(foo, start, len);\n  }\n  public byte[] digest() throws Exception {\n    return md.digest();\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/SHA384.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.security.*;\n\npublic class SHA384 implements com.jcraft.jsch.HASH {\n  MessageDigest md;\n  public int getBlockSize(){return 48;}\n  public void init() throws Exception {\n    try{ md=MessageDigest.getInstance(\"SHA-384\"); }\n    catch(Exception e){\n      System.err.println(e);\n    }\n  }\n  public void update(byte[] foo, int start, int len) throws Exception {\n    md.update(foo, start, len);\n  }\n  public byte[] digest() throws Exception {\n    return md.digest();\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/SHA512.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.security.*;\n\npublic class SHA512 implements com.jcraft.jsch.HASH {\n  MessageDigest md;\n  public int getBlockSize(){return 64;}\n  public void init() throws Exception {\n    try{ md=MessageDigest.getInstance(\"SHA-512\"); }\n    catch(Exception e){\n      System.err.println(e);\n    }\n  }\n  public void update(byte[] foo, int start, int len) throws Exception {\n    md.update(foo, start, len);\n  }\n  public byte[] digest() throws Exception {\n    return md.digest();\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/SignatureDSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.math.BigInteger;\nimport java.security.*;\nimport java.security.spec.*;\n\npublic class SignatureDSA implements com.jcraft.jsch.SignatureDSA{\n\n  java.security.Signature signature;\n  KeyFactory keyFactory;\n\n  public void init() throws Exception{\n    signature=java.security.Signature.getInstance(\"SHA1withDSA\");\n    keyFactory=KeyFactory.getInstance(\"DSA\");\n  }     \n  public void setPubKey(byte[] y, byte[] p, byte[] q, byte[] g) throws Exception{\n    DSAPublicKeySpec dsaPubKeySpec = \n\tnew DSAPublicKeySpec(new BigInteger(y),\n\t\t\t     new BigInteger(p),\n\t\t\t     new BigInteger(q),\n\t\t\t     new BigInteger(g));\n    PublicKey pubKey=keyFactory.generatePublic(dsaPubKeySpec);\n    signature.initVerify(pubKey);\n  }\n  public void setPrvKey(byte[] x, byte[] p, byte[] q, byte[] g) throws Exception{\n    DSAPrivateKeySpec dsaPrivKeySpec = \n\tnew DSAPrivateKeySpec(new BigInteger(x),\n\t\t\t      new BigInteger(p),\n\t\t\t      new BigInteger(q),\n\t\t\t      new BigInteger(g));\n    PrivateKey prvKey = keyFactory.generatePrivate(dsaPrivKeySpec);\n    signature.initSign(prvKey);\n  }\n  public byte[] sign() throws Exception{\n    byte[] sig=signature.sign();      \n/*\nSystem.err.print(\"sign[\"+sig.length+\"] \");\nfor(int i=0; i<sig.length;i++){\nSystem.err.print(Integer.toHexString(sig[i]&0xff)+\":\");\n}\nSystem.err.println(\"\");\n*/\n    // sig is in ASN.1\n    // SEQUENCE::={ r INTEGER, s INTEGER }\n    int len=0;\t\n    int index=3;\n    len=sig[index++]&0xff;\n//System.err.println(\"! len=\"+len);\n    byte[] r=new byte[len];\n    System.arraycopy(sig, index, r, 0, r.length);\n    index=index+len+1;\n    len=sig[index++]&0xff;\n//System.err.println(\"!! len=\"+len);\n    byte[] s=new byte[len];\n    System.arraycopy(sig, index, s, 0, s.length);\n\n    byte[] result=new byte[40];\n\n    // result must be 40 bytes, but length of r and s may not be 20 bytes  \n\n    System.arraycopy(r, (r.length>20)?1:0,\n\t\t     result, (r.length>20)?0:20-r.length,\n\t\t     (r.length>20)?20:r.length);\n    System.arraycopy(s, (s.length>20)?1:0,\n\t\t     result, (s.length>20)?20:40-s.length,\n\t\t     (s.length>20)?20:s.length);\n \n//  System.arraycopy(sig, (sig[3]==20?4:5), result, 0, 20);\n//  System.arraycopy(sig, sig.length-20, result, 20, 20);\n\n    return result;\n  }\n  public void update(byte[] foo) throws Exception{\n   signature.update(foo);\n  }\n  public boolean verify(byte[] sig) throws Exception{\n    int i=0;\n    int j=0;\n    byte[] tmp;\n\n    if(sig[0]==0 && sig[1]==0 && sig[2]==0){\n    j=((sig[i++]<<24)&0xff000000)|((sig[i++]<<16)&0x00ff0000)|\n\t((sig[i++]<<8)&0x0000ff00)|((sig[i++])&0x000000ff);\n    i+=j;\n    j=((sig[i++]<<24)&0xff000000)|((sig[i++]<<16)&0x00ff0000)|\n\t((sig[i++]<<8)&0x0000ff00)|((sig[i++])&0x000000ff);\n    tmp=new byte[j]; \n    System.arraycopy(sig, i, tmp, 0, j); sig=tmp;\n    }\n\n    // ASN.1\n    int frst=((sig[0]&0x80)!=0?1:0);\n    int scnd=((sig[20]&0x80)!=0?1:0);\n    //System.err.println(\"frst: \"+frst+\", scnd: \"+scnd);\n\n    int length=sig.length+6+frst+scnd;\n    tmp=new byte[length];\n    tmp[0]=(byte)0x30; tmp[1]=(byte)0x2c; \n    tmp[1]+=frst; tmp[1]+=scnd;\n    tmp[2]=(byte)0x02; tmp[3]=(byte)0x14;\n    tmp[3]+=frst;\n    System.arraycopy(sig, 0, tmp, 4+frst, 20);\n    tmp[4+tmp[3]]=(byte)0x02; tmp[5+tmp[3]]=(byte)0x14;\n    tmp[5+tmp[3]]+=scnd;\n    System.arraycopy(sig, 20, tmp, 6+tmp[3]+scnd, 20);\n    sig=tmp;\n\n/*\n    tmp=new byte[sig.length+6];\n    tmp[0]=(byte)0x30; tmp[1]=(byte)0x2c; \n    tmp[2]=(byte)0x02; tmp[3]=(byte)0x14;\n    System.arraycopy(sig, 0, tmp, 4, 20);\n    tmp[24]=(byte)0x02; tmp[25]=(byte)0x14;\n    System.arraycopy(sig, 20, tmp, 26, 20); sig=tmp;\n*/  \n    return signature.verify(sig);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/SignatureECDSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.math.BigInteger;\nimport java.security.*;\nimport java.security.spec.*;\nimport com.jcraft.jsch.Buffer;\n\npublic class SignatureECDSA implements com.jcraft.jsch.SignatureECDSA {\n\n  Signature signature;\n  KeyFactory keyFactory;\n\n  public void init() throws Exception{\n    signature=java.security.Signature.getInstance(\"SHA256withECDSA\");\n    keyFactory=KeyFactory.getInstance(\"EC\");\n  }     \n\n  public void setPubKey(byte[] r, byte[] s) throws Exception{\n\n    // r and s must be unsigned values.\n    r=insert0(r);\n    s=insert0(s);\n\n    String name=\"secp256r1\";\n    if(r.length>=64) name=\"secp521r1\";\n    else if(r.length>=48) name=\"secp384r1\";\n\n    AlgorithmParameters param = AlgorithmParameters.getInstance(\"EC\");\n    param.init(new ECGenParameterSpec(name));\n    ECParameterSpec ecparam =\n      (ECParameterSpec)param.getParameterSpec(ECParameterSpec.class);\n    ECPoint w = new ECPoint(new BigInteger(1, r), new BigInteger(1, s));\n    PublicKey pubKey = \n      keyFactory.generatePublic(new ECPublicKeySpec(w, ecparam));\n    signature.initVerify(pubKey);\n  }\n\n  public void setPrvKey(byte[] d) throws Exception{\n\n    // d must be unsigned value.\n    d=insert0(d);\n\n    String name=\"secp256r1\";\n    if(d.length>=64) name=\"secp521r1\";\n    else if(d.length>=48) name=\"secp384r1\";\n\n    AlgorithmParameters param = AlgorithmParameters.getInstance(\"EC\");\n    param.init(new ECGenParameterSpec(name));\n    ECParameterSpec ecparam =\n      (ECParameterSpec)param.getParameterSpec(ECParameterSpec.class);\n    BigInteger _d = new BigInteger(1, d);\n    PrivateKey prvKey = \n      keyFactory.generatePrivate(new ECPrivateKeySpec(_d, ecparam));\n    signature.initSign(prvKey);\n  }\n  public byte[] sign() throws Exception{\n    byte[] sig=signature.sign();\n\n    // It seems that the output from SunEC is in ASN.1,\n    // so we have to convert it.\n    if(sig[0]==0x30 &&                                      // in ASN.1\n       ((sig[1]+2 == sig.length) ||\n        ((sig[1]&0x80)!=0 && (sig[2]&0xff)+3==sig.length))){// 2bytes for len\n\n      int index=3;\n      if((sig[1]&0x80)!=0 && (sig[2]&0xff)+3==sig.length)\n        index=4;\n\n      byte[] r = new byte[sig[index]];\n      byte[] s = new byte[sig[index+2+sig[index]]];\n      System.arraycopy(sig, index+1, r, 0, r.length);\n      System.arraycopy(sig, index+3+sig[index], s, 0, s.length);\n\n      r = chop0(r);\n      s = chop0(s);\n\n      Buffer buf = new Buffer();\n      buf.putMPInt(r);\n      buf.putMPInt(s);\n\n      sig=new byte[buf.getLength()];\n      buf.setOffSet(0);\n      buf.getByte(sig);\n    }\n\n    return sig;\n  }\n  public void update(byte[] foo) throws Exception{\n   signature.update(foo);\n  }\n  public boolean verify(byte[] sig) throws Exception{\n\n    // It seems that SunEC expects ASN.1 data,\n    // so we have to convert it.\n    if(!(sig[0]==0x30 &&                                    // not in ASN.1\n         ((sig[1]+2 == sig.length) ||\n          ((sig[1]&0x80)!=0 && (sig[2]&0xff)+3==sig.length)))) {\n      Buffer b = new Buffer(sig);\n\n      b.getString();  // ecdsa-sha2-nistp256\n      b.getInt();\n\n      byte[] r = b.getMPInt();\n      byte[] s = b.getMPInt();\n\n      r=insert0(r);\n      s=insert0(s);\n\n      byte[] asn1 = null;\n      if(r.length<64){\n        asn1 = new byte[6+r.length+s.length];\n        asn1[0] = (byte)0x30;\n        asn1[1] = (byte)(4+r.length+s.length);\n        asn1[2] = (byte)0x02;\n        asn1[3] = (byte)r.length;\n        System.arraycopy(r, 0, asn1, 4, r.length);\n        asn1[r.length+4] = (byte)0x02;\n        asn1[r.length+5] = (byte)s.length;\n        System.arraycopy(s, 0, asn1, (6+r.length), s.length);\n      }\n      else {\n        asn1 = new byte[6+r.length+s.length+1];\n        asn1[0] = (byte)0x30;\n        asn1[1] = (byte)0x81;\n        asn1[2] = (byte)(4+r.length+s.length);\n        asn1[3] = (byte)0x02;\n        asn1[4] = (byte)r.length;\n        System.arraycopy(r, 0, asn1, 5, r.length);\n        asn1[r.length+5] = (byte)0x02;\n        asn1[r.length+6] = (byte)s.length;\n        System.arraycopy(s, 0, asn1, (7+r.length), s.length);\n      }\n      sig=asn1;\n    }\n\n    return signature.verify(sig); \n  }\n\n  private byte[] insert0(byte[] buf){\n    if ((buf[0] & 0x80) == 0) return buf;\n    byte[] tmp = new byte[buf.length+1];\n    System.arraycopy(buf, 0, tmp, 1, buf.length);\n    bzero(buf);\n    return tmp;\n  }\n  private byte[] chop0(byte[] buf){\n    if(buf[0]!=0) return buf;\n    byte[] tmp = new byte[buf.length-1];\n    System.arraycopy(buf, 1, tmp, 0, tmp.length);\n    bzero(buf);\n    return tmp;\n  }\n\n  private void bzero(byte[] buf){\n    for(int i = 0; i<buf.length; i++) buf[i]=0;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/SignatureRSA.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport java.math.BigInteger;\nimport java.security.*;\nimport java.security.spec.*;\n\npublic class SignatureRSA implements com.jcraft.jsch.SignatureRSA{\n\n  java.security.Signature signature;\n  KeyFactory keyFactory;\n\n  public void init() throws Exception{\n    signature=java.security.Signature.getInstance(\"SHA1withRSA\");\n    keyFactory=KeyFactory.getInstance(\"RSA\");\n  }     \n  public void setPubKey(byte[] e, byte[] n) throws Exception{\n    RSAPublicKeySpec rsaPubKeySpec = \n\tnew RSAPublicKeySpec(new BigInteger(n),\n\t\t\t     new BigInteger(e));\n    PublicKey pubKey=keyFactory.generatePublic(rsaPubKeySpec);\n    signature.initVerify(pubKey);\n  }\n  public void setPrvKey(byte[] d, byte[] n) throws Exception{\n    RSAPrivateKeySpec rsaPrivKeySpec = \n\tnew RSAPrivateKeySpec(new BigInteger(n),\n\t\t\t      new BigInteger(d));\n    PrivateKey prvKey = keyFactory.generatePrivate(rsaPrivKeySpec);\n    signature.initSign(prvKey);\n  }\n  public byte[] sign() throws Exception{\n    byte[] sig=signature.sign();      \n    return sig;\n  }\n  public void update(byte[] foo) throws Exception{\n   signature.update(foo);\n  }\n  public boolean verify(byte[] sig) throws Exception{\n    int i=0;\n    int j=0;\n    byte[] tmp;\n\n    if(sig[0]==0 && sig[1]==0 && sig[2]==0){\n    j=((sig[i++]<<24)&0xff000000)|((sig[i++]<<16)&0x00ff0000)|\n\t((sig[i++]<<8)&0x0000ff00)|((sig[i++])&0x000000ff);\n    i+=j;\n    j=((sig[i++]<<24)&0xff000000)|((sig[i++]<<16)&0x00ff0000)|\n\t((sig[i++]<<8)&0x0000ff00)|((sig[i++])&0x000000ff);\n    tmp=new byte[j]; \n    System.arraycopy(sig, i, tmp, 0, j); sig=tmp;\n    }\n//System.err.println(\"j=\"+j+\" \"+Integer.toHexString(sig[0]&0xff));\n    return signature.verify(sig);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/TripleDESCBC.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.*;\nimport javax.crypto.spec.*;\n\npublic class TripleDESCBC implements Cipher{\n  private static final int ivsize=8;\n  private static final int bsize=24;\n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    String pad=\"NoPadding\";      \n    //if(padding) pad=\"PKCS5Padding\";\n    byte[] tmp;\n    if(iv.length>ivsize){\n      tmp=new byte[ivsize];\n      System.arraycopy(iv, 0, tmp, 0, tmp.length);\n      iv=tmp;\n    }\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n\n    try{\n      cipher=javax.crypto.Cipher.getInstance(\"DESede/CBC/\"+pad);\n/*\n      // The following code does not work on IBM's JDK 1.4.1\n      SecretKeySpec skeySpec = new SecretKeySpec(key, \"DESede\");\n      cipher.init((mode==ENCRYPT_MODE?\n\t\t   javax.crypto.Cipher.ENCRYPT_MODE:\n\t\t   javax.crypto.Cipher.DECRYPT_MODE),\n\t\t  skeySpec, new IvParameterSpec(iv));\n*/\n      DESedeKeySpec keyspec=new DESedeKeySpec(key);\n      SecretKeyFactory keyfactory=SecretKeyFactory.getInstance(\"DESede\");\n      SecretKey _key=keyfactory.generateSecret(keyspec);\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    _key, new IvParameterSpec(iv));\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n  public boolean isCBC(){return true; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jce/TripleDESCTR.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2008-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jce;\n\nimport com.jcraft.jsch.Cipher;\nimport javax.crypto.*;\nimport javax.crypto.spec.*;\n\npublic class TripleDESCTR implements Cipher{\n  private static final int ivsize=8;\n  private static final int bsize=24;\n  private javax.crypto.Cipher cipher;    \n  public int getIVSize(){return ivsize;} \n  public int getBlockSize(){return bsize;}\n  public void init(int mode, byte[] key, byte[] iv) throws Exception{\n    String pad=\"NoPadding\";      \n    //if(padding) pad=\"PKCS5Padding\";\n    byte[] tmp;\n    if(iv.length>ivsize){\n      tmp=new byte[ivsize];\n      System.arraycopy(iv, 0, tmp, 0, tmp.length);\n      iv=tmp;\n    }\n    if(key.length>bsize){\n      tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, tmp.length);\n      key=tmp;\n    }\n\n    try{\n      cipher=javax.crypto.Cipher.getInstance(\"DESede/CTR/\"+pad);\n/*\n      // The following code does not work on IBM's JDK 1.4.1\n      SecretKeySpec skeySpec = new SecretKeySpec(key, \"DESede\");\n      cipher.init((mode==ENCRYPT_MODE?\n\t\t   javax.crypto.Cipher.ENCRYPT_MODE:\n\t\t   javax.crypto.Cipher.DECRYPT_MODE),\n\t\t  skeySpec, new IvParameterSpec(iv));\n*/\n      DESedeKeySpec keyspec=new DESedeKeySpec(key);\n      SecretKeyFactory keyfactory=SecretKeyFactory.getInstance(\"DESede\");\n      SecretKey _key=keyfactory.generateSecret(keyspec);\n      synchronized(javax.crypto.Cipher.class){\n        cipher.init((mode==ENCRYPT_MODE?\n                     javax.crypto.Cipher.ENCRYPT_MODE:\n                     javax.crypto.Cipher.DECRYPT_MODE),\n                    _key, new IvParameterSpec(iv));\n      }\n    }\n    catch(Exception e){\n      cipher=null;\n      throw e;\n    }\n  }\n  public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{\n    cipher.update(foo, s1, len, bar, s2);\n  }\n  public boolean isCBC(){return false; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jcraft/Compression.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2002-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jcraft;\nimport com.jcraft.jzlib.*;\nimport com.jcraft.jsch.*;\n\npublic class Compression implements com.jcraft.jsch.Compression {\n  static private final int BUF_SIZE=4096;\n  private final int buffer_margin=32+20; // AES256 + HMACSHA1\n  private int type;\n  private ZStream stream;\n  private byte[] tmpbuf=new byte[BUF_SIZE];\n\n  public Compression(){\n    stream=new ZStream();\n  }\n\n  public void init(int type, int level){\n    if(type==DEFLATER){\n      stream.deflateInit(level);\n      this.type=DEFLATER;\n    }\n    else if(type==INFLATER){\n      stream.inflateInit();\n      inflated_buf=new byte[BUF_SIZE];\n      this.type=INFLATER;\n    }\n  }\n\n  private byte[] inflated_buf;\n\n  public byte[] compress(byte[] buf, int start, int[] len){\n    stream.next_in=buf;\n    stream.next_in_index=start;\n    stream.avail_in=len[0]-start;\n    int status;\n    int outputlen=start;\n    byte[] outputbuf=buf;\n    int tmp=0;\n\n    do{\n      stream.next_out=tmpbuf;\n      stream.next_out_index=0;\n      stream.avail_out=BUF_SIZE;\n      status=stream.deflate(JZlib.Z_PARTIAL_FLUSH);\n      switch(status){\n        case JZlib.Z_OK:\n          tmp=BUF_SIZE-stream.avail_out;\n          if(outputbuf.length<outputlen+tmp+buffer_margin){\n            byte[] foo=new byte[(outputlen+tmp+buffer_margin)*2];\n            System.arraycopy(outputbuf, 0, foo, 0, outputbuf.length);\n            outputbuf=foo;\n          }\n          System.arraycopy(tmpbuf, 0, outputbuf, outputlen, tmp);\n          outputlen+=tmp;\n          break;\n        default:\n\t    System.err.println(\"compress: deflate returnd \"+status);\n      }\n    }\n    while(stream.avail_out==0);\n\n    len[0]=outputlen;\n    return outputbuf;\n  }\n\n  public byte[] uncompress(byte[] buffer, int start, int[] length){\n    int inflated_end=0;\n\n    stream.next_in=buffer;\n    stream.next_in_index=start;\n    stream.avail_in=length[0];\n\n    while(true){\n      stream.next_out=tmpbuf;\n      stream.next_out_index=0;\n      stream.avail_out=BUF_SIZE;\n      int status=stream.inflate(JZlib.Z_PARTIAL_FLUSH);\n      switch(status){\n        case JZlib.Z_OK:\n\t  if(inflated_buf.length<inflated_end+BUF_SIZE-stream.avail_out){\n            int len=inflated_buf.length*2;\n            if(len<inflated_end+BUF_SIZE-stream.avail_out)\n              len=inflated_end+BUF_SIZE-stream.avail_out;\n            byte[] foo=new byte[len];\n\t    System.arraycopy(inflated_buf, 0, foo, 0, inflated_end);\n\t    inflated_buf=foo;\n\t  }\n\t  System.arraycopy(tmpbuf, 0,\n\t\t\t   inflated_buf, inflated_end,\n\t\t\t   BUF_SIZE-stream.avail_out);\n\t  inflated_end+=(BUF_SIZE-stream.avail_out);\n          length[0]=inflated_end;\n\t  break;\n        case JZlib.Z_BUF_ERROR:\n          if(inflated_end>buffer.length-start){\n            byte[] foo=new byte[inflated_end+start];\n            System.arraycopy(buffer, 0, foo, 0, start);\n            System.arraycopy(inflated_buf, 0, foo, start, inflated_end);\n\t    buffer=foo;\n\t  }\n\t  else{\n            System.arraycopy(inflated_buf, 0, buffer, start, inflated_end);\n\t  }\n          length[0]=inflated_end;\n\t  return buffer;\n\tdefault:\n\t  System.err.println(\"uncompress: inflate returnd \"+status);\n          return null;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jcraft/HMAC.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jcraft;\n\nimport java.security.*;\n\nclass HMAC{\n\n  /*\n   * Refer to RFC2104.\n   *\n   * H(K XOR opad, H(K XOR ipad, text))\n   *\n   * where K is an n byte key\n   * ipad is the byte 0x36 repeated 64 times\n   * opad is the byte 0x5c repeated 64 times\n   * and text is the data being protected\n   */\n  private static final int B=64;\n  private byte[] k_ipad=null;\n  private byte[] k_opad=null;\n\n  private MessageDigest md=null;\n\n  private int bsize=0;\n\n  protected void setH(MessageDigest md){\n    this.md=md;\n    bsize=md.getDigestLength();\n  }\n\n  public int getBlockSize(){return bsize;};\n  public void init(byte[] key) throws Exception{\n    md.reset();\n    if(key.length>bsize){\n      byte[] tmp=new byte[bsize];\n      System.arraycopy(key, 0, tmp, 0, bsize);\t  \n      key=tmp;\n    }\n\n    /* if key is longer than B bytes reset it to key=MD5(key) */\n    if(key.length>B){\n      md.update(key, 0, key.length);\n      key=md.digest();\n    }\n\n    k_ipad=new byte[B];\n    System.arraycopy(key, 0, k_ipad, 0, key.length);\n    k_opad=new byte[B];\n    System.arraycopy(key, 0, k_opad, 0, key.length);\n\n    /* XOR key with ipad and opad values */\n    for(int i=0; i<B; i++) {\n      k_ipad[i]^=(byte)0x36;\n      k_opad[i]^=(byte)0x5c;\n    }\n\n    md.update(k_ipad, 0, B);\n  }\n\n  private final byte[] tmp=new byte[4];\n  public void update(int i){\n    tmp[0]=(byte)(i>>>24);\n    tmp[1]=(byte)(i>>>16);\n    tmp[2]=(byte)(i>>>8);\n    tmp[3]=(byte)i;\n    update(tmp, 0, 4);\n  }\n\n  public void update(byte foo[], int s, int l){\n    md.update(foo, s, l);\n  }\n\n  public void doFinal(byte[] buf, int offset){\n    byte[] result=md.digest();\n    md.update(k_opad, 0, B);\n    md.update(result, 0, bsize);\n    try{md.digest(buf, offset, bsize);}catch(Exception e){}\n    md.update(k_ipad, 0, B);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jcraft/HMACMD5.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jcraft;\n\nimport com.jcraft.jsch.MAC;\nimport java.security.*;\n\npublic class HMACMD5 extends HMAC implements MAC{\n  private static final String name=\"hmac-md5\";\n\n  public HMACMD5(){\n    super();\n    MessageDigest md=null;\n    try{ md=MessageDigest.getInstance(\"MD5\"); }\n    catch(Exception e){\n      System.err.println(e);\n    }\n    setH(md);\n  }\n\n  public String getName(){\n    return name;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jcraft/HMACMD596.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jcraft;\n\nimport com.jcraft.jsch.MAC;\n\npublic class HMACMD596 extends HMACMD5{\n\n  private static final String name=\"hmac-md5-96\";\n  private static final int BSIZE=12;\n\n  public int getBlockSize(){return BSIZE;};\n\n  private final byte[] _buf16=new byte[16];\n  public void doFinal(byte[] buf, int offset){\n    super.doFinal(_buf16, 0);\n    System.arraycopy(_buf16, 0, buf, offset, BSIZE);\n  }\n\n  public String getName(){\n    return name;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jcraft/HMACSHA1.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jcraft;\n\nimport com.jcraft.jsch.MAC;\nimport java.security.*;\n\npublic class HMACSHA1 extends HMAC implements MAC{\n  private static final String name=\"hmac-sha1\";\n\n  public HMACSHA1(){\n    super();\n    MessageDigest md=null;\n    try{ md=MessageDigest.getInstance(\"SHA-1\"); }\n    catch(Exception e){\n      System.err.println(e);\n    }\n    setH(md);\n  }\n\n  public String getName(){\n    return name;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jcraft/HMACSHA196.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jcraft;\n\nimport com.jcraft.jsch.MAC;\n\npublic class HMACSHA196 extends HMACSHA1{\n\n  private static final String name=\"hmac-sha1-96\";\n  private static final int BSIZE=12;\n\n  public int getBlockSize(){return BSIZE;};\n\n  private final byte[] _buf16=new byte[20];\n  public void doFinal(byte[] buf, int offset){\n    super.doFinal(_buf16, 0);\n    System.arraycopy(_buf16, 0, buf, offset, BSIZE);\n  }\n\n  public String getName(){\n    return name;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jsch/jgss/GSSContextKrb5.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2006-2015 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\npackage com.jcraft.jsch.jgss;\n\nimport com.jcraft.jsch.JSchException;\n\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\nimport org.ietf.jgss.GSSContext;\nimport org.ietf.jgss.GSSCredential;\nimport org.ietf.jgss.GSSException;\nimport org.ietf.jgss.GSSManager;\nimport org.ietf.jgss.GSSName;\nimport org.ietf.jgss.MessageProp;\nimport org.ietf.jgss.Oid;\n\npublic class GSSContextKrb5 implements com.jcraft.jsch.GSSContext{\n\n  private static final String pUseSubjectCredsOnly = \n    \"javax.security.auth.useSubjectCredsOnly\";\n  private static String useSubjectCredsOnly = \n    getSystemProperty(pUseSubjectCredsOnly);\n\n  private GSSContext context=null;\n  public void create(String user, String host) throws JSchException{\n    try{\n      // RFC 1964\n      Oid krb5=new Oid(\"1.2.840.113554.1.2.2\");\n      // Kerberos Principal Name Form\n      Oid principalName=new Oid(\"1.2.840.113554.1.2.2.1\");\n\n      GSSManager mgr=GSSManager.getInstance();\n\n      GSSCredential crd=null;\n      /*\n      try{\n        GSSName _user=mgr.createName(user, principalName);\n        crd=mgr.createCredential(_user,\n                                 GSSCredential.DEFAULT_LIFETIME,\n                                 krb5,\n                                 GSSCredential.INITIATE_ONLY);\n      }\n      catch(GSSException crdex){\n      }\n      */\n\n      String cname=host;\n      try{\n        cname=InetAddress.getByName(cname).getCanonicalHostName();\n      }\n      catch(UnknownHostException e){\n      }\n      GSSName _host=mgr.createName(\"host/\"+cname, principalName);\n\n      context=mgr.createContext(_host,\n                                krb5,\n                                crd,\n                                GSSContext.DEFAULT_LIFETIME);\n\n      // RFC4462  3.4.  GSS-API Session\n      //\n      // When calling GSS_Init_sec_context(), the client MUST set\n      // integ_req_flag to \"true\" to request that per-message integrity\n      // protection be supported for this context.  In addition,\n      // deleg_req_flag MAY be set to \"true\" to request access delegation, if\n      // requested by the user.\n      //\n      // Since the user authentication process by its nature authenticates\n      // only the client, the setting of mutual_req_flag is not needed for\n      // this process.  This flag SHOULD be set to \"false\".\n\n      // TODO: OpenSSH's sshd does accepts 'false' for mutual_req_flag\n      //context.requestMutualAuth(false);\n      context.requestMutualAuth(true);\n      context.requestConf(true);\n      context.requestInteg(true);             // for MIC\n      context.requestCredDeleg(true);\n      context.requestAnonymity(false);\n\n      return;\n    }\n    catch(GSSException ex){\n      throw new JSchException(ex.toString());\n    }\n  }\n\n  public boolean isEstablished(){\n    return context.isEstablished();\n  }\n\n  public byte[] init(byte[] token, int s, int l) throws JSchException {\n    try{\n      // Without setting \"javax.security.auth.useSubjectCredsOnly\" to \"false\",\n      // Sun's JVM for Un*x will show messages to stderr in\n      // processing context.initSecContext().\n      // This hack is not thread safe ;-<.\n      // If that property is explicitly given as \"true\" or \"false\",\n      // this hack must not be invoked.\n      if(useSubjectCredsOnly==null){\n        setSystemProperty(pUseSubjectCredsOnly, \"false\");\n      }\n      return context.initSecContext(token, 0, l);\n    }\n    catch(GSSException ex){\n      throw new JSchException(ex.toString());\n    }\n    catch(java.lang.SecurityException ex){\n      throw new JSchException(ex.toString());\n    }\n    finally{\n      if(useSubjectCredsOnly==null){\n        // By the default, it must be \"true\".\n        setSystemProperty(pUseSubjectCredsOnly, \"true\");\n      }\n    }\n  }\n\n  public byte[] getMIC(byte[] message, int s, int l){\n    try{\n      MessageProp prop =  new MessageProp(0, true);\n      return context.getMIC(message, s, l, prop);\n    }\n    catch(GSSException ex){\n      return null;\n    }\n  }\n\n  public void dispose(){\n    try{\n      context.dispose();\n    }\n    catch(GSSException ex){\n    }\n  }\n\n  private static String getSystemProperty(String key){\n    try{ return System.getProperty(key); }\n    catch(Exception e){ \n      // We are not allowed to get the System properties.\n      return null; \n    } \n  }\n\n  private static void setSystemProperty(String key, String value){\n    try{ System.setProperty(key, value); }\n    catch(Exception e){ \n      // We are not allowed to set the System properties.\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/Adler32.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal public class Adler32 implements Checksum {\n\n  // largest prime smaller than 65536\n  static final private int BASE=65521; \n  // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1\n  static final private int NMAX=5552;\n\n  private long s1=1L;\n  private long s2=0L;\n\n  public void reset(long init){\n    s1=init&0xffff;\n    s2=(init>>16)&0xffff;\n  }\n\n  public void reset(){\n    s1=1L;\n    s2=0L;\n  }\n\n  public long getValue(){\n    return ((s2<<16)|s1);\n  }\n\n  public void update(byte[] buf, int index, int len){\n\n    if(len==1){\n      s1+=buf[index++]&0xff; s2+=s1;\n      s1%=BASE;\n      s2%=BASE;\n      return;\n    }\n\n    int len1 = len/NMAX;\n    int len2 = len%NMAX;\n    while(len1-->0) {\n      int k=NMAX;\n      len-=k;\n      while(k-->0){\n\ts1+=buf[index++]&0xff; s2+=s1;\n      }\n      s1%=BASE;\n      s2%=BASE;\n    }\n\n    int k=len2;\n    len-=k;\n    while(k-->0){\n      s1+=buf[index++]&0xff; s2+=s1;\n    }\n    s1%=BASE;\n    s2%=BASE;\n  }\n\n  public Adler32 copy(){\n    Adler32 foo = new Adler32();\n    foo.s1 = this.s1;\n    foo.s2 = this.s2;\n    return foo;\n  }\n\n  // The following logic has come from zlib.1.2.\n  static long combine(long adler1, long adler2, long len2){\n    long BASEL = (long)BASE;\n    long sum1;\n    long sum2;\n    long rem;  // unsigned int\n\n    rem = len2 % BASEL;\n    sum1 = adler1 & 0xffffL;\n    sum2 = rem * sum1;\n    sum2 %= BASEL; // MOD(sum2);\n    sum1 += (adler2 & 0xffffL) + BASEL - 1;\n    sum2 += ((adler1 >> 16) & 0xffffL) + ((adler2 >> 16) & 0xffffL) + BASEL - rem;\n    if (sum1 >= BASEL) sum1 -= BASEL;\n    if (sum1 >= BASEL) sum1 -= BASEL;\n    if (sum2 >= (BASEL << 1)) sum2 -= (BASEL << 1);\n    if (sum2 >= BASEL) sum2 -= BASEL;\n    return sum1 | (sum2 << 16);\n  }\n\n/*\n  private java.util.zip.Adler32 adler=new java.util.zip.Adler32();\n  public void update(byte[] buf, int index, int len){\n    if(buf==null) {adler.reset();}\n    else{adler.update(buf, index, len);}\n  }\n  public void reset(){\n    adler.reset();\n  }\n  public void reset(long init){\n    if(init==1L){\n      adler.reset();\n    }\n    else{\n      System.err.println(\"unsupported operation\");\n    }\n  }\n  public long getValue(){\n    return adler.getValue();\n  }\n*/\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/CRC32.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal public class CRC32 implements Checksum {\n\n  /*\n   *  The following logic has come from RFC1952.\n   */\n  private int v = 0;\n  private static int[] crc_table = null;\n  static {\n    crc_table = new int[256];\n    for (int n = 0; n < 256; n++) {\n      int c = n;\n      for (int k = 8;  --k >= 0; ) {\n        if ((c & 1) != 0)\n\t  c = 0xedb88320 ^ (c >>> 1);\n        else\n          c = c >>> 1;\n      }\n      crc_table[n] = c;\n    }\n  }\n\n  public void update (byte[] buf, int index, int len) {\n    int c = ~v;\n    while (--len >= 0)\n      c = crc_table[(c^buf[index++])&0xff]^(c >>> 8);\n    v = ~c;\n  }\n\n  public void reset(){\n    v = 0;\n  }\n\n  public void reset(long vv){\n    v = (int)(vv&0xffffffffL);\n  }\n\n  public long getValue(){\n    return (long)(v&0xffffffffL);\n  }\n\n  // The following logic has come from zlib.1.2.\n  private static final int GF2_DIM = 32;\n  static long combine(long crc1, long crc2, long len2){\n    long row;\n    long[] even = new long[GF2_DIM];\n    long[] odd = new long[GF2_DIM];\n\n    // degenerate case (also disallow negative lengths)\n    if (len2 <= 0)\n      return crc1;\n\n    // put operator for one zero bit in odd\n    odd[0] = 0xedb88320L;          // CRC-32 polynomial\n    row = 1;\n    for (int n = 1; n < GF2_DIM; n++) {\n        odd[n] = row;\n        row <<= 1;\n    }\n\n    // put operator for two zero bits in even\n    gf2_matrix_square(even, odd);\n\n    // put operator for four zero bits in odd\n    gf2_matrix_square(odd, even);\n\n    // apply len2 zeros to crc1 (first square will put the operator for one\n    // zero byte, eight zero bits, in even)\n    do {\n      // apply zeros operator for this bit of len2\n      gf2_matrix_square(even, odd);\n      if ((len2 & 1)!=0)\n        crc1 = gf2_matrix_times(even, crc1);\n      len2 >>= 1;\n\n      // if no more bits set, then done\n      if (len2 == 0)\n        break;\n\n      // another iteration of the loop with odd and even swapped\n      gf2_matrix_square(odd, even);\n      if ((len2 & 1)!=0)\n        crc1 = gf2_matrix_times(odd, crc1);\n      len2 >>= 1;\n\n      // if no more bits set, then done\n    } while (len2 != 0);\n\n    /* return combined crc */\n    crc1 ^= crc2;\n    return crc1;\n  }\n\n  private static long gf2_matrix_times(long[] mat, long vec){\n    long sum = 0;\n    int index = 0;\n    while (vec!=0) {\n      if ((vec & 1)!=0)\n        sum ^= mat[index];\n      vec >>= 1;\n      index++;\n    }\n    return sum;\n  }\n\n  static final void gf2_matrix_square(long[] square, long[] mat) {\n    for (int n = 0; n < GF2_DIM; n++)\n      square[n] = gf2_matrix_times(mat, mat[n]);\n  }\n\n  /*\n  private java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();\n\n  public void update(byte[] buf, int index, int len){\n    if(buf==null) {crc32.reset();}\n    else{crc32.update(buf, index, len);}\n  }\n  public void reset(){\n    crc32.reset();\n  }\n  public void reset(long init){\n    if(init==0L){\n      crc32.reset();\n    }\n    else{\n      System.err.println(\"unsupported operation\");\n    }\n  }\n  public long getValue(){\n    return crc32.getValue();\n  }\n*/\n  public CRC32 copy(){\n    CRC32 foo = new CRC32();\n    foo.v = this.v;\n    return foo;\n  }\n\n  public static int[] getCRC32Table(){\n    int[] tmp = new int[crc_table.length];\n    System.arraycopy(crc_table, 0, tmp, 0, tmp.length);\n    return tmp;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/ChangeLog",
    "content": "ChangeLog of JZlib\n====================================================================\nLast modified: Mon Feb 20 06:06:07 UTC 2012\n\n\nChanges since version 1.1.0:\n- fixed a bug in DeflaterOutputStream#write() with empty data.  9d4616f\n- fixed a bug in processing unwrapped data with InfalterInputStream. d35db2\n- fixed bugs reported in https://github.com/ymnk/jzlib/pull/5 e4aa20\n  - comments and filename in GZIPHeader must be in ISO-8859-1 encoding\n  - fixing a bug in GZIPHeader#setOS(int os)\n- some refactoring code. e912088 6900f5 614fdf\n- improving the performace of Adler32#update method.  6900f5\n- constructors of Alder32 and CRC32 become public. 30c4cf\n- added ZStream#end() and ZStream#finished().  6b55e3\n- exposed useful constants for jruby.  e17ad1\n- updated pom.xml to delete \"souceDirectory\"\n  No need to specify sourceDirectory if the project follows maven\n  standard.\n- updated configurations to use sbt 0.11.1\n\n\nChanges since version 1.0.7:\n- supported some new functionalities, which have been introduced since 'zlib' 1.2.\n  - JZlib#{adler32,crc32}_combine,\n  - JZlib can handle gzip file format(RFC1952).\n- added following classes,\n  - DeflaterOutputStream\n  - InflaterInputStream\n  - GZIPOutputStream\n  - GZIPInputStream\n  - Inflater\n  - Deflater\n  - ZStream has been deprecated.\n    Use Inflater and Deflater instead of it.\n  - GZIPHeader\n- re-implemented Z{Input,Output}Stream with {Deflater,Inflater}{I/O}Stream\n  - those classes have been deprecated.\n    Use DeflaterOutputStream and InfaterInputStream instead of them.\n- com/ -> src/main/java/com/\n- some tests under src/test/scala/\n- pom.xml for mvn, and projects/ for sbt.\n\n\nChanges since version 1.0.6:\n- change: memory and performance optimisations in the inflate operation.\n- change: added the nowrap argument to Z{Input,Output}?Stream.\n\n\nChanges since version 1.0.5:\n- ZInputStream.read(byte[], int, int) method return sometimes zero\n  instead of -1 at the end of stream.\n- ZOutputStream.end() method should not declare IOException.\n- It should be possible to call ZOutputStream.end() method more times \n  (because you can call\tclose() method and after it end() method in \n   finally block).\n- ZOutputStream.finish() method should not ignore IOException from flush().\nMany thanks to Matej Kraus at seznam.cz , who pointed out above problems.\n\n\nChanges since version 1.0.4:\n- a minor bug fix in ZInputStream\n\n\nChanges since version 1.0.3:\n- fixed a bug in closing ZOutputStream.\n  The inflating and deflating processes were not finished successfully.\n- added 'finish' and 'end' methods to ZOutputStream.java\n- added 'example/test_stream_deflate_inflate.java'\n\n\nChanges since version 1.0.2:\n- enabled pure Java implementation of adler32 and\n  commented out the dependency on J2SE in Adler32.java for J2ME users.\n\n\nChanges since version 1.0.1:\n- fixed a bug in deflating some trivial data, for example,\n  large data chunk filled with zero.\n- added 'version' method to JZlib class.\n\n\nChanges since version 1.0.0:\n- added ZInputStream and ZOutputStream classes.\n- fixed a typo in LICENSE.txt.\n\n\nChanges since version 0.0.9:\n- fixed a bug in setting a dictionary in the inflation process.\n- The license was changed to a BSD style license.\n- Z{Input,Output}Stream classes were deleted.\n\n\nChanges since version 0.0.8:\n- fixed a bug in handling a preset dictionary in the inflation process.\n\n\nChanges since version 0.0.7:\n- added methods to control the window size (the size of the history\n  buffer) and to handle the no-wrap option (no zlib header or check),\n  which is the undocumented functionality of zlib.\n\n\nChanges since version 0.0.6:\n- updated InfBlocks.java as zlib did to fix the vulnerability related to\n  the 'double free'. Of course, JZlib is free from such a vulnerability\n  like the 'double free', but JZlib had crashed with NullPointerException\n  by a specially-crafted block of invalid deflated data.\n\n\nChanges since version 0.0.5:\n- added 'flush()' method to com.jcraft.jzlib.ZOutputStream.\n- fixed to take care when occurring the buffer overflow in\n  com.jcraft.jzlib.ZOutputStream.\nMany thanks to Tim Bendfelt at cs.wisc.edu , who pointed out above problems.\n\n\nChanges since version 0.0.4:\n............................\n- fixed a bug in Adler32 class.\n- fixed a bug in ZInputStream class\n- modified ZInputStream to be extended from InputStream\n  instead of FileInputStream.\n- modified ZOutputStream to be extended from OutputStream\n  instead of FileOutputStream.\n- modified ZStream to be changeable wbits. Give wbits value to\n  the method 'deflateInit' of ZStream.\nMany thanks to Bryan Keller<keller@neomar.com>, who reported bugs\nand made suggestions.\n\n\nChanges since version 0.0.3:\n............................\n- fixed a bug in the compression level 0.\n- modified to be compatible with JIKES's bug.\n- added Z[Input,Output]Stream written by Lapo Luchini<lapo@lapo.it>.\n\n\nChanges since version 0.0.2:\n............................\n- fixed a critical bug, which had arisen in the deflating operation with\n  NO_FLUSH and DEFAULT_COMPRESSION mode.\n  Many thanks to Bryan Keller(keller@neomar.com), who reported this glitch.\n\n\nChanges since version 0.0.1:\n............................\n- fixed the bad compression ratio problem, which is reported from\n  Martin Smith(martin@spamcop.net). The compression ratio was not so good\n  compared with the compression ration of zlib. Now, this problem has been\n  fixed\tand, I hope, that deflated files by JZlib and zlib are completely\n  same bit by bit.\n"
  },
  {
    "path": "java/com/jcraft/jzlib/Checksum.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\ninterface Checksum {\n  void update(byte[] buf, int index, int len);\n  void reset();\n  void reset(long init);\n  long getValue();\n  Checksum copy();\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/Deflate.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\npublic \nfinal class Deflate implements Cloneable {\n\n  static final private int MAX_MEM_LEVEL=9;\n\n  static final private int Z_DEFAULT_COMPRESSION=-1;\n\n  static final private int MAX_WBITS=15;            // 32K LZ77 window\n  static final private int DEF_MEM_LEVEL=8;\n\n  static class Config{\n    int good_length; // reduce lazy search above this match length\n    int max_lazy;    // do not perform lazy search above this match length\n    int nice_length; // quit search above this match length\n    int max_chain;\n    int func;\n    Config(int good_length, int max_lazy, \n\t   int nice_length, int max_chain, int func){\n      this.good_length=good_length;\n      this.max_lazy=max_lazy;\n      this.nice_length=nice_length;\n      this.max_chain=max_chain;\n      this.func=func;\n    }\n  }\n  \n  static final private int STORED=0;\n  static final private int FAST=1;\n  static final private int SLOW=2;\n  static final private Config[] config_table;    \n  static{\n    config_table=new Config[10];\n    //                         good  lazy  nice  chain\n    config_table[0]=new Config(0,    0,    0,    0, STORED);\n    config_table[1]=new Config(4,    4,    8,    4, FAST);\n    config_table[2]=new Config(4,    5,   16,    8, FAST);\n    config_table[3]=new Config(4,    6,   32,   32, FAST);\n\n    config_table[4]=new Config(4,    4,   16,   16, SLOW);\n    config_table[5]=new Config(8,   16,   32,   32, SLOW);\n    config_table[6]=new Config(8,   16,  128,  128, SLOW);\n    config_table[7]=new Config(8,   32,  128,  256, SLOW);\n    config_table[8]=new Config(32, 128,  258, 1024, SLOW);\n    config_table[9]=new Config(32, 258,  258, 4096, SLOW);\n  }\n\n  static final private String[] z_errmsg = {\n    \"need dictionary\",     // Z_NEED_DICT       2\n    \"stream end\",          // Z_STREAM_END      1\n    \"\",                    // Z_OK              0\n    \"file error\",          // Z_ERRNO         (-1)\n    \"stream error\",        // Z_STREAM_ERROR  (-2)\n    \"data error\",          // Z_DATA_ERROR    (-3)\n    \"insufficient memory\", // Z_MEM_ERROR     (-4)\n    \"buffer error\",        // Z_BUF_ERROR     (-5)\n    \"incompatible version\",// Z_VERSION_ERROR (-6)\n    \"\"\n  };\n\n  // block not completed, need more input or more output\n  static final private int NeedMore=0; \n\n  // block flush performed\n  static final private int BlockDone=1; \n\n  // finish started, need only more output at next deflate\n  static final private int FinishStarted=2;\n\n  // finish done, accept no more input or output\n  static final private int FinishDone=3;\n\n  // preset dictionary flag in zlib header\n  static final private int PRESET_DICT=0x20;\n\n  static final private int Z_FILTERED=1;\n  static final private int Z_HUFFMAN_ONLY=2;\n  static final private int Z_DEFAULT_STRATEGY=0;\n\n  static final private int Z_NO_FLUSH=0;\n  static final private int Z_PARTIAL_FLUSH=1;\n  static final private int Z_SYNC_FLUSH=2;\n  static final private int Z_FULL_FLUSH=3;\n  static final private int Z_FINISH=4;\n\n  static final private int Z_OK=0;\n  static final private int Z_STREAM_END=1;\n  static final private int Z_NEED_DICT=2;\n  static final private int Z_ERRNO=-1;\n  static final private int Z_STREAM_ERROR=-2;\n  static final private int Z_DATA_ERROR=-3;\n  static final private int Z_MEM_ERROR=-4;\n  static final private int Z_BUF_ERROR=-5;\n  static final private int Z_VERSION_ERROR=-6;\n\n  static final private int INIT_STATE=42;\n  static final private int BUSY_STATE=113;\n  static final private int FINISH_STATE=666;\n\n  // The deflate compression method\n  static final private int Z_DEFLATED=8;\n\n  static final private int STORED_BLOCK=0;\n  static final private int STATIC_TREES=1;\n  static final private int DYN_TREES=2;\n\n  // The three kinds of block type\n  static final private int Z_BINARY=0;\n  static final private int Z_ASCII=1;\n  static final private int Z_UNKNOWN=2;\n\n  static final private int Buf_size=8*2;\n\n  // repeat previous bit length 3-6 times (2 bits of repeat count)\n  static final private int REP_3_6=16; \n\n  // repeat a zero length 3-10 times  (3 bits of repeat count)\n  static final private int REPZ_3_10=17; \n\n  // repeat a zero length 11-138 times  (7 bits of repeat count)\n  static final private int REPZ_11_138=18; \n\n  static final private int MIN_MATCH=3;\n  static final private int MAX_MATCH=258;\n  static final private int MIN_LOOKAHEAD=(MAX_MATCH+MIN_MATCH+1);\n\n  static final private int MAX_BITS=15;\n  static final private int D_CODES=30;\n  static final private int BL_CODES=19;\n  static final private int LENGTH_CODES=29;\n  static final private int LITERALS=256;\n  static final private int L_CODES=(LITERALS+1+LENGTH_CODES);\n  static final private int HEAP_SIZE=(2*L_CODES+1);\n\n  static final private int END_BLOCK=256;\n\n  ZStream strm;        // pointer back to this zlib stream\n  int status;           // as the name implies\n  byte[] pending_buf;   // output still pending\n  int pending_buf_size; // size of pending_buf\n  int pending_out;      // next pending byte to output to the stream\n  int pending;          // nb of bytes in the pending buffer\n  int wrap = 1;\n  byte data_type;       // UNKNOWN, BINARY or ASCII\n  byte method;          // STORED (for zip only) or DEFLATED\n  int last_flush;       // value of flush param for previous deflate call\n\n  int w_size;           // LZ77 window size (32K by default)\n  int w_bits;           // log2(w_size)  (8..16)\n  int w_mask;           // w_size - 1\n\n  byte[] window;\n  // Sliding window. Input bytes are read into the second half of the window,\n  // and move to the first half later to keep a dictionary of at least wSize\n  // bytes. With this organization, matches are limited to a distance of\n  // wSize-MAX_MATCH bytes, but this ensures that IO is always\n  // performed with a length multiple of the block size. Also, it limits\n  // the window size to 64K, which is quite useful on MSDOS.\n  // To do: use the user input buffer as sliding window.\n\n  int window_size;\n  // Actual size of window: 2*wSize, except when the user input buffer\n  // is directly used as sliding window.\n\n  short[] prev;\n  // Link to older string with same hash index. To limit the size of this\n  // array to 64K, this link is maintained only for the last 32K strings.\n  // An index in this array is thus a window index modulo 32K.\n\n  short[] head; // Heads of the hash chains or NIL.\n\n  int ins_h;          // hash index of string to be inserted\n  int hash_size;      // number of elements in hash table\n  int hash_bits;      // log2(hash_size)\n  int hash_mask;      // hash_size-1\n\n  // Number of bits by which ins_h must be shifted at each input\n  // step. It must be such that after MIN_MATCH steps, the oldest\n  // byte no longer takes part in the hash key, that is:\n  // hash_shift * MIN_MATCH >= hash_bits\n  int hash_shift;\n\n  // Window position at the beginning of the current output block. Gets\n  // negative when the window is moved backwards.\n\n  int block_start;\n\n  int match_length;           // length of best match\n  int prev_match;             // previous match\n  int match_available;        // set if previous match exists\n  int strstart;               // start of string to insert\n  int match_start;            // start of matching string\n  int lookahead;              // number of valid bytes ahead in window\n\n  // Length of the best match at previous step. Matches not greater than this\n  // are discarded. This is used in the lazy match evaluation.\n  int prev_length;\n\n  // To speed up deflation, hash chains are never searched beyond this\n  // length.  A higher limit improves compression ratio but degrades the speed.\n  int max_chain_length;\n\n  // Attempt to find a better match only when the current match is strictly\n  // smaller than this value. This mechanism is used only for compression\n  // levels >= 4.\n  int max_lazy_match;\n\n  // Insert new strings in the hash table only if the match length is not\n  // greater than this length. This saves time but degrades compression.\n  // max_insert_length is used only for compression levels <= 3.\n\n  int level;    // compression level (1..9)\n  int strategy; // favor or force Huffman coding\n\n  // Use a faster search when the previous match is longer than this\n  int good_match;\n\n  // Stop searching when current match exceeds this\n  int nice_match;\n\n  short[] dyn_ltree;       // literal and length tree\n  short[] dyn_dtree;       // distance tree\n  short[] bl_tree;         // Huffman tree for bit lengths\n\n  Tree l_desc=new Tree();  // desc for literal tree\n  Tree d_desc=new Tree();  // desc for distance tree\n  Tree bl_desc=new Tree(); // desc for bit length tree\n\n  // number of codes at each bit length for an optimal tree\n  short[] bl_count=new short[MAX_BITS+1];\n  // working area to be used in Tree#gen_codes()\n  short[] next_code=new short[MAX_BITS+1];\n\n  // heap used to build the Huffman trees\n  int[] heap=new int[2*L_CODES+1];\n\n  int heap_len;               // number of elements in the heap\n  int heap_max;               // element of largest frequency\n  // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.\n  // The same heap array is used to build all trees.\n\n  // Depth of each subtree used as tie breaker for trees of equal frequency\n  byte[] depth=new byte[2*L_CODES+1];\n\n  byte[] l_buf;               // index for literals or lengths */\n\n  // Size of match buffer for literals/lengths.  There are 4 reasons for\n  // limiting lit_bufsize to 64K:\n  //   - frequencies can be kept in 16 bit counters\n  //   - if compression is not successful for the first block, all input\n  //     data is still in the window so we can still emit a stored block even\n  //     when input comes from standard input.  (This can also be done for\n  //     all blocks if lit_bufsize is not greater than 32K.)\n  //   - if compression is not successful for a file smaller than 64K, we can\n  //     even emit a stored file instead of a stored block (saving 5 bytes).\n  //     This is applicable only for zip (not gzip or zlib).\n  //   - creating new Huffman trees less frequently may not provide fast\n  //     adaptation to changes in the input data statistics. (Take for\n  //     example a binary file with poorly compressible code followed by\n  //     a highly compressible string table.) Smaller buffer sizes give\n  //     fast adaptation but have of course the overhead of transmitting\n  //     trees more frequently.\n  //   - I can't count above 4\n  int lit_bufsize;\n\n  int last_lit;      // running index in l_buf\n\n  // Buffer for distances. To simplify the code, d_buf and l_buf have\n  // the same number of elements. To use different lengths, an extra flag\n  // array would be necessary.\n\n  int d_buf;         // index of pendig_buf\n\n  int opt_len;        // bit length of current block with optimal trees\n  int static_len;     // bit length of current block with static trees\n  int matches;        // number of string matches in current block\n  int last_eob_len;   // bit length of EOB code for last block\n\n  // Output buffer. bits are inserted starting at the bottom (least\n  // significant bits).\n  short bi_buf;\n\n  // Number of valid bits in bi_buf.  All bits above the last valid bit\n  // are always zero.\n  int bi_valid;\n\n  GZIPHeader gheader = null;\n\n  Deflate(ZStream strm){\n    this.strm=strm;\n    dyn_ltree=new short[HEAP_SIZE*2];\n    dyn_dtree=new short[(2*D_CODES+1)*2]; // distance tree\n    bl_tree=new short[(2*BL_CODES+1)*2];  // Huffman tree for bit lengths\n  }\n\n  void lm_init() {\n    window_size=2*w_size;\n\n    head[hash_size-1]=0;\n    for(int i=0; i<hash_size-1; i++){\n      head[i]=0;\n    }\n\n    // Set the default configuration parameters:\n    max_lazy_match   = Deflate.config_table[level].max_lazy;\n    good_match       = Deflate.config_table[level].good_length;\n    nice_match       = Deflate.config_table[level].nice_length;\n    max_chain_length = Deflate.config_table[level].max_chain;\n\n    strstart = 0;\n    block_start = 0;\n    lookahead = 0;\n    match_length = prev_length = MIN_MATCH-1;\n    match_available = 0;\n    ins_h = 0;\n  }\n\n  // Initialize the tree data structures for a new zlib stream.\n  void tr_init(){\n\n    l_desc.dyn_tree = dyn_ltree;\n    l_desc.stat_desc = StaticTree.static_l_desc;\n\n    d_desc.dyn_tree = dyn_dtree;\n    d_desc.stat_desc = StaticTree.static_d_desc;\n\n    bl_desc.dyn_tree = bl_tree;\n    bl_desc.stat_desc = StaticTree.static_bl_desc;\n\n    bi_buf = 0;\n    bi_valid = 0;\n    last_eob_len = 8; // enough lookahead for inflate\n\n    // Initialize the first block of the first file:\n    init_block();\n  }\n\n  void init_block(){\n    // Initialize the trees.\n    for(int i = 0; i < L_CODES; i++) dyn_ltree[i*2] = 0;\n    for(int i= 0; i < D_CODES; i++) dyn_dtree[i*2] = 0;\n    for(int i= 0; i < BL_CODES; i++) bl_tree[i*2] = 0;\n\n    dyn_ltree[END_BLOCK*2] = 1;\n    opt_len = static_len = 0;\n    last_lit = matches = 0;\n  }\n\n  // Restore the heap property by moving down the tree starting at node k,\n  // exchanging a node with the smallest of its two sons if necessary, stopping\n  // when the heap property is re-established (each father smaller than its\n  // two sons).\n  void pqdownheap(short[] tree,  // the tree to restore\n\t\t  int k          // node to move down\n\t\t  ){\n    int v = heap[k];\n    int j = k << 1;  // left son of k\n    while (j <= heap_len) {\n      // Set j to the smallest of the two sons:\n      if (j < heap_len &&\n\t  smaller(tree, heap[j+1], heap[j], depth)){\n\tj++;\n      }\n      // Exit if v is smaller than both sons\n      if(smaller(tree, v, heap[j], depth)) break;\n\n      // Exchange v with the smallest son\n      heap[k]=heap[j];  k = j;\n      // And continue down the tree, setting j to the left son of k\n      j <<= 1;\n    }\n    heap[k] = v;\n  }\n\n  static boolean smaller(short[] tree, int n, int m, byte[] depth){\n    short tn2=tree[n*2];\n    short tm2=tree[m*2];\n    return (tn2<tm2 ||\n\t    (tn2==tm2 && depth[n] <= depth[m]));\n  }\n\n  // Scan a literal or distance tree to determine the frequencies of the codes\n  // in the bit length tree.\n  void scan_tree (short[] tree,// the tree to be scanned\n\t\t  int max_code // and its largest code of non zero frequency\n\t\t  ){\n    int n;                     // iterates over all tree elements\n    int prevlen = -1;          // last emitted length\n    int curlen;                // length of current code\n    int nextlen = tree[0*2+1]; // length of next code\n    int count = 0;             // repeat count of the current code\n    int max_count = 7;         // max repeat count\n    int min_count = 4;         // min repeat count\n\n    if (nextlen == 0){ max_count = 138; min_count = 3; }\n    tree[(max_code+1)*2+1] = (short)0xffff; // guard\n\n    for(n = 0; n <= max_code; n++) {\n      curlen = nextlen; nextlen = tree[(n+1)*2+1];\n      if(++count < max_count && curlen == nextlen) {\n\tcontinue;\n      }\n      else if(count < min_count) {\n\tbl_tree[curlen*2] += count;\n      }\n      else if(curlen != 0) {\n\tif(curlen != prevlen) bl_tree[curlen*2]++;\n\tbl_tree[REP_3_6*2]++;\n      }\n      else if(count <= 10) {\n\tbl_tree[REPZ_3_10*2]++;\n      }\n      else{\n\tbl_tree[REPZ_11_138*2]++;\n      }\n      count = 0; prevlen = curlen;\n      if(nextlen == 0) {\n\tmax_count = 138; min_count = 3;\n      }\n      else if(curlen == nextlen) {\n\tmax_count = 6; min_count = 3;\n      }\n      else{\n\tmax_count = 7; min_count = 4;\n      }\n    }\n  }\n\n  // Construct the Huffman tree for the bit lengths and return the index in\n  // bl_order of the last bit length code to send.\n  int build_bl_tree(){\n    int max_blindex;  // index of last bit length code of non zero freq\n\n    // Determine the bit length frequencies for literal and distance trees\n    scan_tree(dyn_ltree, l_desc.max_code);\n    scan_tree(dyn_dtree, d_desc.max_code);\n\n    // Build the bit length tree:\n    bl_desc.build_tree(this);\n    // opt_len now includes the length of the tree representations, except\n    // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.\n\n    // Determine the number of bit length codes to send. The pkzip format\n    // requires that at least 4 bit length codes be sent. (appnote.txt says\n    // 3 but the actual value used is 4.)\n    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {\n      if (bl_tree[Tree.bl_order[max_blindex]*2+1] != 0) break;\n    }\n    // Update opt_len to include the bit length tree and counts\n    opt_len += 3*(max_blindex+1) + 5+5+4;\n\n    return max_blindex;\n  }\n\n\n  // Send the header for a block using dynamic Huffman trees: the counts, the\n  // lengths of the bit length codes, the literal tree and the distance tree.\n  // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.\n  void send_all_trees(int lcodes, int dcodes, int blcodes){\n    int rank;                    // index in bl_order\n\n    send_bits(lcodes-257, 5); // not +255 as stated in appnote.txt\n    send_bits(dcodes-1,   5);\n    send_bits(blcodes-4,  4); // not -3 as stated in appnote.txt\n    for (rank = 0; rank < blcodes; rank++) {\n      send_bits(bl_tree[Tree.bl_order[rank]*2+1], 3);\n    }\n    send_tree(dyn_ltree, lcodes-1); // literal tree\n    send_tree(dyn_dtree, dcodes-1); // distance tree\n  }\n\n  // Send a literal or distance tree in compressed form, using the codes in\n  // bl_tree.\n  void send_tree (short[] tree,// the tree to be sent\n\t\t  int max_code // and its largest code of non zero frequency\n\t\t  ){\n    int n;                     // iterates over all tree elements\n    int prevlen = -1;          // last emitted length\n    int curlen;                // length of current code\n    int nextlen = tree[0*2+1]; // length of next code\n    int count = 0;             // repeat count of the current code\n    int max_count = 7;         // max repeat count\n    int min_count = 4;         // min repeat count\n\n    if (nextlen == 0){ max_count = 138; min_count = 3; }\n\n    for (n = 0; n <= max_code; n++) {\n      curlen = nextlen; nextlen = tree[(n+1)*2+1];\n      if(++count < max_count && curlen == nextlen) {\n\tcontinue;\n      }\n      else if(count < min_count) {\n\tdo { send_code(curlen, bl_tree); } while (--count != 0);\n      }\n      else if(curlen != 0){\n\tif(curlen != prevlen){\n\t  send_code(curlen, bl_tree); count--;\n\t}\n\tsend_code(REP_3_6, bl_tree); \n\tsend_bits(count-3, 2);\n      }\n      else if(count <= 10){\n\tsend_code(REPZ_3_10, bl_tree); \n\tsend_bits(count-3, 3);\n      }\n      else{\n\tsend_code(REPZ_11_138, bl_tree);\n\tsend_bits(count-11, 7);\n      }\n      count = 0; prevlen = curlen;\n      if(nextlen == 0){\n\tmax_count = 138; min_count = 3;\n      }\n      else if(curlen == nextlen){\n\tmax_count = 6; min_count = 3;\n      }\n      else{\n\tmax_count = 7; min_count = 4;\n      }\n    }\n  }\n\n  // Output a byte on the stream.\n  // IN assertion: there is enough room in pending_buf.\n  final void put_byte(byte[] p, int start, int len){\n    System.arraycopy(p, start, pending_buf, pending, len);\n    pending+=len;\n  }\n\n  final void put_byte(byte c){\n    pending_buf[pending++]=c;\n  }\n  final void put_short(int w) {\n    put_byte((byte)(w/*&0xff*/));\n    put_byte((byte)(w>>>8));\n  }\n  final void putShortMSB(int b){\n    put_byte((byte)(b>>8));\n    put_byte((byte)(b/*&0xff*/));\n  }   \n\n  final void send_code(int c, short[] tree){\n    int c2=c*2;\n    send_bits((tree[c2]&0xffff), (tree[c2+1]&0xffff));\n  }\n\n  void send_bits(int value, int length){\n    int len = length;\n    if (bi_valid > (int)Buf_size - len) {\n      int val = value;\n//      bi_buf |= (val << bi_valid);\n      bi_buf |= ((val << bi_valid)&0xffff);\n      put_short(bi_buf);\n      bi_buf = (short)(val >>> (Buf_size - bi_valid));\n      bi_valid += len - Buf_size;\n    } else {\n//      bi_buf |= (value) << bi_valid;\n      bi_buf |= (((value) << bi_valid)&0xffff);\n      bi_valid += len;\n    }\n  }\n\n  // Send one empty static block to give enough lookahead for inflate.\n  // This takes 10 bits, of which 7 may remain in the bit buffer.\n  // The current inflate code requires 9 bits of lookahead. If the\n  // last two codes for the previous block (real code plus EOB) were coded\n  // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode\n  // the last real code. In this case we send two empty static blocks instead\n  // of one. (There are no problems if the previous block is stored or fixed.)\n  // To simplify the code, we assume the worst case of last real code encoded\n  // on one bit only.\n  void _tr_align(){\n    send_bits(STATIC_TREES<<1, 3);\n    send_code(END_BLOCK, StaticTree.static_ltree);\n\n    bi_flush();\n\n    // Of the 10 bits for the empty block, we have already sent\n    // (10 - bi_valid) bits. The lookahead for the last real code (before\n    // the EOB of the previous block) was thus at least one plus the length\n    // of the EOB plus what we have just sent of the empty static block.\n    if (1 + last_eob_len + 10 - bi_valid < 9) {\n      send_bits(STATIC_TREES<<1, 3);\n      send_code(END_BLOCK, StaticTree.static_ltree);\n      bi_flush();\n    }\n    last_eob_len = 7;\n  }\n\n\n  // Save the match info and tally the frequency counts. Return true if\n  // the current block must be flushed.\n  boolean _tr_tally (int dist, // distance of matched string\n\t\t     int lc // match length-MIN_MATCH or unmatched char (if dist==0)\n\t\t     ){\n\n    pending_buf[d_buf+last_lit*2] = (byte)(dist>>>8);\n    pending_buf[d_buf+last_lit*2+1] = (byte)dist;\n\n    l_buf[last_lit] = (byte)lc; last_lit++;\n\n    if (dist == 0) {\n      // lc is the unmatched char\n      dyn_ltree[lc*2]++;\n    } \n    else {\n      matches++;\n      // Here, lc is the match length - MIN_MATCH\n      dist--;             // dist = match distance - 1\n      dyn_ltree[(Tree._length_code[lc]+LITERALS+1)*2]++;\n      dyn_dtree[Tree.d_code(dist)*2]++;\n    }\n\n    if ((last_lit & 0x1fff) == 0 && level > 2) {\n      // Compute an upper bound for the compressed length\n      int out_length = last_lit*8;\n      int in_length = strstart - block_start;\n      int dcode;\n      for (dcode = 0; dcode < D_CODES; dcode++) {\n\tout_length += (int)dyn_dtree[dcode*2] *\n\t  (5L+Tree.extra_dbits[dcode]);\n      }\n      out_length >>>= 3;\n      if ((matches < (last_lit/2)) && out_length < in_length/2) return true;\n    }\n\n    return (last_lit == lit_bufsize-1);\n    // We avoid equality with lit_bufsize because of wraparound at 64K\n    // on 16 bit machines and because stored blocks are restricted to\n    // 64K-1 bytes.\n  }\n\n  // Send the block data compressed using the given Huffman trees\n  void compress_block(short[] ltree, short[] dtree){\n    int  dist;      // distance of matched string\n    int lc;         // match length or unmatched char (if dist == 0)\n    int lx = 0;     // running index in l_buf\n    int code;       // the code to send\n    int extra;      // number of extra bits to send\n\n    if (last_lit != 0){\n      do{\n\tdist=((pending_buf[d_buf+lx*2]<<8)&0xff00)|\n\t  (pending_buf[d_buf+lx*2+1]&0xff);\n\tlc=(l_buf[lx])&0xff; lx++;\n\n\tif(dist == 0){\n\t  send_code(lc, ltree); // send a literal byte\n\t} \n\telse{\n\t  // Here, lc is the match length - MIN_MATCH\n\t  code = Tree._length_code[lc];\n\n\t  send_code(code+LITERALS+1, ltree); // send the length code\n\t  extra = Tree.extra_lbits[code];\n\t  if(extra != 0){\n\t    lc -= Tree.base_length[code];\n\t    send_bits(lc, extra);       // send the extra length bits\n\t  }\n\t  dist--; // dist is now the match distance - 1\n\t  code = Tree.d_code(dist);\n\n\t  send_code(code, dtree);       // send the distance code\n\t  extra = Tree.extra_dbits[code];\n\t  if (extra != 0) {\n\t    dist -= Tree.base_dist[code];\n\t    send_bits(dist, extra);   // send the extra distance bits\n\t  }\n\t} // literal or match pair ?\n\n\t// Check that the overlay between pending_buf and d_buf+l_buf is ok:\n      }\n      while (lx < last_lit);\n    }\n\n    send_code(END_BLOCK, ltree);\n    last_eob_len = ltree[END_BLOCK*2+1];\n  }\n\n  // Set the data type to ASCII or BINARY, using a crude approximation:\n  // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.\n  // IN assertion: the fields freq of dyn_ltree are set and the total of all\n  // frequencies does not exceed 64K (to fit in an int on 16 bit machines).\n  void set_data_type(){\n    int n = 0;\n    int  ascii_freq = 0;\n    int  bin_freq = 0;\n    while(n<7){ bin_freq += dyn_ltree[n*2]; n++;}\n    while(n<128){ ascii_freq += dyn_ltree[n*2]; n++;}\n    while(n<LITERALS){ bin_freq += dyn_ltree[n*2]; n++;}\n    data_type=(byte)(bin_freq > (ascii_freq >>> 2) ? Z_BINARY : Z_ASCII);\n  }\n\n  // Flush the bit buffer, keeping at most 7 bits in it.\n  void bi_flush(){\n    if (bi_valid == 16) {\n      put_short(bi_buf);\n      bi_buf=0;\n      bi_valid=0;\n    }\n    else if (bi_valid >= 8) {\n      put_byte((byte)bi_buf);\n      bi_buf>>>=8;\n      bi_valid-=8;\n    }\n  }\n\n  // Flush the bit buffer and align the output on a byte boundary\n  void bi_windup(){\n    if (bi_valid > 8) {\n      put_short(bi_buf);\n    } else if (bi_valid > 0) {\n      put_byte((byte)bi_buf);\n    }\n    bi_buf = 0;\n    bi_valid = 0;\n  }\n\n  // Copy a stored block, storing first the length and its\n  // one's complement if requested.\n  void copy_block(int buf,         // the input data\n\t\t  int len,         // its length\n\t\t  boolean header   // true if block header must be written\n\t\t  ){\n    int index=0;\n    bi_windup();      // align on byte boundary\n    last_eob_len = 8; // enough lookahead for inflate\n\n    if (header) {\n      put_short((short)len);   \n      put_short((short)~len);\n    }\n\n    //  while(len--!=0) {\n    //    put_byte(window[buf+index]);\n    //    index++;\n    //  }\n    put_byte(window, buf, len);\n  }\n\n  void flush_block_only(boolean eof){\n    _tr_flush_block(block_start>=0 ? block_start : -1,\n\t\t    strstart-block_start,\n\t\t    eof);\n    block_start=strstart;\n    strm.flush_pending();\n  }\n\n  // Copy without compression as much as possible from the input stream, return\n  // the current block state.\n  // This function does not insert new strings in the dictionary since\n  // uncompressible data is probably not useful. This function is used\n  // only for the level=0 compression option.\n  // NOTE: this function should be optimized to avoid extra copying from\n  // window to pending_buf.\n  int deflate_stored(int flush){\n    // Stored blocks are limited to 0xffff bytes, pending_buf is limited\n    // to pending_buf_size, and each stored block has a 5 byte header:\n\n    int max_block_size = 0xffff;\n    int max_start;\n\n    if(max_block_size > pending_buf_size - 5) {\n      max_block_size = pending_buf_size - 5;\n    }\n\n    // Copy as much as possible from input to output:\n    while(true){\n      // Fill the window as much as possible:\n      if(lookahead<=1){\n\tfill_window();\n\tif(lookahead==0 && flush==Z_NO_FLUSH) return NeedMore;\n\tif(lookahead==0) break; // flush the current block\n      }\n\n      strstart+=lookahead;\n      lookahead=0;\n\n      // Emit a stored block if pending_buf will be full:\n      max_start=block_start+max_block_size;\n      if(strstart==0|| strstart>=max_start) {\n\t// strstart == 0 is possible when wraparound on 16-bit machine\n\tlookahead = (int)(strstart-max_start);\n\tstrstart = (int)max_start;\n      \n\tflush_block_only(false);\n\tif(strm.avail_out==0) return NeedMore;\n\n      }\n\n      // Flush if we may have to slide, otherwise block_start may become\n      // negative and the data will be gone:\n      if(strstart-block_start >= w_size-MIN_LOOKAHEAD) {\n\tflush_block_only(false);\n\tif(strm.avail_out==0) return NeedMore;\n      }\n    }\n\n    flush_block_only(flush == Z_FINISH);\n    if(strm.avail_out==0)\n      return (flush == Z_FINISH) ? FinishStarted : NeedMore;\n\n    return flush == Z_FINISH ? FinishDone : BlockDone;\n  }\n\n  // Send a stored block\n  void _tr_stored_block(int buf,        // input block\n\t\t\tint stored_len, // length of input block\n\t\t\tboolean eof     // true if this is the last block for a file\n\t\t\t){\n    send_bits((STORED_BLOCK<<1)+(eof?1:0), 3);  // send block type\n    copy_block(buf, stored_len, true);          // with header\n  }\n\n  // Determine the best encoding for the current block: dynamic trees, static\n  // trees or store, and output the encoded block to the zip file.\n  void _tr_flush_block(int buf,        // input block, or NULL if too old\n\t\t       int stored_len, // length of input block\n\t\t       boolean eof     // true if this is the last block for a file\n\t\t       ) {\n    int opt_lenb, static_lenb;// opt_len and static_len in bytes\n    int max_blindex = 0;      // index of last bit length code of non zero freq\n\n    // Build the Huffman trees unless a stored block is forced\n    if(level > 0) {\n      // Check if the file is ascii or binary\n      if(data_type == Z_UNKNOWN) set_data_type();\n\n      // Construct the literal and distance trees\n      l_desc.build_tree(this);\n\n      d_desc.build_tree(this);\n\n      // At this point, opt_len and static_len are the total bit lengths of\n      // the compressed block data, excluding the tree representations.\n\n      // Build the bit length tree for the above two trees, and get the index\n      // in bl_order of the last bit length code to send.\n      max_blindex=build_bl_tree();\n\n      // Determine the best encoding. Compute first the block length in bytes\n      opt_lenb=(opt_len+3+7)>>>3;\n      static_lenb=(static_len+3+7)>>>3;\n\n      if(static_lenb<=opt_lenb) opt_lenb=static_lenb;\n    }\n    else {\n      opt_lenb=static_lenb=stored_len+5; // force a stored block\n    }\n\n    if(stored_len+4<=opt_lenb && buf != -1){\n      // 4: two words for the lengths\n      // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.\n      // Otherwise we can't have processed more than WSIZE input bytes since\n      // the last block flush, because compression would have been\n      // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to\n      // transform a block into a stored block.\n      _tr_stored_block(buf, stored_len, eof);\n    }\n    else if(static_lenb == opt_lenb){\n      send_bits((STATIC_TREES<<1)+(eof?1:0), 3);\n      compress_block(StaticTree.static_ltree, StaticTree.static_dtree);\n    }\n    else{\n      send_bits((DYN_TREES<<1)+(eof?1:0), 3);\n      send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1);\n      compress_block(dyn_ltree, dyn_dtree);\n    }\n\n    // The above check is made mod 2^32, for files larger than 512 MB\n    // and uLong implemented on 32 bits.\n\n    init_block();\n\n    if(eof){\n      bi_windup();\n    }\n  }\n\n  // Fill the window when the lookahead becomes insufficient.\n  // Updates strstart and lookahead.\n  //\n  // IN assertion: lookahead < MIN_LOOKAHEAD\n  // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD\n  //    At least one byte has been read, or avail_in == 0; reads are\n  //    performed for at least two bytes (required for the zip translate_eol\n  //    option -- not supported here).\n  void fill_window(){\n    int n, m;\n    int p;\n    int more;    // Amount of free space at the end of the window.\n\n    do{\n      more = (window_size-lookahead-strstart);\n\n      // Deal with !@#$% 64K limit:\n      if(more==0 && strstart==0 && lookahead==0){\n\tmore = w_size;\n      } \n      else if(more==-1) {\n\t// Very unlikely, but possible on 16 bit machine if strstart == 0\n\t// and lookahead == 1 (input done one byte at time)\n\tmore--;\n\n\t// If the window is almost full and there is insufficient lookahead,\n\t// move the upper half to the lower one to make room in the upper half.\n      }\n      else if(strstart >= w_size+ w_size-MIN_LOOKAHEAD) {\n\tSystem.arraycopy(window, w_size, window, 0, w_size);\n\tmatch_start-=w_size;\n\tstrstart-=w_size; // we now have strstart >= MAX_DIST\n\tblock_start-=w_size;\n\n\t// Slide the hash table (could be avoided with 32 bit values\n\t// at the expense of memory usage). We slide even when level == 0\n\t// to keep the hash table consistent if we switch back to level > 0\n\t// later. (Using level 0 permanently is not an optimal usage of\n\t// zlib, so we don't care about this pathological case.)\n\n\tn = hash_size;\n\tp=n;\n\tdo {\n\t  m = (head[--p]&0xffff);\n\t  head[p]=(m>=w_size ? (short)(m-w_size) : 0);\n\t}\n\twhile (--n != 0);\n\n\tn = w_size;\n\tp = n;\n\tdo {\n\t  m = (prev[--p]&0xffff);\n\t  prev[p] = (m >= w_size ? (short)(m-w_size) : 0);\n\t  // If n is not on any hash chain, prev[n] is garbage but\n\t  // its value will never be used.\n\t}\n\twhile (--n!=0);\n\tmore += w_size;\n      }\n\n      if (strm.avail_in == 0) return;\n\n      // If there was no sliding:\n      //    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&\n      //    more == window_size - lookahead - strstart\n      // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)\n      // => more >= window_size - 2*WSIZE + 2\n      // In the BIG_MEM or MMAP case (not yet supported),\n      //   window_size == input_size + MIN_LOOKAHEAD  &&\n      //   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.\n      // Otherwise, window_size == 2*WSIZE so more >= 2.\n      // If there was sliding, more >= WSIZE. So in all cases, more >= 2.\n\n      n = strm.read_buf(window, strstart + lookahead, more);\n      lookahead += n;\n\n      // Initialize the hash value now that we have some input:\n      if(lookahead >= MIN_MATCH) {\n\tins_h = window[strstart]&0xff;\n\tins_h=(((ins_h)<<hash_shift)^(window[strstart+1]&0xff))&hash_mask;\n      }\n      // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,\n      // but this is not important since only literal bytes will be emitted.\n    }\n    while (lookahead < MIN_LOOKAHEAD && strm.avail_in != 0);\n  }\n\n  // Compress as much as possible from the input stream, return the current\n  // block state.\n  // This function does not perform lazy evaluation of matches and inserts\n  // new strings in the dictionary only for unmatched strings or for short\n  // matches. It is used only for the fast compression options.\n  int deflate_fast(int flush){\n//    short hash_head = 0; // head of the hash chain\n    int hash_head = 0; // head of the hash chain\n    boolean bflush;      // set if current block must be flushed\n\n    while(true){\n      // Make sure that we always have enough lookahead, except\n      // at the end of the input file. We need MAX_MATCH bytes\n      // for the next match, plus MIN_MATCH bytes to insert the\n      // string following the next match.\n      if(lookahead < MIN_LOOKAHEAD){\n\tfill_window();\n\tif(lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH){\n\t  return NeedMore;\n\t}\n\tif(lookahead == 0) break; // flush the current block\n      }\n\n      // Insert the string window[strstart .. strstart+2] in the\n      // dictionary, and set hash_head to the head of the hash chain:\n      if(lookahead >= MIN_MATCH){\n\tins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask;\n\n//\tprev[strstart&w_mask]=hash_head=head[ins_h];\n        hash_head=(head[ins_h]&0xffff);\n\tprev[strstart&w_mask]=head[ins_h];\n\thead[ins_h]=(short)strstart;\n      }\n\n      // Find the longest match, discarding those <= prev_length.\n      // At this point we have always match_length < MIN_MATCH\n\n      if(hash_head!=0L && \n\t ((strstart-hash_head)&0xffff) <= w_size-MIN_LOOKAHEAD\n\t ){\n\t// To simplify the code, we prevent matches with the string\n\t// of window index 0 (in particular we have to avoid a match\n\t// of the string with itself at the start of the input file).\n\tif(strategy != Z_HUFFMAN_ONLY){\n\t  match_length=longest_match (hash_head);\n\t}\n\t// longest_match() sets match_start\n      }\n      if(match_length>=MIN_MATCH){\n\t//        check_match(strstart, match_start, match_length);\n\n\tbflush=_tr_tally(strstart-match_start, match_length-MIN_MATCH);\n\n\tlookahead -= match_length;\n\n\t// Insert new strings in the hash table only if the match length\n\t// is not too large. This saves time but degrades compression.\n\tif(match_length <= max_lazy_match &&\n\t   lookahead >= MIN_MATCH) {\n\t  match_length--; // string at strstart already in hash table\n\t  do{\n\t    strstart++;\n\n\t    ins_h=((ins_h<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask;\n//\t    prev[strstart&w_mask]=hash_head=head[ins_h];\n\t    hash_head=(head[ins_h]&0xffff);\n\t    prev[strstart&w_mask]=head[ins_h];\n\t    head[ins_h]=(short)strstart;\n\n\t    // strstart never exceeds WSIZE-MAX_MATCH, so there are\n\t    // always MIN_MATCH bytes ahead.\n\t  }\n\t  while (--match_length != 0);\n\t  strstart++; \n\t}\n\telse{\n\t  strstart += match_length;\n\t  match_length = 0;\n\t  ins_h = window[strstart]&0xff;\n\n\t  ins_h=(((ins_h)<<hash_shift)^(window[strstart+1]&0xff))&hash_mask;\n\t  // If lookahead < MIN_MATCH, ins_h is garbage, but it does not\n\t  // matter since it will be recomputed at next deflate call.\n\t}\n      }\n      else {\n\t// No match, output a literal byte\n\n\tbflush=_tr_tally(0, window[strstart]&0xff);\n\tlookahead--;\n\tstrstart++; \n      }\n      if (bflush){\n\n\tflush_block_only(false);\n\tif(strm.avail_out==0) return NeedMore;\n      }\n    }\n\n    flush_block_only(flush == Z_FINISH);\n    if(strm.avail_out==0){\n      if(flush == Z_FINISH) return FinishStarted;\n      else return NeedMore;\n    }\n    return flush==Z_FINISH ? FinishDone : BlockDone;\n  }\n\n  // Same as above, but achieves better compression. We use a lazy\n  // evaluation for matches: a match is finally adopted only if there is\n  // no better match at the next window position.\n  int deflate_slow(int flush){\n//    short hash_head = 0;    // head of hash chain\n    int hash_head = 0;    // head of hash chain\n    boolean bflush;         // set if current block must be flushed\n\n    // Process the input block.\n    while(true){\n      // Make sure that we always have enough lookahead, except\n      // at the end of the input file. We need MAX_MATCH bytes\n      // for the next match, plus MIN_MATCH bytes to insert the\n      // string following the next match.\n\n      if (lookahead < MIN_LOOKAHEAD) {\n\tfill_window();\n\tif(lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {\n\t  return NeedMore;\n\t}\n\tif(lookahead == 0) break; // flush the current block\n      }\n\n      // Insert the string window[strstart .. strstart+2] in the\n      // dictionary, and set hash_head to the head of the hash chain:\n\n      if(lookahead >= MIN_MATCH) {\n\tins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff)) & hash_mask;\n//\tprev[strstart&w_mask]=hash_head=head[ins_h];\n\thash_head=(head[ins_h]&0xffff);\n\tprev[strstart&w_mask]=head[ins_h];\n\thead[ins_h]=(short)strstart;\n      }\n\n      // Find the longest match, discarding those <= prev_length.\n      prev_length = match_length; prev_match = match_start;\n      match_length = MIN_MATCH-1;\n\n      if (hash_head != 0 && prev_length < max_lazy_match &&\n\t  ((strstart-hash_head)&0xffff) <= w_size-MIN_LOOKAHEAD\n\t  ){\n\t// To simplify the code, we prevent matches with the string\n\t// of window index 0 (in particular we have to avoid a match\n\t// of the string with itself at the start of the input file).\n\n\tif(strategy != Z_HUFFMAN_ONLY) {\n\t  match_length = longest_match(hash_head);\n\t}\n\t// longest_match() sets match_start\n\n\tif (match_length <= 5 && (strategy == Z_FILTERED ||\n\t\t\t\t  (match_length == MIN_MATCH &&\n\t\t\t\t   strstart - match_start > 4096))) {\n\n\t  // If prev_match is also MIN_MATCH, match_start is garbage\n\t  // but we will ignore the current match anyway.\n\t  match_length = MIN_MATCH-1;\n\t}\n      }\n\n      // If there was a match at the previous step and the current\n      // match is not better, output the previous match:\n      if(prev_length >= MIN_MATCH && match_length <= prev_length) {\n\tint max_insert = strstart + lookahead - MIN_MATCH;\n\t// Do not insert strings in hash table beyond this.\n\n\t//          check_match(strstart-1, prev_match, prev_length);\n\n\tbflush=_tr_tally(strstart-1-prev_match, prev_length - MIN_MATCH);\n\n\t// Insert in hash table all strings up to the end of the match.\n\t// strstart-1 and strstart are already inserted. If there is not\n\t// enough lookahead, the last two strings are not inserted in\n\t// the hash table.\n\tlookahead -= prev_length-1;\n\tprev_length -= 2;\n\tdo{\n\t  if(++strstart <= max_insert) {\n\t    ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask;\n\t    //prev[strstart&w_mask]=hash_head=head[ins_h];\n\t    hash_head=(head[ins_h]&0xffff);\n\t    prev[strstart&w_mask]=head[ins_h];\n\t    head[ins_h]=(short)strstart;\n\t  }\n\t}\n\twhile(--prev_length != 0);\n\tmatch_available = 0;\n\tmatch_length = MIN_MATCH-1;\n\tstrstart++;\n\n\tif (bflush){\n\t  flush_block_only(false);\n\t  if(strm.avail_out==0) return NeedMore;\n\t}\n      } else if (match_available!=0) {\n\n\t// If there was no match at the previous position, output a\n\t// single literal. If there was a match but the current match\n\t// is longer, truncate the previous match to a single literal.\n\n\tbflush=_tr_tally(0, window[strstart-1]&0xff);\n\n\tif (bflush) {\n\t  flush_block_only(false);\n\t}\n\tstrstart++;\n\tlookahead--;\n\tif(strm.avail_out == 0) return NeedMore;\n      } else {\n\t// There is no previous match to compare with, wait for\n\t// the next step to decide.\n\n\tmatch_available = 1;\n\tstrstart++;\n\tlookahead--;\n      }\n    }\n\n    if(match_available!=0) {\n      bflush=_tr_tally(0, window[strstart-1]&0xff);\n      match_available = 0;\n    }\n    flush_block_only(flush == Z_FINISH);\n\n    if(strm.avail_out==0){\n      if(flush == Z_FINISH) return FinishStarted;\n      else return NeedMore;\n    }\n\n    return flush == Z_FINISH ? FinishDone : BlockDone;\n  }\n\n  int longest_match(int cur_match){\n    int chain_length = max_chain_length; // max hash chain length\n    int scan = strstart;                 // current string\n    int match;                           // matched string\n    int len;                             // length of current match\n    int best_len = prev_length;          // best match length so far\n    int limit = strstart>(w_size-MIN_LOOKAHEAD) ?\n      strstart-(w_size-MIN_LOOKAHEAD) : 0;\n    int nice_match=this.nice_match;\n\n    // Stop when cur_match becomes <= limit. To simplify the code,\n    // we prevent matches with the string of window index 0.\n\n    int wmask = w_mask;\n\n    int strend = strstart + MAX_MATCH;\n    byte scan_end1 = window[scan+best_len-1];\n    byte scan_end = window[scan+best_len];\n\n    // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\n    // It is easy to get rid of this optimization if necessary.\n\n    // Do not waste too much time if we already have a good match:\n    if (prev_length >= good_match) {\n      chain_length >>= 2;\n    }\n\n    // Do not look for matches beyond the end of the input. This is necessary\n    // to make deflate deterministic.\n    if (nice_match > lookahead) nice_match = lookahead;\n\n    do {\n      match = cur_match;\n\n      // Skip to next match if the match length cannot increase\n      // or if the match length is less than 2:\n      if (window[match+best_len]   != scan_end  ||\n\t  window[match+best_len-1] != scan_end1 ||\n\t  window[match]       != window[scan]     ||\n\t  window[++match]     != window[scan+1])      continue;\n\n      // The check at best_len-1 can be removed because it will be made\n      // again later. (This heuristic is not always a win.)\n      // It is not necessary to compare scan[2] and match[2] since they\n      // are always equal when the other bytes match, given that\n      // the hash keys are equal and that HASH_BITS >= 8.\n      scan += 2; match++;\n\n      // We check for insufficient lookahead only every 8th comparison;\n      // the 256th check will be made at strstart+258.\n      do {\n      } while (window[++scan] == window[++match] &&\n\t       window[++scan] == window[++match] &&\n\t       window[++scan] == window[++match] &&\n\t       window[++scan] == window[++match] &&\n\t       window[++scan] == window[++match] &&\n\t       window[++scan] == window[++match] &&\n\t       window[++scan] == window[++match] &&\n\t       window[++scan] == window[++match] &&\n\t       scan < strend);\n\n      len = MAX_MATCH - (int)(strend - scan);\n      scan = strend - MAX_MATCH;\n\n      if(len>best_len) {\n\tmatch_start = cur_match;\n\tbest_len = len;\n\tif (len >= nice_match) break;\n\tscan_end1  = window[scan+best_len-1];\n\tscan_end   = window[scan+best_len];\n      }\n\n    } while ((cur_match = (prev[cur_match & wmask]&0xffff)) > limit\n\t     && --chain_length != 0);\n\n    if (best_len <= lookahead) return best_len;\n    return lookahead;\n  }\n\n  int deflateInit(int level, int bits, int memlevel){\n    return deflateInit(level, Z_DEFLATED, bits, memlevel,\n\t\t\tZ_DEFAULT_STRATEGY);\n  }\n    \n  int deflateInit(int level, int bits){\n    return deflateInit(level, Z_DEFLATED, bits, DEF_MEM_LEVEL,\n\t\t\tZ_DEFAULT_STRATEGY);\n  }\n  int deflateInit(int level){\n    return deflateInit(level, MAX_WBITS);\n  }\n  private int deflateInit(int level, int method,  int windowBits,\n\t\t\t  int memLevel, int strategy){\n    int wrap = 1;\n    //    byte[] my_version=ZLIB_VERSION;\n\n    //\n    //  if (version == null || version[0] != my_version[0]\n    //  || stream_size != sizeof(z_stream)) {\n    //  return Z_VERSION_ERROR;\n    //  }\n\n    strm.msg = null;\n\n    if (level == Z_DEFAULT_COMPRESSION) level = 6;\n\n    if (windowBits < 0) { // undocumented feature: suppress zlib header\n      wrap = 0;\n      windowBits = -windowBits;\n    }\n    else if(windowBits > 15){\n      wrap = 2;\n      windowBits -= 16;\n      strm.adler=new CRC32();\n    }\n\n    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || \n\tmethod != Z_DEFLATED ||\n\twindowBits < 9 || windowBits > 15 || level < 0 || level > 9 ||\n        strategy < 0 || strategy > Z_HUFFMAN_ONLY) {\n      return Z_STREAM_ERROR;\n    }\n\n    strm.dstate = (Deflate)this;\n\n    this.wrap = wrap;\n    w_bits = windowBits;\n    w_size = 1 << w_bits;\n    w_mask = w_size - 1;\n\n    hash_bits = memLevel + 7;\n    hash_size = 1 << hash_bits;\n    hash_mask = hash_size - 1;\n    hash_shift = ((hash_bits+MIN_MATCH-1)/MIN_MATCH);\n\n    window = new byte[w_size*2];\n    prev = new short[w_size];\n    head = new short[hash_size];\n\n    lit_bufsize = 1 << (memLevel + 6); // 16K elements by default\n\n    // We overlay pending_buf and d_buf+l_buf. This works since the average\n    // output size for (length,distance) codes is <= 24 bits.\n    pending_buf = new byte[lit_bufsize*3];\n    pending_buf_size = lit_bufsize*3;\n\n    d_buf = lit_bufsize;\n    l_buf = new byte[lit_bufsize];\n\n    this.level = level;\n\n    this.strategy = strategy;\n    this.method = (byte)method;\n\n    return deflateReset();\n  }\n\n  int deflateReset(){\n    strm.total_in = strm.total_out = 0;\n    strm.msg = null; //\n    strm.data_type = Z_UNKNOWN;\n\n    pending = 0;\n    pending_out = 0;\n\n    if(wrap < 0){\n      wrap = -wrap;\n    }\n    status = (wrap==0) ? BUSY_STATE : INIT_STATE;\n    strm.adler.reset();\n\n    last_flush = Z_NO_FLUSH;\n\n    tr_init();\n    lm_init();\n    return Z_OK;\n  }\n\n  int deflateEnd(){\n    if(status!=INIT_STATE && status!=BUSY_STATE && status!=FINISH_STATE){\n      return Z_STREAM_ERROR;\n    }\n    // Deallocate in reverse order of allocations:\n    pending_buf=null;\n    l_buf=null;\n    head=null;\n    prev=null;\n    window=null;\n    // free\n    // dstate=null;\n    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;\n  }\n\n  int deflateParams(int _level, int _strategy){\n    int err=Z_OK;\n\n    if(_level == Z_DEFAULT_COMPRESSION){\n      _level = 6;\n    }\n    if(_level < 0 || _level > 9 || \n       _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {\n      return Z_STREAM_ERROR;\n    }\n\n    if(config_table[level].func!=config_table[_level].func &&\n       strm.total_in != 0) {\n      // Flush the last buffer:\n      err = strm.deflate(Z_PARTIAL_FLUSH);\n    }\n\n    if(level != _level) {\n      level = _level;\n      max_lazy_match   = config_table[level].max_lazy;\n      good_match       = config_table[level].good_length;\n      nice_match       = config_table[level].nice_length;\n      max_chain_length = config_table[level].max_chain;\n    }\n    strategy = _strategy;\n    return err;\n  }\n\n  int deflateSetDictionary (byte[] dictionary, int dictLength){\n    int length = dictLength;\n    int index=0;\n\n    if(dictionary == null || status != INIT_STATE)\n      return Z_STREAM_ERROR;\n\n    strm.adler.update(dictionary, 0, dictLength);\n\n    if(length < MIN_MATCH) return Z_OK;\n    if(length > w_size-MIN_LOOKAHEAD){\n      length = w_size-MIN_LOOKAHEAD;\n      index=dictLength-length; // use the tail of the dictionary\n    }\n    System.arraycopy(dictionary, index, window, 0, length);\n    strstart = length;\n    block_start = length;\n\n    // Insert all strings in the hash table (except for the last two bytes).\n    // s->lookahead stays null, so s->ins_h will be recomputed at the next\n    // call of fill_window.\n\n    ins_h = window[0]&0xff;\n    ins_h=(((ins_h)<<hash_shift)^(window[1]&0xff))&hash_mask;\n\n    for(int n=0; n<=length-MIN_MATCH; n++){\n      ins_h=(((ins_h)<<hash_shift)^(window[(n)+(MIN_MATCH-1)]&0xff))&hash_mask;\n      prev[n&w_mask]=head[ins_h];\n      head[ins_h]=(short)n;\n    }\n    return Z_OK;\n  }\n\n  int deflate(int flush){\n    int old_flush;\n\n    if(flush>Z_FINISH || flush<0){\n      return Z_STREAM_ERROR;\n    }\n\n    if(strm.next_out == null ||\n       (strm.next_in == null && strm.avail_in != 0) ||\n       (status == FINISH_STATE && flush != Z_FINISH)) {\n      strm.msg=z_errmsg[Z_NEED_DICT-(Z_STREAM_ERROR)];\n      return Z_STREAM_ERROR;\n    }\n    if(strm.avail_out == 0){\n      strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)];\n      return Z_BUF_ERROR;\n    }\n\n    old_flush = last_flush;\n    last_flush = flush;\n\n    // Write the zlib header\n    if(status == INIT_STATE) {\n      if(wrap == 2){\n        getGZIPHeader().put(this);\n        status=BUSY_STATE;\n        strm.adler.reset();\n      }\n      else{\n      int header = (Z_DEFLATED+((w_bits-8)<<4))<<8;\n      int level_flags=((level-1)&0xff)>>1;\n\n      if(level_flags>3) level_flags=3;\n      header |= (level_flags<<6);\n      if(strstart!=0) header |= PRESET_DICT;\n      header+=31-(header % 31);\n\n      status=BUSY_STATE;\n      putShortMSB(header);\n\n\n      // Save the adler32 of the preset dictionary:\n      if(strstart!=0){\n        long adler=strm.adler.getValue();\n        putShortMSB((int)(adler>>>16));\n        putShortMSB((int)(adler&0xffff));\n      }\n      strm.adler.reset();\n      }\n    }\n\n    // Flush as much pending output as possible\n    if(pending != 0) {\n      strm.flush_pending();\n      if(strm.avail_out == 0) {\n\t// Since avail_out is 0, deflate will be called again with\n\t// more output space, but possibly with both pending and\n\t// avail_in equal to zero. There won't be anything to do,\n\t// but this is not an error situation so make sure we\n\t// return OK instead of BUF_ERROR at next call of deflate:\n\tlast_flush = -1;\n\treturn Z_OK;\n      }\n\n      // Make sure there is something to do and avoid duplicate consecutive\n      // flushes. For repeated and useless calls with Z_FINISH, we keep\n      // returning Z_STREAM_END instead of Z_BUFF_ERROR.\n    }\n    else if(strm.avail_in==0 && flush <= old_flush &&\n\t    flush != Z_FINISH) {\n      strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)];\n      return Z_BUF_ERROR;\n    }\n\n    // User must not provide more input after the first FINISH:\n    if(status == FINISH_STATE && strm.avail_in != 0) {\n      strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)];\n      return Z_BUF_ERROR;\n    }\n\n    // Start a new block or continue the current one.\n    if(strm.avail_in!=0 || lookahead!=0 ||\n       (flush != Z_NO_FLUSH && status != FINISH_STATE)) {\n      int bstate=-1;\n      switch(config_table[level].func){\n      case STORED: \n\tbstate = deflate_stored(flush);\n\tbreak;\n      case FAST: \n\tbstate = deflate_fast(flush);\n\tbreak;\n      case SLOW: \n\tbstate = deflate_slow(flush);\n\tbreak;\n      default:\n      }\n\n      if (bstate==FinishStarted || bstate==FinishDone) {\n\tstatus = FINISH_STATE;\n      }\n      if (bstate==NeedMore || bstate==FinishStarted) {\n\tif(strm.avail_out == 0) {\n\t  last_flush = -1; // avoid BUF_ERROR next call, see above\n\t}\n\treturn Z_OK;\n\t// If flush != Z_NO_FLUSH && avail_out == 0, the next call\n\t// of deflate should use the same flush parameter to make sure\n\t// that the flush is complete. So we don't have to output an\n\t// empty block here, this will be done at next call. This also\n\t// ensures that for a very small output buffer, we emit at most\n\t// one empty block.\n      }\n\n      if (bstate==BlockDone) {\n\tif(flush == Z_PARTIAL_FLUSH) {\n\t  _tr_align();\n\t} \n\telse { // FULL_FLUSH or SYNC_FLUSH\n\t  _tr_stored_block(0, 0, false);\n\t  // For a full flush, this empty block will be recognized\n\t  // as a special marker by inflate_sync().\n\t  if(flush == Z_FULL_FLUSH) {\n\t    //state.head[s.hash_size-1]=0;\n\t    for(int i=0; i<hash_size/*-1*/; i++)  // forget history\n\t      head[i]=0;\n\t  }\n\t}\n\tstrm.flush_pending();\n\tif(strm.avail_out == 0) {\n\t  last_flush = -1; // avoid BUF_ERROR at next call, see above\n\t  return Z_OK;\n\t}\n      }\n    }\n\n    if(flush!=Z_FINISH) return Z_OK;\n    if(wrap<=0) return Z_STREAM_END;\n\n    if(wrap==2){\n      long adler=strm.adler.getValue();\n      put_byte((byte)(adler&0xff));\n      put_byte((byte)((adler>>8)&0xff));\n      put_byte((byte)((adler>>16)&0xff));\n      put_byte((byte)((adler>>24)&0xff));\n      put_byte((byte)(strm.total_in&0xff));\n      put_byte((byte)((strm.total_in>>8)&0xff));\n      put_byte((byte)((strm.total_in>>16)&0xff));\n      put_byte((byte)((strm.total_in>>24)&0xff));\n\n      getGZIPHeader().setCRC(adler);\n    } \n    else{\n      // Write the zlib trailer (adler32)\n      long adler=strm.adler.getValue();\n      putShortMSB((int)(adler>>>16));\n      putShortMSB((int)(adler&0xffff));\n    }\n\n    strm.flush_pending();\n\n    // If avail_out is zero, the application will call deflate again\n    // to flush the rest.\n\n    if(wrap > 0) wrap = -wrap; // write the trailer only once!\n    return pending != 0 ? Z_OK : Z_STREAM_END;\n  }\n\n  static int deflateCopy(ZStream dest, ZStream src){\n\n    if(src.dstate == null){\n      return Z_STREAM_ERROR;\n    }\n\n    if(src.next_in!=null){\n      dest.next_in = new byte[src.next_in.length];\n      System.arraycopy(src.next_in, 0, dest.next_in, 0, src.next_in.length);\n    }\n    dest.next_in_index = src.next_in_index;\n    dest.avail_in = src.avail_in;\n    dest.total_in = src.total_in;\n\n    if(src.next_out!=null){\n      dest.next_out = new byte[src.next_out.length];\n      System.arraycopy(src.next_out, 0, dest.next_out ,0 , src.next_out.length);\n    }\n\n    dest.next_out_index = src.next_out_index;\n    dest.avail_out = src.avail_out;\n    dest.total_out = src.total_out;\n\n    dest.msg = src.msg;\n    dest.data_type = src.data_type;\n    dest.adler = src.adler.copy();\n\n    try{\n      dest.dstate = (Deflate)src.dstate.clone();\n      dest.dstate.strm = dest;\n    }\n    catch(CloneNotSupportedException e){\n      //\n    }\n    return Z_OK;\n  }\n\n  public Object clone() throws CloneNotSupportedException {\n    Deflate dest = (Deflate)super.clone();\n\n    dest.pending_buf = dup(dest.pending_buf);\n    dest.d_buf = dest.d_buf;\n    dest.l_buf = dup(dest.l_buf);\n    dest.window = dup(dest.window);\n\n    dest.prev = dup(dest.prev);\n    dest.head = dup(dest.head);\n    dest.dyn_ltree = dup(dest.dyn_ltree);\n    dest.dyn_dtree = dup(dest.dyn_dtree);\n    dest.bl_tree = dup(dest.bl_tree);\n\n    dest.bl_count = dup(dest.bl_count);\n    dest.next_code = dup(dest.next_code);\n    dest.heap = dup(dest.heap);\n    dest.depth = dup(dest.depth);\n\n    dest.l_desc.dyn_tree = dest.dyn_ltree;\n    dest.d_desc.dyn_tree = dest.dyn_dtree;\n    dest.bl_desc.dyn_tree = dest.bl_tree;\n\n    /*\n    dest.l_desc.stat_desc = StaticTree.static_l_desc;\n    dest.d_desc.stat_desc = StaticTree.static_d_desc;\n    dest.bl_desc.stat_desc = StaticTree.static_bl_desc;\n    */\n\n    if(dest.gheader!=null){\n      dest.gheader = (GZIPHeader)dest.gheader.clone();\n    }\n\n    return dest;\n  }\n\n  private byte[] dup(byte[] buf){\n    byte[] foo = new byte[buf.length];\n    System.arraycopy(buf, 0, foo, 0, foo.length);\n    return foo;\n  }\n  private short[] dup(short[] buf){\n    short[] foo = new short[buf.length];\n    System.arraycopy(buf, 0, foo, 0, foo.length);\n    return foo;\n  }\n  private int[] dup(int[] buf){\n    int[] foo = new int[buf.length];\n    System.arraycopy(buf, 0, foo, 0, foo.length);\n    return foo;\n  }\n\n  synchronized GZIPHeader getGZIPHeader(){\n    if(gheader==null){\n      gheader = new GZIPHeader();\n    }\n    return gheader;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/Deflater.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal public class Deflater extends ZStream{\n\n  static final private int MAX_WBITS=15;        // 32K LZ77 window\n  static final private int DEF_WBITS=MAX_WBITS;\n\n  static final private int Z_NO_FLUSH=0;\n  static final private int Z_PARTIAL_FLUSH=1;\n  static final private int Z_SYNC_FLUSH=2;\n  static final private int Z_FULL_FLUSH=3;\n  static final private int Z_FINISH=4;\n\n  static final private int MAX_MEM_LEVEL=9;\n\n  static final private int Z_OK=0;\n  static final private int Z_STREAM_END=1;\n  static final private int Z_NEED_DICT=2;\n  static final private int Z_ERRNO=-1;\n  static final private int Z_STREAM_ERROR=-2;\n  static final private int Z_DATA_ERROR=-3;\n  static final private int Z_MEM_ERROR=-4;\n  static final private int Z_BUF_ERROR=-5;\n  static final private int Z_VERSION_ERROR=-6;\n\n  private boolean finished = false;\n\n  public Deflater(){\n    super();\n  }\n\n  public Deflater(int level) throws GZIPException {\n    this(level, MAX_WBITS);\n  }\n\n  public Deflater(int level, boolean nowrap) throws GZIPException {\n    this(level, MAX_WBITS, nowrap);\n  }\n\n  public Deflater(int level, int bits) throws GZIPException {\n    this(level, bits, false);\n  }\n\n  public Deflater(int level, int bits, boolean nowrap) throws GZIPException {\n    super();\n    int ret = init(level, bits, nowrap);\n    if(ret!=Z_OK)\n      throw new GZIPException(ret+\": \"+msg);\n  }\n\n  public Deflater(int level, int bits, int memlevel, JZlib.WrapperType wrapperType) throws GZIPException {\n    super();\n    int ret = init(level, bits, memlevel, wrapperType);\n    if(ret!=Z_OK)\n      throw new GZIPException(ret+\": \"+msg);\n  }\n\n  public Deflater(int level, int bits, int memlevel) throws GZIPException {\n    super();\n    int ret = init(level, bits, memlevel);\n    if(ret!=Z_OK)\n      throw new GZIPException(ret+\": \"+msg);\n  }\n\n  public int init(int level){\n    return init(level, MAX_WBITS);\n  }\n  public int init(int level, boolean nowrap){\n    return init(level, MAX_WBITS, nowrap);\n  }\n  public int init(int level, int bits){\n    return init(level, bits, false);\n  }\n  public int init(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){\n    if(bits < 9 || bits > 15){\n      return Z_STREAM_ERROR;\n    }\n    if(wrapperType == JZlib.W_NONE) {\n      bits *= -1;\n    }\n    else if(wrapperType == JZlib.W_GZIP) {\n        bits += 16;\n    }\n    else if(wrapperType == JZlib.W_ANY) {\n        return Z_STREAM_ERROR;\n    }\n    else if(wrapperType == JZlib.W_ZLIB) {\n    }\n    return init(level, bits, memlevel);\n  }\n  public int init(int level, int bits, int memlevel){\n    finished = false;\n    dstate=new Deflate(this);\n    return dstate.deflateInit(level, bits, memlevel);\n  }\n  public int init(int level, int bits, boolean nowrap){\n    finished = false;\n    dstate=new Deflate(this);\n    return dstate.deflateInit(level, nowrap?-bits:bits);\n  }\n\n  public int deflate(int flush){\n    if(dstate==null){\n      return Z_STREAM_ERROR;\n    }\n    int ret = dstate.deflate(flush);\n    if(ret == Z_STREAM_END)\n      finished = true;\n    return ret;\n  }\n  public int end(){\n    finished = true;\n    if(dstate==null) return Z_STREAM_ERROR;\n    int ret=dstate.deflateEnd();\n    dstate=null;\n    free();\n    return ret;\n  }\n  public int params(int level, int strategy){\n    if(dstate==null) return Z_STREAM_ERROR;\n    return dstate.deflateParams(level, strategy);\n  }\n  public int setDictionary (byte[] dictionary, int dictLength){\n    if(dstate == null)\n      return Z_STREAM_ERROR;\n    return dstate.deflateSetDictionary(dictionary, dictLength);\n  }\n\n  public boolean finished(){\n    return finished;\n  }\n\n  public int copy(Deflater src){\n    this.finished = src.finished;\n    return Deflate.deflateCopy(this, src);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/DeflaterOutputStream.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\npackage com.jcraft.jzlib;\nimport java.io.*;\n\npublic class DeflaterOutputStream extends FilterOutputStream {\n\n  protected final Deflater deflater;\n\n  protected byte[] buffer;\n\n  private boolean closed = false;\n\n  private boolean syncFlush = false;\n\n  private final byte[] buf1 = new byte[1];\n\n  protected boolean mydeflater = false;\n\n  private boolean close_out = true;\n\n  protected static final int DEFAULT_BUFSIZE = 512;\n\n  public DeflaterOutputStream(OutputStream out) throws IOException {\n    this(out, \n         new Deflater(JZlib.Z_DEFAULT_COMPRESSION),\n         DEFAULT_BUFSIZE, true);\n    mydeflater = true;\n  }\n\n  public DeflaterOutputStream(OutputStream out, Deflater def) throws IOException {\n    this(out, def, DEFAULT_BUFSIZE, true);\n  }\n\n  public DeflaterOutputStream(OutputStream out,\n                              Deflater deflater,\n                              int size) throws IOException {\n    this(out, deflater, size, true);\n  }\n  public DeflaterOutputStream(OutputStream out,\n                              Deflater deflater,\n                              int size,\n                              boolean close_out)  throws IOException {\n    super(out);\n    if (out == null || deflater == null) {\n      throw new NullPointerException();\n    }\n    else if (size <= 0) {\n      throw new IllegalArgumentException(\"buffer size must be greater than 0\");\n    }\n    this.deflater = deflater;\n    buffer = new byte[size];\n    this.close_out = close_out;\n  }\n\n  public void write(int b) throws IOException {\n    buf1[0] = (byte)(b & 0xff);\n    write(buf1, 0, 1);\n  }\n\n  public void write(byte[] b, int off, int len) throws IOException {\n    if (deflater.finished()) {\n      throw new IOException(\"finished\");\n    }\n    else if (off<0 | len<0 | off+len>b.length) {\n      throw new IndexOutOfBoundsException();\n    }\n    else if (len == 0) {\n      return;\n    }\n    else {\n      int flush = syncFlush ? JZlib.Z_SYNC_FLUSH : JZlib.Z_NO_FLUSH;\n      deflater.setInput(b, off, len, true);\n      while (deflater.avail_in>0) {\n        int err = deflate(flush);\n        if (err == JZlib.Z_STREAM_END)\n          break;\n      }\n    }\n  }\n\n  public void finish() throws IOException {\n    while (!deflater.finished()) {\n      deflate(JZlib.Z_FINISH);\n    }\n  }\n\n  public void close() throws IOException {\n    if (!closed) {\n      finish();\n      if (mydeflater){\n        deflater.end();\n      }\n      if(close_out)\n        out.close();\n      closed = true;\n    }\n  }\n\n  protected int deflate(int flush) throws IOException {\n    deflater.setOutput(buffer, 0, buffer.length);\n    int err = deflater.deflate(flush);\n    switch(err) {\n      case JZlib.Z_OK:\n      case JZlib.Z_STREAM_END:\n        break;\n      case JZlib.Z_BUF_ERROR:\n        if(deflater.avail_in<=0 && flush!=JZlib.Z_FINISH){\n          // flush() without any data\n          break;\n        }\n      default:\n        throw new IOException(\"failed to deflate\");\n    }\n    int len = deflater.next_out_index;\n    if (len > 0) {\n      out.write(buffer, 0, len);\n    }\n    return err;\n  }\n\n  public void flush() throws IOException {\n    if (syncFlush && !deflater.finished()) {\n      while (true) {\n        int err = deflate(JZlib.Z_SYNC_FLUSH);\n        if (deflater.next_out_index < buffer.length)\n          break;\n        if (err == JZlib.Z_STREAM_END)\n          break;\n      }\n    }\n    out.flush();\n  }\n\n  public long getTotalIn() {\n    return deflater.getTotalIn();\n  }\n\n  public long getTotalOut() {\n    return deflater.getTotalOut();\n  }\n\n  public void setSyncFlush(boolean syncFlush){\n    this.syncFlush = syncFlush;\n  }\n\n  public boolean getSyncFlush(){\n    return this.syncFlush;\n  }\n\n  public Deflater getDeflater(){\n    return deflater;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/GZIPException.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\npublic class GZIPException extends java.io.IOException {\n  public GZIPException() {\n    super();\n  }\n  public GZIPException(String s) {\n    super(s);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/GZIPHeader.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nimport java.io.UnsupportedEncodingException;\n\n/**\n * @see \"http://www.ietf.org/rfc/rfc1952.txt\"\n */\npublic class GZIPHeader implements Cloneable {\n\n  public static final byte OS_MSDOS = (byte) 0x00;\n  public static final byte OS_AMIGA = (byte) 0x01;\n  public static final byte OS_VMS = (byte) 0x02;\n  public static final byte OS_UNIX = (byte) 0x03;\n  public static final byte OS_ATARI = (byte) 0x05;\n  public static final byte OS_OS2 = (byte) 0x06;\n  public static final byte OS_MACOS = (byte) 0x07;\n  public static final byte OS_TOPS20 = (byte) 0x0a;\n  public static final byte OS_WIN32 = (byte) 0x0b;\n  public static final byte OS_VMCMS = (byte) 0x04;\n  public static final byte OS_ZSYSTEM = (byte) 0x08;\n  public static final byte OS_CPM = (byte) 0x09;\n  public static final byte OS_QDOS = (byte) 0x0c;\n  public static final byte OS_RISCOS = (byte) 0x0d;\n  public static final byte OS_UNKNOWN = (byte) 0xff;\n\n  boolean text = false;\n  private boolean fhcrc = false;\n  long time;\n  int xflags;\n  int os = 255;\n  byte[] extra;\n  byte[] name;\n  byte[] comment;\n  int hcrc;\n  long crc;\n  boolean done = false;\n  long mtime = 0;\n\n  public void setModifiedTime(long mtime) {\n    this.mtime = mtime;\n  }\n\n  public long getModifiedTime() {\n    return mtime;\n  }\n\n  public void setOS(int os) {\n    if((0<=os && os <=13) || os==255)\n      this.os=os;\n    else\n      throw new IllegalArgumentException(\"os: \"+os);\n  }\n\n  public int getOS(){\n    return os;\n  }\n\n  public void setName(String name) {\n    try{\n      this.name=name.getBytes(\"ISO-8859-1\");\n    }\n    catch(UnsupportedEncodingException e){\n      throw new IllegalArgumentException(\"name must be in ISO-8859-1 \"+name);\n    }\n  }\n\n  public String getName(){\n    if(name==null) return \"\";\n    try {\n      return new String(name, \"ISO-8859-1\");\n    }\n    catch (UnsupportedEncodingException e) {\n      throw new InternalError(e.toString());\n    }\n  }\n\n  public void setComment(String comment) {\n    try{\n      this.comment=comment.getBytes(\"ISO-8859-1\");\n    }\n    catch(UnsupportedEncodingException e){\n      throw new IllegalArgumentException(\"comment must be in ISO-8859-1 \"+name);\n    }\n  }\n\n  public String getComment(){\n    if(comment==null) return \"\";\n    try {\n      return new String(comment, \"ISO-8859-1\");\n    }\n    catch (UnsupportedEncodingException e) {\n      throw new InternalError(e.toString());\n    }\n  }\n\n  public void setCRC(long crc){\n    this.crc = crc;\n  }\n\n  public long getCRC(){\n    return crc;\n  }\n\n  void put(Deflate d){\n    int flag = 0;\n    if(text){\n      flag |= 1;     // FTEXT\n    }\n    if(fhcrc){\n      flag |= 2;     // FHCRC\n    }\n    if(extra!=null){\n      flag |= 4;     // FEXTRA\n    }\n    if(name!=null){\n      flag |= 8;    // FNAME\n    }\n    if(comment!=null){\n      flag |= 16;   // FCOMMENT\n    }\n    int xfl = 0;\n    if(d.level == JZlib.Z_BEST_SPEED){\n      xfl |= 4;\n    }\n    else if (d.level == JZlib.Z_BEST_COMPRESSION){\n      xfl |= 2;\n    }\n\n    d.put_short((short)0x8b1f);  // ID1 ID2\n    d.put_byte((byte)8);         // CM(Compression Method)\n    d.put_byte((byte)flag);\n    d.put_byte((byte)mtime);\n    d.put_byte((byte)(mtime>>8));\n    d.put_byte((byte)(mtime>>16));\n    d.put_byte((byte)(mtime>>24));\n    d.put_byte((byte)xfl);\n    d.put_byte((byte)os);\n\n    if(extra!=null){\n      d.put_byte((byte)extra.length);\n      d.put_byte((byte)(extra.length>>8));\n      d.put_byte(extra, 0, extra.length);\n    }\n\n    if(name!=null){\n      d.put_byte(name, 0, name.length);\n      d.put_byte((byte)0);\n    }\n\n    if(comment!=null){\n      d.put_byte(comment, 0, comment.length);\n      d.put_byte((byte)0);\n    }\n  }\n\n  @Override\n  public Object clone() throws CloneNotSupportedException {\n    GZIPHeader gheader = (GZIPHeader)super.clone();\n    byte[] tmp;\n    if(gheader.extra!=null){\n      tmp=new byte[gheader.extra.length];\n      System.arraycopy(gheader.extra, 0, tmp, 0, tmp.length);\n      gheader.extra = tmp;\n    }\n\n    if(gheader.name!=null){\n      tmp=new byte[gheader.name.length];\n      System.arraycopy(gheader.name, 0, tmp, 0, tmp.length);\n      gheader.name = tmp;\n    }\n\n    if(gheader.comment!=null){\n      tmp=new byte[gheader.comment.length];\n      System.arraycopy(gheader.comment, 0, tmp, 0, tmp.length);\n      gheader.comment = tmp;\n    }\n\n    return gheader;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/GZIPInputStream.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\npackage com.jcraft.jzlib;\nimport java.io.*;\n\npublic class GZIPInputStream extends InflaterInputStream {\n\n  public GZIPInputStream(InputStream in) throws IOException {\n    this(in, DEFAULT_BUFSIZE, true);\n  }\n\n  public GZIPInputStream(InputStream in,\n                         int size,\n                         boolean close_in) throws IOException {\n    this(in, new Inflater(15+16), size, close_in);\n    myinflater = true;\n  }\n\n  public GZIPInputStream(InputStream in, \n                         Inflater inflater,\n                         int size,\n                         boolean close_in) throws IOException {\n    super(in, inflater, size, close_in);\n  }\n\n  public long getModifiedtime() {\n    return inflater.istate.getGZIPHeader().getModifiedTime();\n  }\n\n  public int getOS() {\n    return inflater.istate.getGZIPHeader().getOS();\n  }\n\n  public String getName() {\n    return inflater.istate.getGZIPHeader().getName();\n  }\n\n  public String getComment() {\n    return inflater.istate.getGZIPHeader().getComment();\n  }\n\n  public long getCRC() throws GZIPException {\n    if(inflater.istate.mode != 12 /*DONE*/)\n      throw new GZIPException(\"checksum is not calculated yet.\");\n    return inflater.istate.getGZIPHeader().getCRC();\n  }\n\n  public void readHeader() throws IOException {\n\n    byte[] empty = \"\".getBytes();\n    inflater.setOutput(empty, 0, 0);\n    inflater.setInput(empty, 0, 0, false);\n\n    byte[] b = new byte[10];\n\n    int n = fill(b);\n    if(n!=10){\n      if(n>0){\n        inflater.setInput(b, 0, n, false);\n        //inflater.next_in_index = n;\n        inflater.next_in_index = 0;\n        inflater.avail_in = n;\n      }\n      throw new IOException(\"no input\");\n    }\n\n    inflater.setInput(b, 0, n, false);\n\n    byte[] b1 = new byte[1];\n    do{\n      if(inflater.avail_in<=0){\n        int i = in.read(b1);\n        if(i<=0)\n          throw new IOException(\"no input\");\n        inflater.setInput(b1, 0, 1, true);\n      }\n\n      int err = inflater.inflate(JZlib.Z_NO_FLUSH);\n\n      if(err!=0/*Z_OK*/){\n        int len = 2048-inflater.next_in.length;\n        if(len>0){\n          byte[] tmp = new byte[len];\n          n = fill(tmp);\n          if(n>0){\n            inflater.avail_in += inflater.next_in_index;\n            inflater.next_in_index = 0;\n            inflater.setInput(tmp, 0, n, true);\n          }\n        }\n        //inflater.next_in_index = inflater.next_in.length;\n        inflater.avail_in += inflater.next_in_index;\n        inflater.next_in_index = 0;\n        throw new IOException(inflater.msg);\n      }\n    }\n    while(inflater.istate.inParsingHeader());\n  }\n\n  private int fill(byte[] buf) {\n    int len = buf.length;\n    int n = 0;\n    do{\n      int i = -1;\n      try {\n        i = in.read(buf, n, buf.length - n);\n      }\n      catch(IOException e){\n      }\n      if(i == -1){\n        break;\n      }\n      n+=i;\n    }\n    while(n<len);\n    return n;\n  }\n}"
  },
  {
    "path": "java/com/jcraft/jzlib/GZIPOutputStream.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\npackage com.jcraft.jzlib;\nimport java.io.*;\n\npublic class GZIPOutputStream extends DeflaterOutputStream {\n\n  public GZIPOutputStream(OutputStream out) throws IOException {\n    this(out, DEFAULT_BUFSIZE);\n  }\n\n  public GZIPOutputStream(OutputStream out, int size) throws IOException {\n    this(out, size, true);\n  }\n\n  public GZIPOutputStream(OutputStream out, \n                          int size,\n                          boolean close_out) throws IOException {\n    this(out,\n         new Deflater(JZlib.Z_DEFAULT_COMPRESSION, 15+16),\n         size, close_out);\n    mydeflater=true; \n  }\n\n  public GZIPOutputStream(OutputStream out, \n                          Deflater deflater,\n                          int size,\n                          boolean close_out) throws IOException{\n    super(out, deflater, size, close_out);\n  }\n\n\n  private void check() throws GZIPException {\n    if(deflater.dstate.status != 42 /*INIT_STATUS*/)\n      throw new GZIPException(\"header is already written.\");\n  }\n\n  public void setModifiedTime(long mtime) throws GZIPException {\n    check();\n    deflater.dstate.getGZIPHeader().setModifiedTime(mtime);\n  }\n\n  public void setOS(int os) throws GZIPException {\n    check();\n    deflater.dstate.getGZIPHeader().setOS(os);\n  }\n\n  public void setName(String name) throws GZIPException {\n    check();\n    deflater.dstate.getGZIPHeader().setName(name);\n  }\n\n  public void setComment(String comment) throws GZIPException {\n    check();\n    deflater.dstate.getGZIPHeader().setComment(comment);\n  }\n\n  public long getCRC() throws GZIPException {\n    if(deflater.dstate.status != 666 /*FINISH_STATE*/)\n      throw new GZIPException(\"checksum is not calculated yet.\");\n    return deflater.dstate.getGZIPHeader().getCRC();\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/InfBlocks.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal class InfBlocks{\n  static final private int MANY=1440;\n\n  // And'ing with mask[n] masks the lower n bits\n  static final private int[] inflate_mask = {\n    0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,\n    0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,\n    0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,\n    0x00007fff, 0x0000ffff\n  };\n\n  // Table for deflate from PKZIP's appnote.txt.\n  static final int[] border = { // Order of the bit length code lengths\n    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15\n  };\n\n  static final private int Z_OK=0;\n  static final private int Z_STREAM_END=1;\n  static final private int Z_NEED_DICT=2;\n  static final private int Z_ERRNO=-1;\n  static final private int Z_STREAM_ERROR=-2;\n  static final private int Z_DATA_ERROR=-3;\n  static final private int Z_MEM_ERROR=-4;\n  static final private int Z_BUF_ERROR=-5;\n  static final private int Z_VERSION_ERROR=-6;\n\n  static final private int TYPE=0;  // get type bits (3, including end bit)\n  static final private int LENS=1;  // get lengths for stored\n  static final private int STORED=2;// processing stored block\n  static final private int TABLE=3; // get table lengths\n  static final private int BTREE=4; // get bit lengths tree for a dynamic block\n  static final private int DTREE=5; // get length, distance trees for a dynamic block\n  static final private int CODES=6; // processing fixed or dynamic block\n  static final private int DRY=7;   // output remaining window bytes\n  static final private int DONE=8;  // finished last block, done\n  static final private int BAD=9;   // ot a data error--stuck here\n\n  int mode;            // current inflate_block mode \n\n  int left;            // if STORED, bytes left to copy \n\n  int table;           // table lengths (14 bits) \n  int index;           // index into blens (or border) \n  int[] blens;         // bit lengths of codes \n  int[] bb=new int[1]; // bit length tree depth \n  int[] tb=new int[1]; // bit length decoding tree \n\n  int[] bl=new int[1];\n  int[] bd=new int[1];\n\n  int[][] tl=new int[1][];\n  int[][] td=new int[1][];\n  int[] tli=new int[1]; // tl_index\n  int[] tdi=new int[1]; // td_index\n\n  private final InfCodes codes;      // if CODES, current state \n\n  int last;            // true if this block is the last block \n\n  // mode independent information \n  int bitk;            // bits in bit buffer \n  int bitb;            // bit buffer \n  int[] hufts;         // single malloc for tree space \n  byte[] window;       // sliding window \n  int end;             // one byte after sliding window \n  int read;            // window read pointer \n  int write;           // window write pointer \n  private boolean check;\n\n  private final InfTree inftree=new InfTree();\n\n  private final ZStream z; \n\n  InfBlocks(ZStream z, int w){\n    this.z=z;\n    this.codes=new InfCodes(this.z, this);\n    hufts=new int[MANY*3];\n    window=new byte[w];\n    end=w;\n    this.check = (z.istate.wrap==0) ? false : true;\n    mode = TYPE;\n    reset();\n  }\n\n  void reset(){\n    if(mode==BTREE || mode==DTREE){\n    }\n    if(mode==CODES){\n      codes.free(z);\n    }\n    mode=TYPE;\n    bitk=0;\n    bitb=0;\n    read=write=0;\n    if(check){\n      z.adler.reset();\n    }\n  }\n\n  int proc(int r){\n    int t;              // temporary storage\n    int b;              // bit buffer\n    int k;              // bits in bit buffer\n    int p;              // input data pointer\n    int n;              // bytes available there\n    int q;              // output window write pointer\n    int m;              // bytes to end of window or read pointer\n\n    // copy input/output information to locals (UPDATE macro restores)\n    {p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;}\n    {q=write;m=(int)(q<read?read-q-1:end-q);}\n\n    // process input based on current state\n    while(true){\n      switch (mode){\n      case TYPE:\n\n\twhile(k<(3)){\n\t  if(n!=0){\n\t    r=Z_OK;\n\t  }\n\t  else{\n\t    bitb=b; bitk=k; \n\t    z.avail_in=n;\n\t    z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t    write=q;\n\t    return inflate_flush(r);\n\t  };\n\t  n--;\n\t  b|=(z.next_in[p++]&0xff)<<k;\n\t  k+=8;\n\t}\n\tt = (int)(b & 7);\n\tlast = t & 1;\n\n\tswitch (t >>> 1){\n        case 0:                         // stored \n          {b>>>=(3);k-=(3);}\n          t = k & 7;                    // go to byte boundary\n\n          {b>>>=(t);k-=(t);}\n          mode = LENS;                  // get length of stored block\n          break;\n        case 1:                         // fixed\n          InfTree.inflate_trees_fixed(bl, bd, tl, td, z);\n          codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);\n\n          {b>>>=(3);k-=(3);}\n\n          mode = CODES;\n          break;\n        case 2:                         // dynamic\n\n          {b>>>=(3);k-=(3);}\n\n          mode = TABLE;\n          break;\n        case 3:                         // illegal\n\n          {b>>>=(3);k-=(3);}\n          mode = BAD;\n          z.msg = \"invalid block type\";\n          r = Z_DATA_ERROR;\n\n\t  bitb=b; bitk=k; \n\t  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t  write=q;\n\t  return inflate_flush(r);\n\t}\n\tbreak;\n      case LENS:\n\n\twhile(k<(32)){\n\t  if(n!=0){\n\t    r=Z_OK;\n\t  }\n\t  else{\n\t    bitb=b; bitk=k; \n\t    z.avail_in=n;\n\t    z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t    write=q;\n\t    return inflate_flush(r);\n\t  };\n\t  n--;\n\t  b|=(z.next_in[p++]&0xff)<<k;\n\t  k+=8;\n\t}\n\n\tif ((((~b) >>> 16) & 0xffff) != (b & 0xffff)){\n\t  mode = BAD;\n\t  z.msg = \"invalid stored block lengths\";\n\t  r = Z_DATA_ERROR;\n\n\t  bitb=b; bitk=k; \n\t  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t  write=q;\n\t  return inflate_flush(r);\n\t}\n\tleft = (b & 0xffff);\n\tb = k = 0;                       // dump bits\n\tmode = left!=0 ? STORED : (last!=0 ? DRY : TYPE);\n\tbreak;\n      case STORED:\n\tif (n == 0){\n\t  bitb=b; bitk=k; \n\t  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t  write=q;\n\t  return inflate_flush(r);\n\t}\n\n\tif(m==0){\n\t  if(q==end&&read!=0){\n\t    q=0; m=(int)(q<read?read-q-1:end-q);\n\t  }\n\t  if(m==0){\n\t    write=q; \n\t    r=inflate_flush(r);\n\t    q=write;m=(int)(q<read?read-q-1:end-q);\n\t    if(q==end&&read!=0){\n\t      q=0; m=(int)(q<read?read-q-1:end-q);\n\t    }\n\t    if(m==0){\n\t      bitb=b; bitk=k; \n\t      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t      write=q;\n\t      return inflate_flush(r);\n\t    }\n\t  }\n\t}\n\tr=Z_OK;\n\n\tt = left;\n\tif(t>n) t = n;\n\tif(t>m) t = m;\n\tSystem.arraycopy(z.next_in, p, window, q, t);\n\tp += t;  n -= t;\n\tq += t;  m -= t;\n\tif ((left -= t) != 0)\n\t  break;\n\tmode = last!=0 ? DRY : TYPE;\n\tbreak;\n      case TABLE:\n\n\twhile(k<(14)){\n\t  if(n!=0){\n\t    r=Z_OK;\n\t  }\n\t  else{\n\t    bitb=b; bitk=k; \n\t    z.avail_in=n;\n\t    z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t    write=q;\n\t    return inflate_flush(r);\n\t  };\n\t  n--;\n\t  b|=(z.next_in[p++]&0xff)<<k;\n\t  k+=8;\n\t}\n\n\ttable = t = (b & 0x3fff);\n\tif ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)\n\t  {\n\t    mode = BAD;\n\t    z.msg = \"too many length or distance symbols\";\n\t    r = Z_DATA_ERROR;\n\n\t    bitb=b; bitk=k; \n\t    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t    write=q;\n\t    return inflate_flush(r);\n\t  }\n\tt = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);\n\tif(blens==null || blens.length<t){\n\t  blens=new int[t];\n\t}\n\telse{\n\t  for(int i=0; i<t; i++){blens[i]=0;}\n\t}\n\n\t{b>>>=(14);k-=(14);}\n\n\tindex = 0;\n\tmode = BTREE;\n      case BTREE:\n\twhile (index < 4 + (table >>> 10)){\n\t  while(k<(3)){\n\t    if(n!=0){\n\t      r=Z_OK;\n\t    }\n\t    else{\n\t      bitb=b; bitk=k; \n\t      z.avail_in=n;\n\t      z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t      write=q;\n\t      return inflate_flush(r);\n\t    };\n\t    n--;\n\t    b|=(z.next_in[p++]&0xff)<<k;\n\t    k+=8;\n\t  }\n\n\t  blens[border[index++]] = b&7;\n\n\t  {b>>>=(3);k-=(3);}\n\t}\n\n\twhile(index < 19){\n\t  blens[border[index++]] = 0;\n\t}\n\n\tbb[0] = 7;\n\tt = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);\n\tif (t != Z_OK){\n\t  r = t;\n\t  if (r == Z_DATA_ERROR){\n\t    blens=null;\n\t    mode = BAD;\n\t  }\n\n\t  bitb=b; bitk=k; \n\t  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t  write=q;\n\t  return inflate_flush(r);\n\t}\n\n\tindex = 0;\n\tmode = DTREE;\n      case DTREE:\n\twhile (true){\n\t  t = table;\n\t  if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){\n\t    break;\n\t  }\n\n\t  int[] h;\n\t  int i, j, c;\n\n\t  t = bb[0];\n\n\t  while(k<(t)){\n\t    if(n!=0){\n\t      r=Z_OK;\n\t    }\n\t    else{\n\t      bitb=b; bitk=k; \n\t      z.avail_in=n;\n\t      z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t      write=q;\n\t      return inflate_flush(r);\n\t    };\n\t    n--;\n\t    b|=(z.next_in[p++]&0xff)<<k;\n\t    k+=8;\n\t  }\n\n\t  if(tb[0]==-1){\n            //System.err.println(\"null...\");\n\t  }\n\n\t  t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1];\n\t  c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2];\n\n\t  if (c < 16){\n\t    b>>>=(t);k-=(t);\n\t    blens[index++] = c;\n\t  }\n\t  else { // c == 16..18\n\t    i = c == 18 ? 7 : c - 14;\n\t    j = c == 18 ? 11 : 3;\n\n\t    while(k<(t+i)){\n\t      if(n!=0){\n\t\tr=Z_OK;\n\t      }\n\t      else{\n\t\tbitb=b; bitk=k; \n\t\tz.avail_in=n;\n\t\tz.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t\twrite=q;\n\t\treturn inflate_flush(r);\n\t      };\n\t      n--;\n\t      b|=(z.next_in[p++]&0xff)<<k;\n\t      k+=8;\n\t    }\n\n\t    b>>>=(t);k-=(t);\n\n\t    j += (b & inflate_mask[i]);\n\n\t    b>>>=(i);k-=(i);\n\n\t    i = index;\n\t    t = table;\n\t    if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||\n\t\t(c == 16 && i < 1)){\n\t      blens=null;\n\t      mode = BAD;\n\t      z.msg = \"invalid bit length repeat\";\n\t      r = Z_DATA_ERROR;\n\n\t      bitb=b; bitk=k; \n\t      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t      write=q;\n\t      return inflate_flush(r);\n\t    }\n\n\t    c = c == 16 ? blens[i-1] : 0;\n\t    do{\n\t      blens[i++] = c;\n\t    }\n\t    while (--j!=0);\n\t    index = i;\n\t  }\n\t}\n\n\ttb[0]=-1;\n\t{\n\t  bl[0] = 9;         // must be <= 9 for lookahead assumptions\n\t  bd[0] = 6;         // must be <= 9 for lookahead assumptions\n\t  t = table;\n\t  t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), \n\t\t\t\t\t    1 + ((t >> 5) & 0x1f),\n\t\t\t\t\t    blens, bl, bd, tli, tdi, hufts, z);\n\n\t  if (t != Z_OK){\n\t    if (t == Z_DATA_ERROR){\n\t      blens=null;\n\t      mode = BAD;\n\t    }\n\t    r = t;\n\n\t    bitb=b; bitk=k; \n\t    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t    write=q;\n\t    return inflate_flush(r);\n\t  }\n\t  codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]);\n\t}\n\tmode = CODES;\n      case CODES:\n\tbitb=b; bitk=k;\n\tz.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\twrite=q;\n\n\tif ((r = codes.proc(r)) != Z_STREAM_END){\n\t  return inflate_flush(r);\n\t}\n\tr = Z_OK;\n\tcodes.free(z);\n\n\tp=z.next_in_index; n=z.avail_in;b=bitb;k=bitk;\n\tq=write;m=(int)(q<read?read-q-1:end-q);\n\n\tif (last==0){\n\t  mode = TYPE;\n\t  break;\n\t}\n\tmode = DRY;\n      case DRY:\n\twrite=q; \n\tr=inflate_flush(r); \n\tq=write; m=(int)(q<read?read-q-1:end-q);\n\tif (read != write){\n\t  bitb=b; bitk=k; \n\t  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t  write=q;\n\t  return inflate_flush(r);\n\t}\n\tmode = DONE;\n      case DONE:\n\tr = Z_STREAM_END;\n\n\tbitb=b; bitk=k; \n\tz.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\twrite=q;\n\treturn inflate_flush(r);\n      case BAD:\n\tr = Z_DATA_ERROR;\n\n\tbitb=b; bitk=k; \n\tz.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\twrite=q;\n\treturn inflate_flush(r);\n\n      default:\n\tr = Z_STREAM_ERROR;\n\n\tbitb=b; bitk=k; \n\tz.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\twrite=q;\n\treturn inflate_flush(r);\n      }\n    }\n  }\n\n  void free(){\n    reset();\n    window=null;\n    hufts=null;\n    //ZFREE(z, s);\n  }\n\n  void set_dictionary(byte[] d, int start, int n){\n    System.arraycopy(d, start, window, 0, n);\n    read = write = n;\n  }\n\n  // Returns true if inflate is currently at the end of a block generated\n  // by Z_SYNC_FLUSH or Z_FULL_FLUSH. \n  int sync_point(){\n    return mode == LENS ? 1 : 0;\n  }\n\n  // copy as much as possible from the sliding window to the output area\n  int inflate_flush(int r){\n    int n;\n    int p;\n    int q;\n\n    // local copies of source and destination pointers\n    p = z.next_out_index;\n    q = read;\n\n    // compute number of bytes to copy as far as end of window\n    n = (int)((q <= write ? write : end) - q);\n    if(n > z.avail_out) n = z.avail_out;\n    if(n!=0 && r == Z_BUF_ERROR) r = Z_OK;\n\n    // update counters\n    z.avail_out -= n;\n    z.total_out += n;\n\n    // update check information\n    if(check && n>0){\n      z.adler.update(window, q, n);\n    }\n\n    // copy as far as end of window\n    System.arraycopy(window, q, z.next_out, p, n);\n    p += n;\n    q += n;\n\n    // see if more to copy at beginning of window\n    if (q == end){\n      // wrap pointers\n      q = 0;\n      if (write == end)\n        write = 0;\n\n      // compute bytes to copy\n      n = write - q;\n      if (n > z.avail_out) n = z.avail_out;\n      if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;\n\n      // update counters\n      z.avail_out -= n;\n      z.total_out += n;\n\n      // update check information\n      if(check && n>0){\n\tz.adler.update(window, q, n);\n      }\n\n      // copy\n      System.arraycopy(window, q, z.next_out, p, n);\n      p += n;\n      q += n;\n    }\n\n    // update pointers\n    z.next_out_index = p;\n    read = q;\n\n    // done\n    return r;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/InfCodes.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal class InfCodes{\n\n  static final private int[] inflate_mask = {\n    0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,\n    0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,\n    0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,\n    0x00007fff, 0x0000ffff\n  };\n\n  static final private int Z_OK=0;\n  static final private int Z_STREAM_END=1;\n  static final private int Z_NEED_DICT=2;\n  static final private int Z_ERRNO=-1;\n  static final private int Z_STREAM_ERROR=-2;\n  static final private int Z_DATA_ERROR=-3;\n  static final private int Z_MEM_ERROR=-4;\n  static final private int Z_BUF_ERROR=-5;\n  static final private int Z_VERSION_ERROR=-6;\n\n  // waiting for \"i:\"=input,\n  //             \"o:\"=output,\n  //             \"x:\"=nothing\n  static final private int START=0;  // x: set up for LEN\n  static final private int LEN=1;    // i: get length/literal/eob next\n  static final private int LENEXT=2; // i: getting length extra (have base)\n  static final private int DIST=3;   // i: get distance next\n  static final private int DISTEXT=4;// i: getting distance extra\n  static final private int COPY=5;   // o: copying bytes in window, waiting for space\n  static final private int LIT=6;    // o: got literal, waiting for output space\n  static final private int WASH=7;   // o: got eob, possibly still output waiting\n  static final private int END=8;    // x: got eob and all data flushed\n  static final private int BADCODE=9;// x: got error\n\n  int mode;      // current inflate_codes mode\n\n  // mode dependent information\n  int len;\n\n  int[] tree; // pointer into tree\n  int tree_index=0;\n  int need;   // bits needed\n\n  int lit;\n\n  // if EXT or COPY, where and how much\n  int get;              // bits to get for extra\n  int dist;             // distance back to copy from\n\n  byte lbits;           // ltree bits decoded per branch\n  byte dbits;           // dtree bits decoder per branch\n  int[] ltree;          // literal/length/eob tree\n  int ltree_index;      // literal/length/eob tree\n  int[] dtree;          // distance tree\n  int dtree_index;      // distance tree\n\n  private final ZStream z;\n  private final InfBlocks s;\n  InfCodes(ZStream z, InfBlocks s){\n    this.z=z; \n    this.s=s; \n  }\n\n  void init(int bl, int bd,\n\t   int[] tl, int tl_index,\n\t   int[] td, int td_index){\n    mode=START;\n    lbits=(byte)bl;\n    dbits=(byte)bd;\n    ltree=tl;\n    ltree_index=tl_index;\n    dtree = td;\n    dtree_index=td_index;\n    tree=null;\n  }\n\n  int proc(int r){ \n    int j;              // temporary storage\n    int[] t;            // temporary pointer\n    int tindex;         // temporary pointer\n    int e;              // extra bits or operation\n    int b=0;            // bit buffer\n    int k=0;            // bits in bit buffer\n    int p=0;            // input data pointer\n    int n;              // bytes available there\n    int q;              // output window write pointer\n    int m;              // bytes to end of window or read pointer\n    int f;              // pointer to copy strings from\n\n    // copy input/output information to locals (UPDATE macro restores)\n    p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;\n    q=s.write;m=q<s.read?s.read-q-1:s.end-q;\n\n    // process input and output based on current state\n    while (true){\n      switch (mode){\n\t// waiting for \"i:\"=input, \"o:\"=output, \"x:\"=nothing\n      case START:         // x: set up for LEN\n\tif (m >= 258 && n >= 10){\n\n\t  s.bitb=b;s.bitk=k;\n\t  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t  s.write=q;\n\t  r = inflate_fast(lbits, dbits, \n\t\t\t   ltree, ltree_index, \n\t\t\t   dtree, dtree_index,\n\t\t\t   s, z);\n\n\t  p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;\n\t  q=s.write;m=q<s.read?s.read-q-1:s.end-q;\n\n\t  if (r != Z_OK){\n\t    mode = r == Z_STREAM_END ? WASH : BADCODE;\n\t    break;\n\t  }\n\t}\n\tneed = lbits;\n\ttree = ltree;\n\ttree_index=ltree_index;\n\n\tmode = LEN;\n      case LEN:           // i: get length/literal/eob next\n\tj = need;\n\n\twhile(k<(j)){\n\t  if(n!=0)r=Z_OK;\n\t  else{\n\n\t    s.bitb=b;s.bitk=k;\n\t    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t    s.write=q;\n\t    return s.inflate_flush(r);\n\t  }\n\t  n--;\n\t  b|=(z.next_in[p++]&0xff)<<k;\n\t  k+=8;\n\t}\n\n\ttindex=(tree_index+(b&inflate_mask[j]))*3;\n\n\tb>>>=(tree[tindex+1]);\n\tk-=(tree[tindex+1]);\n\n\te=tree[tindex];\n\n\tif(e == 0){               // literal\n\t  lit = tree[tindex+2];\n\t  mode = LIT;\n\t  break;\n\t}\n\tif((e & 16)!=0 ){          // length\n\t  get = e & 15;\n\t  len = tree[tindex+2];\n\t  mode = LENEXT;\n\t  break;\n\t}\n\tif ((e & 64) == 0){        // next table\n\t  need = e;\n\t  tree_index = tindex/3+tree[tindex+2];\n\t  break;\n\t}\n\tif ((e & 32)!=0){               // end of block\n\t  mode = WASH;\n\t  break;\n\t}\n\tmode = BADCODE;        // invalid code\n\tz.msg = \"invalid literal/length code\";\n\tr = Z_DATA_ERROR;\n\n\ts.bitb=b;s.bitk=k;\n\tz.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\ts.write=q;\n\treturn s.inflate_flush(r);\n\n      case LENEXT:        // i: getting length extra (have base)\n\tj = get;\n\n\twhile(k<(j)){\n\t  if(n!=0)r=Z_OK;\n\t  else{\n\n\t    s.bitb=b;s.bitk=k;\n\t    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t    s.write=q;\n\t    return s.inflate_flush(r);\n\t  }\n\t  n--; b|=(z.next_in[p++]&0xff)<<k;\n\t  k+=8;\n\t}\n\n\tlen += (b & inflate_mask[j]);\n\n\tb>>=j;\n\tk-=j;\n\n\tneed = dbits;\n\ttree = dtree;\n\ttree_index=dtree_index;\n\tmode = DIST;\n      case DIST:          // i: get distance next\n\tj = need;\n\n\twhile(k<(j)){\n\t  if(n!=0)r=Z_OK;\n\t  else{\n\n\t    s.bitb=b;s.bitk=k;\n\t    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t    s.write=q;\n\t    return s.inflate_flush(r);\n\t  }\n\t  n--; b|=(z.next_in[p++]&0xff)<<k;\n\t  k+=8;\n\t}\n\n\ttindex=(tree_index+(b & inflate_mask[j]))*3;\n\n\tb>>=tree[tindex+1];\n\tk-=tree[tindex+1];\n\n\te = (tree[tindex]);\n\tif((e & 16)!=0){               // distance\n\t  get = e & 15;\n\t  dist = tree[tindex+2];\n\t  mode = DISTEXT;\n\t  break;\n\t}\n\tif ((e & 64) == 0){        // next table\n\t  need = e;\n\t  tree_index = tindex/3 + tree[tindex+2];\n\t  break;\n\t}\n\tmode = BADCODE;        // invalid code\n\tz.msg = \"invalid distance code\";\n\tr = Z_DATA_ERROR;\n\n\ts.bitb=b;s.bitk=k;\n\tz.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\ts.write=q;\n\treturn s.inflate_flush(r);\n\n      case DISTEXT:       // i: getting distance extra\n\tj = get;\n\n\twhile(k<(j)){\n\t  if(n!=0)r=Z_OK;\n\t  else{\n\n\t    s.bitb=b;s.bitk=k;\n\t    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t    s.write=q;\n\t    return s.inflate_flush(r);\n\t  }\n\t  n--; b|=(z.next_in[p++]&0xff)<<k;\n\t  k+=8;\n\t}\n\n\tdist += (b & inflate_mask[j]);\n\n\tb>>=j;\n\tk-=j;\n\n\tmode = COPY;\n      case COPY:          // o: copying bytes in window, waiting for space\n        f = q - dist;\n        while(f < 0){     // modulo window size-\"while\" instead\n          f += s.end;     // of \"if\" handles invalid distances\n\t}\n\twhile (len!=0){\n\n\t  if(m==0){\n\t    if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}\n\t    if(m==0){\n\t      s.write=q; r=s.inflate_flush(r);\n\t      q=s.write;m=q<s.read?s.read-q-1:s.end-q;\n\n\t      if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}\n\n\t      if(m==0){\n\t\ts.bitb=b;s.bitk=k;\n\t\tz.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t\ts.write=q;\n\t\treturn s.inflate_flush(r);\n\t      }  \n\t    }\n\t  }\n\n\t  s.window[q++]=s.window[f++]; m--;\n\n\t  if (f == s.end)\n            f = 0;\n\t  len--;\n\t}\n\tmode = START;\n\tbreak;\n      case LIT:           // o: got literal, waiting for output space\n\tif(m==0){\n\t  if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}\n\t  if(m==0){\n\t    s.write=q; r=s.inflate_flush(r);\n\t    q=s.write;m=q<s.read?s.read-q-1:s.end-q;\n\n\t    if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}\n\t    if(m==0){\n\t      s.bitb=b;s.bitk=k;\n\t      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t      s.write=q;\n\t      return s.inflate_flush(r);\n\t    }\n\t  }\n\t}\n\tr=Z_OK;\n\n\ts.window[q++]=(byte)lit; m--;\n\n\tmode = START;\n\tbreak;\n      case WASH:           // o: got eob, possibly more output\n\tif (k > 7){        // return unused byte, if any\n\t  k -= 8;\n\t  n++;\n\t  p--;             // can always return one\n\t}\n\n\ts.write=q; r=s.inflate_flush(r);\n\tq=s.write;m=q<s.read?s.read-q-1:s.end-q;\n\n\tif (s.read != s.write){\n\t  s.bitb=b;s.bitk=k;\n\t  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t  s.write=q;\n\t  return s.inflate_flush(r);\n\t}\n\tmode = END;\n      case END:\n\tr = Z_STREAM_END;\n\ts.bitb=b;s.bitk=k;\n\tz.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\ts.write=q;\n\treturn s.inflate_flush(r);\n\n      case BADCODE:       // x: got error\n\n\tr = Z_DATA_ERROR;\n\n\ts.bitb=b;s.bitk=k;\n\tz.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\ts.write=q;\n\treturn s.inflate_flush(r);\n\n      default:\n\tr = Z_STREAM_ERROR;\n\n\ts.bitb=b;s.bitk=k;\n\tz.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\ts.write=q;\n\treturn s.inflate_flush(r);\n      }\n    }\n  }\n\n  void free(ZStream z){\n    //  ZFREE(z, c);\n  }\n\n  // Called with number of bytes left to write in window at least 258\n  // (the maximum string length) and number of input bytes available\n  // at least ten.  The ten bytes are six bytes for the longest length/\n  // distance pair plus four bytes for overloading the bit buffer.\n\n  int inflate_fast(int bl, int bd, \n\t\t   int[] tl, int tl_index,\n\t\t   int[] td, int td_index,\n\t\t   InfBlocks s, ZStream z){\n    int t;                // temporary pointer\n    int[] tp;             // temporary pointer\n    int tp_index;         // temporary pointer\n    int e;                // extra bits or operation\n    int b;                // bit buffer\n    int k;                // bits in bit buffer\n    int p;                // input data pointer\n    int n;                // bytes available there\n    int q;                // output window write pointer\n    int m;                // bytes to end of window or read pointer\n    int ml;               // mask for literal/length tree\n    int md;               // mask for distance tree\n    int c;                // bytes to copy\n    int d;                // distance back to copy from\n    int r;                // copy source pointer\n\n    int tp_index_t_3;     // (tp_index+t)*3\n\n    // load input, output, bit values\n    p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;\n    q=s.write;m=q<s.read?s.read-q-1:s.end-q;\n\n    // initialize masks\n    ml = inflate_mask[bl];\n    md = inflate_mask[bd];\n\n    // do until not enough input or output space for fast loop\n    do {                          // assume called with m >= 258 && n >= 10\n      // get literal/length code\n      while(k<(20)){              // max bits for literal/length code\n\tn--;\n\tb|=(z.next_in[p++]&0xff)<<k;k+=8;\n      }\n\n      t= b&ml;\n      tp=tl; \n      tp_index=tl_index;\n      tp_index_t_3=(tp_index+t)*3;\n      if ((e = tp[tp_index_t_3]) == 0){\n\tb>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);\n\n\ts.window[q++] = (byte)tp[tp_index_t_3+2];\n\tm--;\n\tcontinue;\n      }\n      do {\n\n\tb>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);\n\n\tif((e&16)!=0){\n\t  e &= 15;\n\t  c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);\n\n\t  b>>=e; k-=e;\n\n\t  // decode distance base of block to copy\n\t  while(k<(15)){           // max bits for distance code\n\t    n--;\n\t    b|=(z.next_in[p++]&0xff)<<k;k+=8;\n\t  }\n\n\t  t= b&md;\n\t  tp=td;\n\t  tp_index=td_index;\n          tp_index_t_3=(tp_index+t)*3;\n\t  e = tp[tp_index_t_3];\n\n\t  do {\n\n\t    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);\n\n\t    if((e&16)!=0){\n\t      // get extra bits to add to distance base\n\t      e &= 15;\n\t      while(k<(e)){         // get extra bits (up to 13)\n\t\tn--;\n\t\tb|=(z.next_in[p++]&0xff)<<k;k+=8;\n\t      }\n\n\t      d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);\n\n\t      b>>=(e); k-=(e);\n\n\t      // do the copy\n\t      m -= c;\n\t      if (q >= d){                // offset before dest\n\t\t//  just copy\n\t\tr=q-d;\n\t\tif(q-r>0 && 2>(q-r)){           \n\t\t  s.window[q++]=s.window[r++]; // minimum count is three,\n\t\t  s.window[q++]=s.window[r++]; // so unroll loop a little\n\t\t  c-=2;\n\t\t}\n\t\telse{\n\t\t  System.arraycopy(s.window, r, s.window, q, 2);\n\t\t  q+=2; r+=2; c-=2;\n\t\t}\n\t      }\n\t      else{                  // else offset after destination\n                r=q-d;\n                do{\n                  r+=s.end;          // force pointer in window\n                }while(r<0);         // covers invalid distances\n\t\te=s.end-r;\n\t\tif(c>e){             // if source crosses,\n\t\t  c-=e;              // wrapped copy\n\t\t  if(q-r>0 && e>(q-r)){           \n\t\t    do{s.window[q++] = s.window[r++];}\n\t\t    while(--e!=0);\n\t\t  }\n\t\t  else{\n\t\t    System.arraycopy(s.window, r, s.window, q, e);\n\t\t    q+=e; r+=e; e=0;\n\t\t  }\n\t\t  r = 0;                  // copy rest from start of window\n\t\t}\n\n\t      }\n\n\t      // copy all or what's left\n\t      if(q-r>0 && c>(q-r)){           \n\t\tdo{s.window[q++] = s.window[r++];}\n\t\twhile(--c!=0);\n\t      }\n\t      else{\n\t\tSystem.arraycopy(s.window, r, s.window, q, c);\n\t\tq+=c; r+=c; c=0;\n\t      }\n\t      break;\n\t    }\n\t    else if((e&64)==0){\n\t      t+=tp[tp_index_t_3+2];\n\t      t+=(b&inflate_mask[e]);\n\t      tp_index_t_3=(tp_index+t)*3;\n\t      e=tp[tp_index_t_3];\n\t    }\n\t    else{\n\t      z.msg = \"invalid distance code\";\n\n\t      c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;\n\n\t      s.bitb=b;s.bitk=k;\n\t      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t      s.write=q;\n\n\t      return Z_DATA_ERROR;\n\t    }\n\t  }\n\t  while(true);\n\t  break;\n\t}\n\n\tif((e&64)==0){\n\t  t+=tp[tp_index_t_3+2];\n\t  t+=(b&inflate_mask[e]);\n\t  tp_index_t_3=(tp_index+t)*3;\n\t  if((e=tp[tp_index_t_3])==0){\n\n\t    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);\n\n\t    s.window[q++]=(byte)tp[tp_index_t_3+2];\n\t    m--;\n\t    break;\n\t  }\n\t}\n\telse if((e&32)!=0){\n\n\t  c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;\n \n\t  s.bitb=b;s.bitk=k;\n\t  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t  s.write=q;\n\n\t  return Z_STREAM_END;\n\t}\n\telse{\n\t  z.msg=\"invalid literal/length code\";\n\n\t  c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;\n\n\t  s.bitb=b;s.bitk=k;\n\t  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n\t  s.write=q;\n\n\t  return Z_DATA_ERROR;\n\t}\n      } \n      while(true);\n    } \n    while(m>=258 && n>= 10);\n\n    // not enough input or output--restore pointers and return\n    c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;\n\n    s.bitb=b;s.bitk=k;\n    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;\n    s.write=q;\n\n    return Z_OK;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/InfTree.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal class InfTree{\n\n  static final private int MANY=1440;\n\n  static final private int Z_OK=0;\n  static final private int Z_STREAM_END=1;\n  static final private int Z_NEED_DICT=2;\n  static final private int Z_ERRNO=-1;\n  static final private int Z_STREAM_ERROR=-2;\n  static final private int Z_DATA_ERROR=-3;\n  static final private int Z_MEM_ERROR=-4;\n  static final private int Z_BUF_ERROR=-5;\n  static final private int Z_VERSION_ERROR=-6;\n\n  static final int fixed_bl = 9;\n  static final int fixed_bd = 5;\n\n  static final int[] fixed_tl = {\n    96,7,256, 0,8,80, 0,8,16, 84,8,115,\n    82,7,31, 0,8,112, 0,8,48, 0,9,192,\n    80,7,10, 0,8,96, 0,8,32, 0,9,160,\n    0,8,0, 0,8,128, 0,8,64, 0,9,224,\n    80,7,6, 0,8,88, 0,8,24, 0,9,144,\n    83,7,59, 0,8,120, 0,8,56, 0,9,208,\n    81,7,17, 0,8,104, 0,8,40, 0,9,176,\n    0,8,8, 0,8,136, 0,8,72, 0,9,240,\n    80,7,4, 0,8,84, 0,8,20, 85,8,227,\n    83,7,43, 0,8,116, 0,8,52, 0,9,200,\n    81,7,13, 0,8,100, 0,8,36, 0,9,168,\n    0,8,4, 0,8,132, 0,8,68, 0,9,232,\n    80,7,8, 0,8,92, 0,8,28, 0,9,152,\n    84,7,83, 0,8,124, 0,8,60, 0,9,216,\n    82,7,23, 0,8,108, 0,8,44, 0,9,184,\n    0,8,12, 0,8,140, 0,8,76, 0,9,248,\n    80,7,3, 0,8,82, 0,8,18, 85,8,163,\n    83,7,35, 0,8,114, 0,8,50, 0,9,196,\n    81,7,11, 0,8,98, 0,8,34, 0,9,164,\n    0,8,2, 0,8,130, 0,8,66, 0,9,228,\n    80,7,7, 0,8,90, 0,8,26, 0,9,148,\n    84,7,67, 0,8,122, 0,8,58, 0,9,212,\n    82,7,19, 0,8,106, 0,8,42, 0,9,180,\n    0,8,10, 0,8,138, 0,8,74, 0,9,244,\n    80,7,5, 0,8,86, 0,8,22, 192,8,0,\n    83,7,51, 0,8,118, 0,8,54, 0,9,204,\n    81,7,15, 0,8,102, 0,8,38, 0,9,172,\n    0,8,6, 0,8,134, 0,8,70, 0,9,236,\n    80,7,9, 0,8,94, 0,8,30, 0,9,156,\n    84,7,99, 0,8,126, 0,8,62, 0,9,220,\n    82,7,27, 0,8,110, 0,8,46, 0,9,188,\n    0,8,14, 0,8,142, 0,8,78, 0,9,252,\n    96,7,256, 0,8,81, 0,8,17, 85,8,131,\n    82,7,31, 0,8,113, 0,8,49, 0,9,194,\n    80,7,10, 0,8,97, 0,8,33, 0,9,162,\n    0,8,1, 0,8,129, 0,8,65, 0,9,226,\n    80,7,6, 0,8,89, 0,8,25, 0,9,146,\n    83,7,59, 0,8,121, 0,8,57, 0,9,210,\n    81,7,17, 0,8,105, 0,8,41, 0,9,178,\n    0,8,9, 0,8,137, 0,8,73, 0,9,242,\n    80,7,4, 0,8,85, 0,8,21, 80,8,258,\n    83,7,43, 0,8,117, 0,8,53, 0,9,202,\n    81,7,13, 0,8,101, 0,8,37, 0,9,170,\n    0,8,5, 0,8,133, 0,8,69, 0,9,234,\n    80,7,8, 0,8,93, 0,8,29, 0,9,154,\n    84,7,83, 0,8,125, 0,8,61, 0,9,218,\n    82,7,23, 0,8,109, 0,8,45, 0,9,186,\n    0,8,13, 0,8,141, 0,8,77, 0,9,250,\n    80,7,3, 0,8,83, 0,8,19, 85,8,195,\n    83,7,35, 0,8,115, 0,8,51, 0,9,198,\n    81,7,11, 0,8,99, 0,8,35, 0,9,166,\n    0,8,3, 0,8,131, 0,8,67, 0,9,230,\n    80,7,7, 0,8,91, 0,8,27, 0,9,150,\n    84,7,67, 0,8,123, 0,8,59, 0,9,214,\n    82,7,19, 0,8,107, 0,8,43, 0,9,182,\n    0,8,11, 0,8,139, 0,8,75, 0,9,246,\n    80,7,5, 0,8,87, 0,8,23, 192,8,0,\n    83,7,51, 0,8,119, 0,8,55, 0,9,206,\n    81,7,15, 0,8,103, 0,8,39, 0,9,174,\n    0,8,7, 0,8,135, 0,8,71, 0,9,238,\n    80,7,9, 0,8,95, 0,8,31, 0,9,158,\n    84,7,99, 0,8,127, 0,8,63, 0,9,222,\n    82,7,27, 0,8,111, 0,8,47, 0,9,190,\n    0,8,15, 0,8,143, 0,8,79, 0,9,254,\n    96,7,256, 0,8,80, 0,8,16, 84,8,115,\n    82,7,31, 0,8,112, 0,8,48, 0,9,193,\n\n    80,7,10, 0,8,96, 0,8,32, 0,9,161,\n    0,8,0, 0,8,128, 0,8,64, 0,9,225,\n    80,7,6, 0,8,88, 0,8,24, 0,9,145,\n    83,7,59, 0,8,120, 0,8,56, 0,9,209,\n    81,7,17, 0,8,104, 0,8,40, 0,9,177,\n    0,8,8, 0,8,136, 0,8,72, 0,9,241,\n    80,7,4, 0,8,84, 0,8,20, 85,8,227,\n    83,7,43, 0,8,116, 0,8,52, 0,9,201,\n    81,7,13, 0,8,100, 0,8,36, 0,9,169,\n    0,8,4, 0,8,132, 0,8,68, 0,9,233,\n    80,7,8, 0,8,92, 0,8,28, 0,9,153,\n    84,7,83, 0,8,124, 0,8,60, 0,9,217,\n    82,7,23, 0,8,108, 0,8,44, 0,9,185,\n    0,8,12, 0,8,140, 0,8,76, 0,9,249,\n    80,7,3, 0,8,82, 0,8,18, 85,8,163,\n    83,7,35, 0,8,114, 0,8,50, 0,9,197,\n    81,7,11, 0,8,98, 0,8,34, 0,9,165,\n    0,8,2, 0,8,130, 0,8,66, 0,9,229,\n    80,7,7, 0,8,90, 0,8,26, 0,9,149,\n    84,7,67, 0,8,122, 0,8,58, 0,9,213,\n    82,7,19, 0,8,106, 0,8,42, 0,9,181,\n    0,8,10, 0,8,138, 0,8,74, 0,9,245,\n    80,7,5, 0,8,86, 0,8,22, 192,8,0,\n    83,7,51, 0,8,118, 0,8,54, 0,9,205,\n    81,7,15, 0,8,102, 0,8,38, 0,9,173,\n    0,8,6, 0,8,134, 0,8,70, 0,9,237,\n    80,7,9, 0,8,94, 0,8,30, 0,9,157,\n    84,7,99, 0,8,126, 0,8,62, 0,9,221,\n    82,7,27, 0,8,110, 0,8,46, 0,9,189,\n    0,8,14, 0,8,142, 0,8,78, 0,9,253,\n    96,7,256, 0,8,81, 0,8,17, 85,8,131,\n    82,7,31, 0,8,113, 0,8,49, 0,9,195,\n    80,7,10, 0,8,97, 0,8,33, 0,9,163,\n    0,8,1, 0,8,129, 0,8,65, 0,9,227,\n    80,7,6, 0,8,89, 0,8,25, 0,9,147,\n    83,7,59, 0,8,121, 0,8,57, 0,9,211,\n    81,7,17, 0,8,105, 0,8,41, 0,9,179,\n    0,8,9, 0,8,137, 0,8,73, 0,9,243,\n    80,7,4, 0,8,85, 0,8,21, 80,8,258,\n    83,7,43, 0,8,117, 0,8,53, 0,9,203,\n    81,7,13, 0,8,101, 0,8,37, 0,9,171,\n    0,8,5, 0,8,133, 0,8,69, 0,9,235,\n    80,7,8, 0,8,93, 0,8,29, 0,9,155,\n    84,7,83, 0,8,125, 0,8,61, 0,9,219,\n    82,7,23, 0,8,109, 0,8,45, 0,9,187,\n    0,8,13, 0,8,141, 0,8,77, 0,9,251,\n    80,7,3, 0,8,83, 0,8,19, 85,8,195,\n    83,7,35, 0,8,115, 0,8,51, 0,9,199,\n    81,7,11, 0,8,99, 0,8,35, 0,9,167,\n    0,8,3, 0,8,131, 0,8,67, 0,9,231,\n    80,7,7, 0,8,91, 0,8,27, 0,9,151,\n    84,7,67, 0,8,123, 0,8,59, 0,9,215,\n    82,7,19, 0,8,107, 0,8,43, 0,9,183,\n    0,8,11, 0,8,139, 0,8,75, 0,9,247,\n    80,7,5, 0,8,87, 0,8,23, 192,8,0,\n    83,7,51, 0,8,119, 0,8,55, 0,9,207,\n    81,7,15, 0,8,103, 0,8,39, 0,9,175,\n    0,8,7, 0,8,135, 0,8,71, 0,9,239,\n    80,7,9, 0,8,95, 0,8,31, 0,9,159,\n    84,7,99, 0,8,127, 0,8,63, 0,9,223,\n    82,7,27, 0,8,111, 0,8,47, 0,9,191,\n    0,8,15, 0,8,143, 0,8,79, 0,9,255\n  };\n  static final int[] fixed_td = {\n    80,5,1, 87,5,257, 83,5,17, 91,5,4097,\n    81,5,5, 89,5,1025, 85,5,65, 93,5,16385,\n    80,5,3, 88,5,513, 84,5,33, 92,5,8193,\n    82,5,9, 90,5,2049, 86,5,129, 192,5,24577,\n    80,5,2, 87,5,385, 83,5,25, 91,5,6145,\n    81,5,7, 89,5,1537, 85,5,97, 93,5,24577,\n    80,5,4, 88,5,769, 84,5,49, 92,5,12289,\n    82,5,13, 90,5,3073, 86,5,193, 192,5,24577\n  };\n\n  // Tables for deflate from PKZIP's appnote.txt.\n  static final int[] cplens = { // Copy lengths for literal codes 257..285\n        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0\n  };\n\n  // see note #13 above about 258\n  static final int[] cplext = { // Extra bits for literal codes 257..285\n        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,\n        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112  // 112==invalid\n  };\n\n  static final int[] cpdist = { // Copy offsets for distance codes 0..29\n        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\n        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\n        8193, 12289, 16385, 24577\n  };\n\n  static final int[] cpdext = { // Extra bits for distance codes\n        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,\n        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,\n        12, 12, 13, 13};\n\n  // If BMAX needs to be larger than 16, then h and x[] should be uLong.\n  static final int BMAX=15;         // maximum bit length of any code\n\n  int[] hn = null;  // hufts used in space\n  int[] v = null;   // work area for huft_build \n  int[] c = null;   // bit length count table\n  int[] r = null;   // table entry for structure assignment\n  int[] u = null;   // table stack\n  int[] x = null;   // bit offsets, then code stack\n\n  private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX)\n                         int bindex, \n                         int n,   // number of codes (assumed <= 288)\n                         int s,   // number of simple-valued codes (0..s-1)\n                         int[] d, // list of base values for non-simple codes\n                         int[] e, // list of extra bits for non-simple codes\n                         int[] t, // result: starting table\n                         int[] m, // maximum lookup bits, returns actual\n                         int[] hp,// space for trees\n                         int[] hn,// hufts used in space\n                         int[] v  // working area: values in order of bit length\n                         ){\n    // Given a list of code lengths and a maximum table size, make a set of\n    // tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR\n    // if the given code set is incomplete (the tables are still built in this\n    // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of\n    // lengths), or Z_MEM_ERROR if not enough memory.\n\n    int a;                       // counter for codes of length k\n    int f;                       // i repeats in table every f entries\n    int g;                       // maximum code length\n    int h;                       // table level\n    int i;                       // counter, current code\n    int j;                       // counter\n    int k;                       // number of bits in current code\n    int l;                       // bits per table (returned in m)\n    int mask;                    // (1 << w) - 1, to avoid cc -O bug on HP\n    int p;                       // pointer into c[], b[], or v[]\n    int q;                       // points to current table\n    int w;                       // bits before this table == (l * h)\n    int xp;                      // pointer into x\n    int y;                       // number of dummy codes added\n    int z;                       // number of entries in current table\n\n    // Generate counts for each bit length\n\n    p = 0; i = n;\n    do {\n      c[b[bindex+p]]++; p++; i--;   // assume all entries <= BMAX\n    }while(i!=0);\n\n    if(c[0] == n){                // null input--all zero length codes\n      t[0] = -1;\n      m[0] = 0;\n      return Z_OK;\n    }\n\n    // Find minimum and maximum length, bound *m by those\n    l = m[0];\n    for (j = 1; j <= BMAX; j++)\n      if(c[j]!=0) break;\n    k = j;                        // minimum code length\n    if(l < j){\n      l = j;\n    }\n    for (i = BMAX; i!=0; i--){\n      if(c[i]!=0) break;\n    }\n    g = i;                        // maximum code length\n    if(l > i){\n      l = i;\n    }\n    m[0] = l;\n\n    // Adjust last length count to fill out codes, if needed\n    for (y = 1 << j; j < i; j++, y <<= 1){\n      if ((y -= c[j]) < 0){\n        return Z_DATA_ERROR;\n      }\n    }\n    if ((y -= c[i]) < 0){\n      return Z_DATA_ERROR;\n    }\n    c[i] += y;\n\n    // Generate starting offsets into the value table for each length\n    x[1] = j = 0;\n    p = 1;  xp = 2;\n    while (--i!=0) {                 // note that i == g from above\n      x[xp] = (j += c[p]);\n      xp++;\n      p++;\n    }\n\n    // Make a table of values in order of bit lengths\n    i = 0; p = 0;\n    do {\n      if ((j = b[bindex+p]) != 0){\n        v[x[j]++] = i;\n      }\n      p++;\n    }\n    while (++i < n);\n    n = x[g];                     // set n to length of v\n\n    // Generate the Huffman codes and for each, make the table entries\n    x[0] = i = 0;                 // first Huffman code is zero\n    p = 0;                        // grab values in bit order\n    h = -1;                       // no tables yet--level -1\n    w = -l;                       // bits decoded == (l * h)\n    u[0] = 0;                     // just to keep compilers happy\n    q = 0;                        // ditto\n    z = 0;                        // ditto\n\n    // go through the bit lengths (k already is bits in shortest code)\n    for (; k <= g; k++){\n      a = c[k];\n      while (a--!=0){\n\t// here i is the Huffman code of length k bits for value *p\n\t// make tables up to required level\n        while (k > w + l){\n          h++;\n          w += l;                 // previous table always l bits\n\t  // compute minimum size table less than or equal to l bits\n          z = g - w;\n          z = (z > l) ? l : z;        // table size upper limit\n          if((f=1<<(j=k-w))>a+1){     // try a k-w bit table\n                                      // too few codes for k-w bit table\n            f -= a + 1;               // deduct codes from patterns left\n            xp = k;\n            if(j < z){\n              while (++j < z){        // try smaller tables up to z bits\n                if((f <<= 1) <= c[++xp])\n                  break;              // enough codes to use up j bits\n                f -= c[xp];           // else deduct codes from patterns\n              }\n\t    }\n          }\n          z = 1 << j;                 // table entries for j-bit table\n\n\t  // allocate new table\n          if (hn[0] + z > MANY){       // (note: doesn't matter for fixed)\n            return Z_DATA_ERROR;       // overflow of MANY\n          }\n          u[h] = q = /*hp+*/ hn[0];   // DEBUG\n          hn[0] += z;\n \n\t  // connect to last table, if there is one\n\t  if(h!=0){\n            x[h]=i;           // save pattern for backing up\n            r[0]=(byte)j;     // bits in this table\n            r[1]=(byte)l;     // bits to dump before this table\n            j=i>>>(w - l);\n            r[2] = (int)(q - u[h-1] - j);               // offset to this table\n            System.arraycopy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table\n          }\n          else{\n            t[0] = q;               // first table is returned result\n\t  }\n        }\n\n\t// set up table entry in r\n        r[1] = (byte)(k - w);\n        if (p >= n){\n          r[0] = 128 + 64;      // out of values--invalid code\n\t}\n        else if (v[p] < s){\n          r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64);  // 256 is end-of-block\n          r[2] = v[p++];          // simple code is just the value\n        }\n        else{\n          r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists\n          r[2]=d[v[p++] - s];\n        }\n\n        // fill code-like entries with r\n        f=1<<(k-w);\n        for (j=i>>>w;j<z;j+=f){\n          System.arraycopy(r, 0, hp, (q+j)*3, 3);\n\t}\n\n\t// backwards increment the k-bit code i\n        for (j = 1 << (k - 1); (i & j)!=0; j >>>= 1){\n          i ^= j;\n\t}\n        i ^= j;\n\n\t// backup over finished tables\n        mask = (1 << w) - 1;      // needed on HP, cc -O bug\n        while ((i & mask) != x[h]){\n          h--;                    // don't need to update q\n          w -= l;\n          mask = (1 << w) - 1;\n        }\n      }\n    }\n    // Return Z_BUF_ERROR if we were given an incomplete table\n    return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;\n  }\n\n  int inflate_trees_bits(int[] c,  // 19 code lengths\n                         int[] bb, // bits tree desired/actual depth\n                         int[] tb, // bits tree result\n                         int[] hp, // space for trees\n                         ZStream z // for messages\n                         ){\n    int result;\n    initWorkArea(19);\n    hn[0]=0;\n    result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);\n\n    if(result == Z_DATA_ERROR){\n      z.msg = \"oversubscribed dynamic bit lengths tree\";\n    }\n    else if(result == Z_BUF_ERROR || bb[0] == 0){\n      z.msg = \"incomplete dynamic bit lengths tree\";\n      result = Z_DATA_ERROR;\n    }\n    return result;\n  }\n\n  int inflate_trees_dynamic(int nl,   // number of literal/length codes\n                            int nd,   // number of distance codes\n                            int[] c,  // that many (total) code lengths\n                            int[] bl, // literal desired/actual bit depth\n                            int[] bd, // distance desired/actual bit depth \n                            int[] tl, // literal/length tree result\n                            int[] td, // distance tree result\n                            int[] hp, // space for trees\n                            ZStream z // for messages\n                            ){\n    int result;\n\n    // build literal/length tree\n    initWorkArea(288);\n    hn[0]=0;\n    result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);\n    if (result != Z_OK || bl[0] == 0){\n      if(result == Z_DATA_ERROR){\n        z.msg = \"oversubscribed literal/length tree\";\n      }\n      else if (result != Z_MEM_ERROR){\n        z.msg = \"incomplete literal/length tree\";\n        result = Z_DATA_ERROR;\n      }\n      return result;\n    }\n\n    // build distance tree\n    initWorkArea(288);\n    result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);\n\n    if (result != Z_OK || (bd[0] == 0 && nl > 257)){\n      if (result == Z_DATA_ERROR){\n        z.msg = \"oversubscribed distance tree\";\n      }\n      else if (result == Z_BUF_ERROR) {\n        z.msg = \"incomplete distance tree\";\n        result = Z_DATA_ERROR;\n      }\n      else if (result != Z_MEM_ERROR){\n        z.msg = \"empty distance tree with lengths\";\n        result = Z_DATA_ERROR;\n      }\n      return result;\n    }\n\n    return Z_OK;\n  }\n\n  static int inflate_trees_fixed(int[] bl,  //literal desired/actual bit depth\n                                 int[] bd,  //distance desired/actual bit depth\n                                 int[][] tl,//literal/length tree result\n                                 int[][] td,//distance tree result \n                                 ZStream z  //for memory allocation\n\t\t\t\t ){\n    bl[0]=fixed_bl;\n    bd[0]=fixed_bd;\n    tl[0]=fixed_tl;\n    td[0]=fixed_td;\n    return Z_OK;\n  }\n\n  private void initWorkArea(int vsize){\n    if(hn==null){\n      hn=new int[1];\n      v=new int[vsize];\n      c=new int[BMAX+1];\n      r=new int[3];\n      u=new int[BMAX];\n      x=new int[BMAX+1];\n    }\n    if(v.length<vsize){ v=new int[vsize]; }\n    for(int i=0; i<vsize; i++){v[i]=0;}\n    for(int i=0; i<BMAX+1; i++){c[i]=0;}\n    for(int i=0; i<3; i++){r[i]=0;}\n    System.arraycopy(c, 0, u, 0, BMAX);\n    System.arraycopy(c, 0, x, 0, BMAX+1);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/Inflate.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal class Inflate{\n  \n  static final private int MAX_WBITS=15; // 32K LZ77 window\n\n  // preset dictionary flag in zlib header\n  static final private int PRESET_DICT=0x20;\n\n  static final int Z_NO_FLUSH=0;\n  static final int Z_PARTIAL_FLUSH=1;\n  static final int Z_SYNC_FLUSH=2;\n  static final int Z_FULL_FLUSH=3;\n  static final int Z_FINISH=4;\n\n  static final private int Z_DEFLATED=8;\n\n  static final private int Z_OK=0;\n  static final private int Z_STREAM_END=1;\n  static final private int Z_NEED_DICT=2;\n  static final private int Z_ERRNO=-1;\n  static final private int Z_STREAM_ERROR=-2;\n  static final private int Z_DATA_ERROR=-3;\n  static final private int Z_MEM_ERROR=-4;\n  static final private int Z_BUF_ERROR=-5;\n  static final private int Z_VERSION_ERROR=-6;\n\n  static final private int METHOD=0;   // waiting for method byte\n  static final private int FLAG=1;     // waiting for flag byte\n  static final private int DICT4=2;    // four dictionary check bytes to go\n  static final private int DICT3=3;    // three dictionary check bytes to go\n  static final private int DICT2=4;    // two dictionary check bytes to go\n  static final private int DICT1=5;    // one dictionary check byte to go\n  static final private int DICT0=6;    // waiting for inflateSetDictionary\n  static final private int BLOCKS=7;   // decompressing blocks\n  static final private int CHECK4=8;   // four check bytes to go\n  static final private int CHECK3=9;   // three check bytes to go\n  static final private int CHECK2=10;  // two check bytes to go\n  static final private int CHECK1=11;  // one check byte to go\n  static final private int DONE=12;    // finished check, done\n  static final private int BAD=13;     // got an error--stay here\n\n  static final private int HEAD=14;\n  static final private int LENGTH=15;\n  static final private int TIME=16;\n  static final private int OS=17;\n  static final private int EXLEN=18;\n  static final private int EXTRA=19;\n  static final private int NAME=20;\n  static final private int COMMENT=21;\n  static final private int HCRC=22;\n  static final private int FLAGS=23;\n\n  static final int INFLATE_ANY=0x40000000;\n\n  int mode;                            // current inflate mode\n\n  // mode dependent information\n  int method;        // if FLAGS, method byte\n\n  // if CHECK, check values to compare\n  long was = -1;           // computed check value\n  long need;               // stream check value\n\n  // if BAD, inflateSync's marker bytes count\n  int marker;\n\n  // mode independent information\n  int  wrap;          // flag for no wrapper\n                      // 0: no wrapper\n                      // 1: zlib header\n                      // 2: gzip header\n                      // 4: auto detection\n\n  int wbits;            // log2(window size)  (8..15, defaults to 15)\n\n  InfBlocks blocks;     // current inflate_blocks state\n\n  private final ZStream z;\n\n  private int flags; \n\n  private int need_bytes = -1;\n  private byte[] crcbuf=new byte[4];\n\n  GZIPHeader gheader = null;\n\n  int inflateReset(){\n    if(z == null) return Z_STREAM_ERROR;\n    \n    z.total_in = z.total_out = 0;\n    z.msg = null;\n    this.mode = HEAD;\n    this.need_bytes = -1;\n    this.blocks.reset();\n    return Z_OK;\n  }\n\n  int inflateEnd(){\n    if(blocks != null){\n      blocks.free();\n    }\n    return Z_OK;\n  }\n\n  Inflate(ZStream z){\n    this.z=z;\n  }\n\n  int inflateInit(int w){\n    z.msg = null;\n    blocks = null;\n\n    // handle undocumented wrap option (no zlib header or check)\n    wrap = 0;\n    if(w < 0){\n      w = - w;\n    }\n    else if((w&INFLATE_ANY) != 0){\n      wrap = 4;\n      w &= ~INFLATE_ANY;\n      if(w < 48)\n        w &= 15;\n    }\n    else if((w & ~31) != 0) { // for example, DEF_WBITS + 32\n      wrap = 4;               // zlib and gzip wrapped data should be accepted.\n      w &= 15;\n    }\n    else {\n      wrap = (w >> 4) + 1;\n      if(w < 48)\n        w &= 15;\n    }\n\n    if(w<8 ||w>15){\n      inflateEnd();\n      return Z_STREAM_ERROR;\n    }\n    if(blocks != null && wbits != w){\n      blocks.free();\n      blocks=null;\n    }\n\n    // set window size\n    wbits=w;\n\n    this.blocks=new InfBlocks(z, 1<<w);\n\n    // reset state\n    inflateReset();\n\n    return Z_OK;\n  }\n\n  int inflate(int f){\n    int hold = 0;\n\n    int r;\n    int b;\n\n    if(z == null || z.next_in == null){\n      if(f == Z_FINISH && this.mode==HEAD)\n        return Z_OK; \n      return Z_STREAM_ERROR;\n    }\n\n    f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;\n    r = Z_BUF_ERROR;\n    while (true){\n\n      switch (this.mode){\n      case HEAD:\n        if(wrap==0){\n\t  this.mode = BLOCKS;\n          break;\n        } \n\n        try { r=readBytes(2, r, f); }\n        catch(Return e){ return e.r; }\n\n        if((wrap == 4 || (wrap&2)!=0) &&\n           this.need == 0x8b1fL) {   // gzip header\n          if(wrap == 4){\n            wrap = 2;\n          }\n\t  z.adler=new CRC32();\n          checksum(2, this.need);\n\n          if(gheader==null) \n            gheader=new GZIPHeader();\n\n          this.mode = FLAGS;\n          break;\n        }\n\n        if((wrap&2) != 0){\n          this.mode = BAD;\n          z.msg = \"incorrect header check\";\n          break;\n        }\n\n        flags = 0;\n\n        this.method = ((int)this.need)&0xff;\n        b=((int)(this.need>>8))&0xff;\n\n        if(((wrap&1)==0 ||  // check if zlib header allowed\n            (((this.method << 8)+b) % 31)!=0) &&\n           (this.method&0xf)!=Z_DEFLATED){\n          if(wrap == 4){\n            z.next_in_index -= 2;\n            z.avail_in += 2;\n            z.total_in -= 2;\n            wrap = 0;\n            this.mode = BLOCKS;\n            break;\n          }  \n          this.mode = BAD;\n          z.msg = \"incorrect header check\";\n          // since zlib 1.2, it is allowted to inflateSync for this case.\n          /*\n          this.marker = 5;       // can't try inflateSync\n          */\n          break;\n        }\n\n        if((this.method&0xf)!=Z_DEFLATED){\n          this.mode = BAD;\n          z.msg=\"unknown compression method\";\n          // since zlib 1.2, it is allowted to inflateSync for this case.\n\t  /*\n          this.marker = 5;       // can't try inflateSync\n\t  */\n          break;\n        }\n  \n        if(wrap == 4){\n          wrap = 1;\n        }  \n\n        if((this.method>>4)+8>this.wbits){\n          this.mode = BAD;\n          z.msg=\"invalid window size\";\n          // since zlib 1.2, it is allowted to inflateSync for this case.\n\t  /*\n          this.marker = 5;       // can't try inflateSync\n\t  */\n          break;\n        }\n\n        z.adler=new Adler32();\n\n        if((b&PRESET_DICT)==0){\n          this.mode = BLOCKS;\n          break;\n        }\n        this.mode = DICT4;\n      case DICT4:\n\n        if(z.avail_in==0)return r;r=f;\n\n        z.avail_in--; z.total_in++;\n        this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;\n        this.mode=DICT3;\n      case DICT3:\n\n        if(z.avail_in==0)return r;r=f;\n\n        z.avail_in--; z.total_in++;\n        this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;\n        this.mode=DICT2;\n      case DICT2:\n\n        if(z.avail_in==0)return r;r=f;\n\n        z.avail_in--; z.total_in++;\n        this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;\n        this.mode=DICT1;\n      case DICT1:\n\n        if(z.avail_in==0)return r;r=f;\n\n        z.avail_in--; z.total_in++;\n        this.need += (z.next_in[z.next_in_index++]&0xffL);\n        z.adler.reset(this.need);\n        this.mode = DICT0;\n        return Z_NEED_DICT;\n      case DICT0:\n        this.mode = BAD;\n        z.msg = \"need dictionary\";\n        this.marker = 0;       // can try inflateSync\n        return Z_STREAM_ERROR;\n      case BLOCKS:\n        r = this.blocks.proc(r);\n        if(r == Z_DATA_ERROR){\n          this.mode = BAD;\n          this.marker = 0;     // can try inflateSync\n          break;\n        }\n        if(r == Z_OK){\n          r = f;\n        }\n        if(r != Z_STREAM_END){\n          return r;\n        }\n        r = f;\n        this.was=z.adler.getValue();\n        this.blocks.reset();\n        if(this.wrap==0){\n          this.mode=DONE;\n          break;\n        }\n        this.mode=CHECK4;\n      case CHECK4:\n\n        if(z.avail_in==0)return r;r=f;\n\n        z.avail_in--; z.total_in++;\n        this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;\n        this.mode=CHECK3;\n      case CHECK3:\n\n        if(z.avail_in==0)return r;r=f;\n\n        z.avail_in--; z.total_in++;\n        this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;\n        this.mode = CHECK2;\n      case CHECK2:\n\n        if(z.avail_in==0)return r;r=f;\n\n        z.avail_in--; z.total_in++;\n        this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;\n        this.mode = CHECK1;\n      case CHECK1:\n\n        if(z.avail_in==0)return r;r=f;\n\n        z.avail_in--; z.total_in++;\n        this.need+=(z.next_in[z.next_in_index++]&0xffL);\n\n        if(flags!=0){  // gzip\n          this.need = ((this.need&0xff000000)>>24 | \n                          (this.need&0x00ff0000)>>8 | \n                          (this.need&0x0000ff00)<<8 | \n                          (this.need&0x0000ffff)<<24)&0xffffffffL;\n        }\n\n        if(((int)(this.was)) != ((int)(this.need))){\n          z.msg = \"incorrect data check\";\n          // chack is delayed\n          /*\n          this.mode = BAD;\n          this.marker = 5;       // can't try inflateSync\n          break;\n\t  */\n        }\n        else if(flags!=0 && gheader!=null){\n          gheader.crc = this.need; \n        }\n\n        this.mode = LENGTH;\n      case LENGTH:\n        if (wrap!=0 && flags!=0) {\n\n          try { r=readBytes(4, r, f); }\n          catch(Return e){ return e.r; }\n\n          if(z.msg!=null && z.msg.equals(\"incorrect data check\")){\n            this.mode = BAD;\n            this.marker = 5;       // can't try inflateSync\n            break;\n          }\n\n          if (this.need != (z.total_out & 0xffffffffL)) {\n            z.msg = \"incorrect length check\";\n            this.mode = BAD;\n            break;\n          }\n          z.msg = null;\n        }\n        else {\n          if(z.msg!=null && z.msg.equals(\"incorrect data check\")){\n            this.mode = BAD;\n            this.marker = 5;       // can't try inflateSync\n            break;\n          }\n        }\n\n        this.mode = DONE;\n      case DONE:\n        return Z_STREAM_END;\n      case BAD:\n        return Z_DATA_ERROR;\n\n      case FLAGS:\n\n        try { r=readBytes(2, r, f); }\n        catch(Return e){ return e.r; }\n\n        flags = ((int)this.need)&0xffff;\n\n        if ((flags & 0xff) != Z_DEFLATED) {\n          z.msg = \"unknown compression method\";\n          this.mode = BAD; \n          break;\n        }\n        if ((flags & 0xe000)!=0) {\n          z.msg = \"unknown header flags set\";\n          this.mode = BAD; \n          break;\n        }\n\n        if ((flags & 0x0200)!=0){\n          checksum(2, this.need);\n        } \n\n        this.mode = TIME;\n\n      case TIME:\n        try { r=readBytes(4, r, f); }\n        catch(Return e){ return e.r; }\n        if(gheader!=null)\n          gheader.time = this.need;\n        if ((flags & 0x0200)!=0){\n          checksum(4, this.need);\n        }\n        this.mode = OS;\n      case OS:\n        try { r=readBytes(2, r, f); }\n        catch(Return e){ return e.r; }\n        if(gheader!=null){\n          gheader.xflags = ((int)this.need)&0xff;\n          gheader.os = (((int)this.need)>>8)&0xff;\n        }\n        if ((flags & 0x0200)!=0){\n          checksum(2, this.need);\n        }\n        this.mode = EXLEN;\n      case EXLEN:\n        if ((flags & 0x0400)!=0) {\n          try { r=readBytes(2, r, f); }\n          catch(Return e){ return e.r; }\n          if(gheader!=null){\n            gheader.extra = new byte[((int)this.need)&0xffff];\n          }\n          if ((flags & 0x0200)!=0){\n            checksum(2, this.need);\n          }\n        }\n        else if(gheader!=null){\n          gheader.extra=null;\n        }\n        this.mode = EXTRA;\n\n      case EXTRA:\n        if ((flags & 0x0400)!=0) {\n          try { \n            r=readBytes(r, f);\n            if(gheader!=null){\n              byte[] foo = tmp_string.toByteArray();\n              tmp_string=null;\n              if(foo.length == gheader.extra.length){\n                System.arraycopy(foo, 0, gheader.extra, 0, foo.length);\n\t      }\n              else{\n                z.msg = \"bad extra field length\";\n                this.mode = BAD; \n                break;\n\t      }\n            }\n          }\n          catch(Return e){ return e.r; }\n        }\n        else if(gheader!=null){\n          gheader.extra=null;\n\t}\n\tthis.mode = NAME;\n      case NAME:\n\tif ((flags & 0x0800)!=0) {\n          try { \n            r=readString(r, f);\n            if(gheader!=null){\n              gheader.name=tmp_string.toByteArray();\n            }\n            tmp_string=null;\n          }\n          catch(Return e){ return e.r; }\n        }\n        else if(gheader!=null){\n          gheader.name=null;\n\t}\n        this.mode = COMMENT;\n      case COMMENT:\n        if ((flags & 0x1000)!=0) {\n          try { \n            r=readString(r, f);\n            if(gheader!=null){\n              gheader.comment=tmp_string.toByteArray();\n            }\n            tmp_string=null;\n          }\n          catch(Return e){ return e.r; }\n        }\n        else if(gheader!=null){\n          gheader.comment=null;\n\t}\n        this.mode = HCRC;\n      case HCRC:\n\tif ((flags & 0x0200)!=0) {\n          try { r=readBytes(2, r, f); }\n          catch(Return e){ return e.r; }\n          if(gheader!=null){\n            gheader.hcrc=(int)(this.need&0xffff);\n          }\n          if(this.need != (z.adler.getValue()&0xffffL)){\n            this.mode = BAD;\n            z.msg = \"header crc mismatch\";\n            this.marker = 5;       // can't try inflateSync\n            break;\n          }\n        }\n        z.adler = new CRC32();\n\n        this.mode = BLOCKS;\n        break;\n      default:\n        return Z_STREAM_ERROR;\n      }\n    }\n  }\n\n  int inflateSetDictionary(byte[] dictionary, int dictLength){\n    if(z==null || (this.mode != DICT0 && this.wrap != 0)){\n      return Z_STREAM_ERROR;\n    }\n\n    int index=0;\n    int length = dictLength;\n\n    if(this.mode==DICT0){\n      long adler_need=z.adler.getValue();\n      z.adler.reset();\n      z.adler.update(dictionary, 0, dictLength);\n      if(z.adler.getValue()!=adler_need){\n        return Z_DATA_ERROR;\n      }\n    }\n\n    z.adler.reset();\n\n    if(length >= (1<<this.wbits)){\n      length = (1<<this.wbits)-1;\n      index=dictLength - length;\n    }\n    this.blocks.set_dictionary(dictionary, index, length);\n    this.mode = BLOCKS;\n    return Z_OK;\n  }\n\n  static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff};\n\n  int inflateSync(){\n    int n;       // number of bytes to look at\n    int p;       // pointer to bytes\n    int m;       // number of marker bytes found in a row\n    long r, w;   // temporaries to save total_in and total_out\n\n    // set up\n    if(z == null)\n      return Z_STREAM_ERROR;\n    if(this.mode != BAD){\n      this.mode = BAD;\n      this.marker = 0;\n    }\n    if((n=z.avail_in)==0)\n      return Z_BUF_ERROR;\n\n    p=z.next_in_index;\n    m=this.marker;\n    // search\n    while (n!=0 && m < 4){\n      if(z.next_in[p] == mark[m]){\n        m++;\n      }\n      else if(z.next_in[p]!=0){\n        m = 0;\n      }\n      else{\n        m = 4 - m;\n      }\n      p++; n--;\n    }\n\n    // restore\n    z.total_in += p-z.next_in_index;\n    z.next_in_index = p;\n    z.avail_in = n;\n    this.marker = m;\n\n    // return no joy or set up to restart on a new block\n    if(m != 4){\n      return Z_DATA_ERROR;\n    }\n    r=z.total_in;  w=z.total_out;\n    inflateReset();\n    z.total_in=r;  z.total_out = w;\n    this.mode = BLOCKS;\n\n    return Z_OK;\n  }\n\n  // Returns true if inflate is currently at the end of a block generated\n  // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP\n  // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH\n  // but removes the length bytes of the resulting empty stored block. When\n  // decompressing, PPP checks that at the end of input packet, inflate is\n  // waiting for these length bytes.\n  int inflateSyncPoint(){\n    if(z == null || this.blocks == null)\n      return Z_STREAM_ERROR;\n    return this.blocks.sync_point();\n  }\n\n  private int readBytes(int n, int r, int f) throws Return{\n    if(need_bytes == -1){\n      need_bytes=n;\n      this.need=0;\n    }\n    while(need_bytes>0){\n      if(z.avail_in==0){ throw new Return(r); }; r=f;\n      z.avail_in--; z.total_in++;\n      this.need = this.need | \n\t((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8));\n      need_bytes--;\n    }\n    if(n==2){\n      this.need&=0xffffL;\n    }\n    else if(n==4) {\n      this.need&=0xffffffffL;\n    }\n    need_bytes=-1;\n    return r;\n  }\n  class Return extends Exception{\n    int r;\n    Return(int r){this.r=r; }\n  }\n\n  private java.io.ByteArrayOutputStream tmp_string = null;\n  private int readString(int r, int f) throws Return{\n    if(tmp_string == null){\n      tmp_string=new java.io.ByteArrayOutputStream();\n    }\n    int b=0; \n    do {\n      if(z.avail_in==0){ throw new Return(r); }; r=f;\n      z.avail_in--; z.total_in++;\n      b = z.next_in[z.next_in_index];\n      if(b!=0) tmp_string.write(z.next_in, z.next_in_index, 1);\n      z.adler.update(z.next_in, z.next_in_index, 1);\n      z.next_in_index++;\n    }while(b!=0);\n    return r;\n  }\n\n  private int readBytes(int r, int f) throws Return{\n    if(tmp_string == null){\n      tmp_string=new java.io.ByteArrayOutputStream();\n    }\n    int b=0; \n    while(this.need>0){\n      if(z.avail_in==0){ throw new Return(r); }; r=f;\n      z.avail_in--; z.total_in++;\n      b = z.next_in[z.next_in_index];\n      tmp_string.write(z.next_in, z.next_in_index, 1);\n      z.adler.update(z.next_in, z.next_in_index, 1);\n      z.next_in_index++;\n      this.need--;\n    }\n    return r;\n  }\n\n  private void checksum(int n, long v){\n    for(int i=0; i<n; i++){\n      crcbuf[i]=(byte)(v&0xff);\n      v>>=8;\n    }\n    z.adler.update(crcbuf, 0, n);\n  }\n\n  public GZIPHeader getGZIPHeader(){\n    return gheader;\n  }\n\n  boolean inParsingHeader(){\n    switch(mode){\n      case HEAD:\n      case DICT4:\n      case DICT3:\n      case DICT2:\n      case DICT1:\n      case FLAGS:\n      case TIME:\n      case OS:\n      case EXLEN:\n      case EXTRA:\n      case NAME:\n      case COMMENT:\n      case HCRC:\n\treturn true;\n      default:\n\treturn false;\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/Inflater.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal public class Inflater extends ZStream{\n\n  static final private int MAX_WBITS=15;        // 32K LZ77 window\n  static final private int DEF_WBITS=MAX_WBITS;\n\n  static final private int Z_NO_FLUSH=0;\n  static final private int Z_PARTIAL_FLUSH=1;\n  static final private int Z_SYNC_FLUSH=2;\n  static final private int Z_FULL_FLUSH=3;\n  static final private int Z_FINISH=4;\n\n  static final private int MAX_MEM_LEVEL=9;\n\n  static final private int Z_OK=0;\n  static final private int Z_STREAM_END=1;\n  static final private int Z_NEED_DICT=2;\n  static final private int Z_ERRNO=-1;\n  static final private int Z_STREAM_ERROR=-2;\n  static final private int Z_DATA_ERROR=-3;\n  static final private int Z_MEM_ERROR=-4;\n  static final private int Z_BUF_ERROR=-5;\n  static final private int Z_VERSION_ERROR=-6;\n\n  public Inflater() {\n    super();\n    init();\n  }\n\n  public Inflater(JZlib.WrapperType wrapperType) throws GZIPException {\n    this(DEF_WBITS, wrapperType);\n  }\n\n  public Inflater(int w, JZlib.WrapperType wrapperType) throws GZIPException {\n    super();\n    int ret = init(w, wrapperType);\n    if(ret!=Z_OK)\n      throw new GZIPException(ret+\": \"+msg);\n  }\n\n  public Inflater(int w) throws GZIPException {\n    this(w, false);\n  }\n\n  public Inflater(boolean nowrap) throws GZIPException {\n    this(DEF_WBITS, nowrap);\n  }\n\n  public Inflater(int w, boolean nowrap) throws GZIPException {\n    super();\n    int ret = init(w, nowrap);\n    if(ret!=Z_OK)\n      throw new GZIPException(ret+\": \"+msg);\n  }\n\n  private boolean finished = false;\n\n  public int init(){\n    return init(DEF_WBITS);\n  }\n\n  public int init(JZlib.WrapperType wrapperType){\n    return init(DEF_WBITS, wrapperType);\n  }\n\n  public int init(int w, JZlib.WrapperType wrapperType) {\n    boolean nowrap = false;\n    if(wrapperType == JZlib.W_NONE){\n      nowrap = true;\n    }\n    else if(wrapperType == JZlib.W_GZIP) {\n      w += 16;\n    }\n    else if(wrapperType == JZlib.W_ANY) {\n      w |= Inflate.INFLATE_ANY;\n    }\n    else if(wrapperType == JZlib.W_ZLIB) {\n    }\n    return init(w, nowrap);\n  }\n\n  public int init(boolean nowrap){\n    return init(DEF_WBITS, nowrap);\n  }\n\n  public int init(int w){\n    return init(w, false);\n  }\n\n  public int init(int w, boolean nowrap){\n    finished = false;\n    istate=new Inflate(this);\n    return istate.inflateInit(nowrap?-w:w);\n  }\n\n  public int inflate(int f){\n    if(istate==null) return Z_STREAM_ERROR;\n    int ret = istate.inflate(f);\n    if(ret == Z_STREAM_END) \n      finished = true;\n    return ret;\n  }\n\n  public int end(){\n    finished = true;\n    if(istate==null) return Z_STREAM_ERROR;\n    int ret=istate.inflateEnd();\n//    istate = null;\n    return ret;\n  }\n\n  public int sync(){\n    if(istate == null)\n      return Z_STREAM_ERROR;\n    return istate.inflateSync();\n  }\n\n  public int syncPoint(){\n    if(istate == null)\n      return Z_STREAM_ERROR;\n    return istate.inflateSyncPoint();\n  }\n\n  public int setDictionary(byte[] dictionary, int dictLength){\n    if(istate == null)\n      return Z_STREAM_ERROR;\n    return istate.inflateSetDictionary(dictionary, dictLength);\n  }\n\n  public boolean finished(){\n    return istate.mode==12 /*DONE*/;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/InflaterInputStream.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\npackage com.jcraft.jzlib;\nimport java.io.*;\n\npublic class InflaterInputStream extends FilterInputStream {\n  protected final Inflater inflater;\n  protected byte[] buf;\n\n  private boolean closed = false;\n\n  private boolean eof = false;\n\n  private boolean close_in = true;\n\n  protected static final int DEFAULT_BUFSIZE = 512;\n\n  public InflaterInputStream(InputStream in) throws IOException {\n    this(in, false);\n  }\n\n  public InflaterInputStream(InputStream in, boolean nowrap) throws IOException {\n    this(in, new Inflater(nowrap));\n    myinflater = true;\n  }\n\n  public InflaterInputStream(InputStream in, Inflater inflater) throws IOException {\n    this(in, inflater, DEFAULT_BUFSIZE);\n  }\n\n  public InflaterInputStream(InputStream in,\n                             Inflater inflater, int size) throws IOException {\n    this(in, inflater, size, true);\n  }\n\n  public InflaterInputStream(InputStream in,\n                             Inflater inflater,\n                             int size, boolean close_in) throws IOException {\n    super(in);\n    if (in == null || inflater == null) {\n      throw new NullPointerException();\n    }\n    else if (size <= 0) {\n      throw new IllegalArgumentException(\"buffer size must be greater than 0\");\n    }\n    this.inflater = inflater;\n    buf = new byte[size];\n    this.close_in = close_in;\n  }\n\n  protected boolean myinflater = false;\n\n  private byte[] byte1 = new byte[1];\n\n  public int read() throws IOException {\n    if (closed) { throw new IOException(\"Stream closed\"); }\n    return read(byte1, 0, 1) == -1 ? -1 : byte1[0] & 0xff;\n  }\n\n  public int read(byte[] b, int off, int len) throws IOException {\n    if (closed) { throw new IOException(\"Stream closed\"); }\n    if (b == null) {\n      throw new NullPointerException();\n    }\n    else if (off < 0 || len < 0 || len > b.length - off) {\n      throw new IndexOutOfBoundsException();\n    }\n    else if (len == 0) {\n      return 0;\n    }\n    else if (eof) {\n      return -1;\n    }\n\n    int n = 0;\n    inflater.setOutput(b, off, len);\n    while(!eof) {\n      if(inflater.avail_in==0)\n        fill();\n      int err = inflater.inflate(JZlib.Z_NO_FLUSH);\n      n += inflater.next_out_index - off;\n      off = inflater.next_out_index;\n      switch(err) {\n        case JZlib.Z_DATA_ERROR:\n          throw new IOException(inflater.msg);\n        case JZlib.Z_STREAM_END:\n        case JZlib.Z_NEED_DICT:\n          eof = true;\n          if(err == JZlib.Z_NEED_DICT)\n            return -1;\n          break;\n        default:\n      } \n      if(inflater.avail_out==0)\n        break;\n    }\n    return n;\n  }\n\n  public int available() throws IOException {\n    if (closed) { throw new IOException(\"Stream closed\"); }\n    if (eof) {\n      return 0;\n    }\n    else {\n      return 1;\n    }\n  }\n\n  private byte[] b = new byte[512];\n\n  public long skip(long n) throws IOException {\n    if (n < 0) {\n      throw new IllegalArgumentException(\"negative skip length\");\n    }\n\n    if (closed) { throw new IOException(\"Stream closed\"); }\n\n    int max = (int)Math.min(n, Integer.MAX_VALUE);\n    int total = 0;\n    while (total < max) {\n      int len = max - total;\n      if (len > b.length) {\n        len = b.length;\n      }\n      len = read(b, 0, len);\n      if (len == -1) {\n        eof = true;\n        break;\n      }\n      total += len;\n    }\n    return total;\n  }\n\n  public void close() throws IOException {\n    if (!closed) {\n      if (myinflater)\n        inflater.end();\n      if(close_in)\n        in.close();\n      closed = true;\n    }\n  }\n\n  protected void fill() throws IOException {\n    if (closed) { throw new IOException(\"Stream closed\"); }\n    int len = in.read(buf, 0, buf.length);\n    if (len == -1) {\n      if(inflater.istate.wrap == 0 &&\n         !inflater.finished()){\n        buf[0]=0;\n        len=1;\n      }\n      else if(inflater.istate.was != -1){  // in reading trailer\n        throw new IOException(\"footer is not found\");\n      }\n      else{\n        throw new EOFException(\"Unexpected end of ZLIB input stream\");\n      }\n    }\n    inflater.setInput(buf, 0, len, true);\n  }\n\n  public boolean markSupported() {\n    return false;\n  }\n\n  public synchronized void mark(int readlimit) {\n  }\n\n  public synchronized void reset() throws IOException {\n    throw new IOException(\"mark/reset not supported\");\n  }\n\n  public long getTotalIn() {\n    return inflater.getTotalIn();\n  }\n\n  public long getTotalOut() {\n    return inflater.getTotalOut();\n  }\n\n  public byte[] getAvailIn() {\n    if(inflater.avail_in<=0)\n      return null;\n    byte[] tmp = new byte[inflater.avail_in];\n    System.arraycopy(inflater.next_in, inflater.next_in_index,\n                     tmp, 0, inflater.avail_in);\n    return tmp;\n  }\n\n  public void readHeader() throws IOException {\n\n    byte[] empty = \"\".getBytes();\n    inflater.setInput(empty, 0, 0, false);\n    inflater.setOutput(empty, 0, 0);\n\n    int err = inflater.inflate(JZlib.Z_NO_FLUSH);\n    if(!inflater.istate.inParsingHeader()){\n      return;\n    }\n\n    byte[] b1 = new byte[1];\n    do{\n      int i = in.read(b1);\n      if(i<=0)\n        throw new IOException(\"no input\");\n      inflater.setInput(b1);\n      err = inflater.inflate(JZlib.Z_NO_FLUSH);\n      if(err!=0/*Z_OK*/)\n        throw new IOException(inflater.msg);\n    }\n    while(inflater.istate.inParsingHeader());\n  }\n\n  public Inflater getInflater(){\n    return inflater;\n  }\n}"
  },
  {
    "path": "java/com/jcraft/jzlib/JZlib.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal public class JZlib{\n  private static final String version=\"1.1.0\";\n  public static String version(){return version;}\n\n  static final public int MAX_WBITS=15;        // 32K LZ77 window\n  static final public int DEF_WBITS=MAX_WBITS;\n\n  public enum WrapperType {\n    NONE, ZLIB, GZIP, ANY\n  }\n\n  public static final WrapperType W_NONE = WrapperType.NONE;\n  public static final WrapperType W_ZLIB = WrapperType.ZLIB;\n  public static final WrapperType W_GZIP = WrapperType.GZIP;\n  public static final WrapperType W_ANY = WrapperType.ANY;\n\n  // compression levels\n  static final public int Z_NO_COMPRESSION=0;\n  static final public int Z_BEST_SPEED=1;\n  static final public int Z_BEST_COMPRESSION=9;\n  static final public int Z_DEFAULT_COMPRESSION=(-1);\n\n  // compression strategy\n  static final public int Z_FILTERED=1;\n  static final public int Z_HUFFMAN_ONLY=2;\n  static final public int Z_DEFAULT_STRATEGY=0;\n\n  static final public int Z_NO_FLUSH=0;\n  static final public int Z_PARTIAL_FLUSH=1;\n  static final public int Z_SYNC_FLUSH=2;\n  static final public int Z_FULL_FLUSH=3;\n  static final public int Z_FINISH=4;\n\n  static final public int Z_OK=0;\n  static final public int Z_STREAM_END=1;\n  static final public int Z_NEED_DICT=2;\n  static final public int Z_ERRNO=-1;\n  static final public int Z_STREAM_ERROR=-2;\n  static final public int Z_DATA_ERROR=-3;\n  static final public int Z_MEM_ERROR=-4;\n  static final public int Z_BUF_ERROR=-5;\n  static final public int Z_VERSION_ERROR=-6;\n\n  // The three kinds of block type\n  static final public byte Z_BINARY = 0;\n  static final public byte Z_ASCII = 1;\n  static final public byte Z_UNKNOWN = 2;\n\n  public static long adler32_combine(long adler1, long adler2, long len2){\n    return Adler32.combine(adler1, adler2, len2);\n  }\n\n  public static long crc32_combine(long crc1, long crc2, long len2){\n    return CRC32.combine(crc1, crc2, len2);\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/LICENSE.txt",
    "content": "JZlib 0.0.* were released under the GNU LGPL license.  Later, we have switched \nover to a BSD-style license. \n\n------------------------------------------------------------------------------\nCopyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "java/com/jcraft/jzlib/README",
    "content": "\n                                     JZlib\n\n                               zlib in pure Java(TM)\n                                by ymnk@jcraft.com, JCraft,Inc.\n\n                          http://www.jcraft.com/jzlib/\n\nLast modified: Mon Sep 19 15:28:43 UTC 2011\n\nDescription\n===========\nJZlib is a re-implementation of zlib in pure Java.\nThe first and final aim for hacking this stuff is\nto add the packet compression support to pure Java SSH systems.\n\n\nDocumentation\n=============\n* README files all over the source tree have info related to the stuff\n  in the directories. \n* ChangeLog: what changed from the previous version?\n* LICENSE.txt\n\n\nDirectories & Files in the Source Tree\n======================================\n* src/main/java has source trees of JZlib.\n* example/ has some samples, which demonstrate the usages.\n* misc/ has some stuffs. At present, this directory includes\n  a patch file for MindTerm v.1.2.1, which adds the packet compression\n  functionality.\n\n\nFeatures\n========\n* Needless to say, JZlib can inflate data, which is deflated by zlib and\n  JZlib can generate deflated data, which is acceptable and inflated by zlib.\n* JZlib supports all compression level and all flushing mode in zlib. \n* JZlib does not support gzip file handling supports.\n* The performance has not been estimated yet,  but it will be not so bad\n  in deflating/inflating data stream on the low bandwidth network.\n* JZlib is under BSD style license.\n* Any invention has not been done in developing JZlib.\n  So, if zlib is patent free, JZlib is also not covered by any patents.\n\n\nWhy JZlib?\n==========\nJava Platform API provides packages 'java.util.zip.*' for\naccessing to zlib, but that support is very limited \nif you need to use the essence of zlib. For example,\nwe needed to full access to zlib to add the packet compression\nsupport to pure Java SSH system, but they are useless for our requirements.\nThe Internet draft, SSH Transport Layer Protocol, says in the section '4.2 Compression' as follows,\n\n  The following compression methods are currently defined:\n    none  REQUIRED  no compression\n    zlib  OPTIONAL  GNU ZLIB (LZ77) compression\n  The \"zlib\" compression is described in [RFC-1950] and in [RFC-1951]. The\n  compression context is initialized after each key exchange, and is\n  passed from one packet to the next with only a partial flush being\n  performed at the end of each packet. A partial flush means that all data\n  will be output, but the next packet will continue using compression\n  tables from the end of the previous packet.\n\nTo implement this functionality, the Z_PARTIAL_FLUSH mode of zlib must be\nused, however JDK does not permit us to do so. It seems that this problem has\nbeen well known and some people have already reported to \nJavaSoft's BugParade(for example, BugId:4255743), \nbut any positive response has not been returned from JavaSoft, \nso this problem will not be solved forever. \nThis is our motivation to hack JZlib.\n\n\nBuilding Jar File\n=================\nUse 'sbt'(https://github.com/harrah/xsbt/wiki),\n  % sbt package\nor\n  % mvn package\nor\n  % cd src/main/java\n  % javac -target 1.5 com/jcraft/jzlib/*.java\n  % jar -cvf jzlib.jar com/jcraft/jzlib/*.class\n\n\nA unofficial patch for MindTerm v.1.2.1\n=======================================\nA unofficial patch file for MindTerm v.1.2.1 has included in 'misc' directory.\nIt adds the packet compression support to MindTerm. \nPlease refer to 'misc/README' file.\n\n\nCopyrights & Disclaimers\n========================\nJZlib is copyrighted by ymnk, JCraft,Inc. and is licensed through BSD\nstyle license.  Read the LICENSE.txt file for the complete license.\n\n\nCredits\n=======\nJZlib has been developed by ymnk@jcraft.com,\nbut he has just re-implemented zlib in pure Java.\nSo, all credit should go to authors Jean-loup Gailly and Mark Adler\nand contributors of zlib.  Here is the copyright notice of zlib version 1.1.3,\n\n  |Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler\n  |\n  |This software is provided 'as-is', without any express or implied\n  |warranty.  In no event will the authors be held liable for any damages\n  |arising from the use of this software.\n  |\n  |Permission is granted to anyone to use this software for any purpose,\n  |including commercial applications, and to alter it and redistribute it\n  |freely, subject to the following restrictions:\n  |\n  |1. The origin of this software must not be misrepresented; you must not\n  |   claim that you wrote the original software. If you use this software\n  |   in a product, an acknowledgment in the product documentation would be\n  |   appreciated but is not required.\n  |2. Altered source versions must be plainly marked as such, and must not be\n  |   misrepresented as being the original software.\n  |3. This notice may not be removed or altered from any source distribution.\n  |\n  |Jean-loup Gailly        Mark Adler\n  |jloup@gzip.org          madler@alumni.caltech.edu\n\n\nIf you have any comments, suggestions and questions, write us \nat jzlib@jcraft.com\n\n\n``SSH is a registered trademark and Secure Shell is a trademark of\nSSH Communications Security Corp (www.ssh.com)''.\n"
  },
  {
    "path": "java/com/jcraft/jzlib/StaticTree.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal class StaticTree{\n  static final private int MAX_BITS=15;\n\n  static final private int BL_CODES=19;\n  static final private int D_CODES=30;\n  static final private int LITERALS=256;\n  static final private int LENGTH_CODES=29;\n  static final private int L_CODES=(LITERALS+1+LENGTH_CODES);\n\n  // Bit length codes must not exceed MAX_BL_BITS bits\n  static final int MAX_BL_BITS=7; \n\n  static final short[] static_ltree = {\n    12,  8, 140,  8,  76,  8, 204,  8,  44,  8,\n    172,  8, 108,  8, 236,  8,  28,  8, 156,  8,\n    92,  8, 220,  8,  60,  8, 188,  8, 124,  8,\n    252,  8,   2,  8, 130,  8,  66,  8, 194,  8,\n    34,  8, 162,  8,  98,  8, 226,  8,  18,  8,\n    146,  8,  82,  8, 210,  8,  50,  8, 178,  8,\n    114,  8, 242,  8,  10,  8, 138,  8,  74,  8,\n    202,  8,  42,  8, 170,  8, 106,  8, 234,  8,\n    26,  8, 154,  8,  90,  8, 218,  8,  58,  8,\n    186,  8, 122,  8, 250,  8,   6,  8, 134,  8,\n    70,  8, 198,  8,  38,  8, 166,  8, 102,  8,\n    230,  8,  22,  8, 150,  8,  86,  8, 214,  8,\n    54,  8, 182,  8, 118,  8, 246,  8,  14,  8,\n    142,  8,  78,  8, 206,  8,  46,  8, 174,  8,\n    110,  8, 238,  8,  30,  8, 158,  8,  94,  8,\n    222,  8,  62,  8, 190,  8, 126,  8, 254,  8,\n    1,  8, 129,  8,  65,  8, 193,  8,  33,  8,\n    161,  8,  97,  8, 225,  8,  17,  8, 145,  8,\n    81,  8, 209,  8,  49,  8, 177,  8, 113,  8,\n    241,  8,   9,  8, 137,  8,  73,  8, 201,  8,\n    41,  8, 169,  8, 105,  8, 233,  8,  25,  8,\n    153,  8,  89,  8, 217,  8,  57,  8, 185,  8,\n    121,  8, 249,  8,   5,  8, 133,  8,  69,  8,\n    197,  8,  37,  8, 165,  8, 101,  8, 229,  8,\n    21,  8, 149,  8,  85,  8, 213,  8,  53,  8,\n    181,  8, 117,  8, 245,  8,  13,  8, 141,  8,\n    77,  8, 205,  8,  45,  8, 173,  8, 109,  8,\n    237,  8,  29,  8, 157,  8,  93,  8, 221,  8,\n    61,  8, 189,  8, 125,  8, 253,  8,  19,  9,\n    275,  9, 147,  9, 403,  9,  83,  9, 339,  9,\n    211,  9, 467,  9,  51,  9, 307,  9, 179,  9,\n    435,  9, 115,  9, 371,  9, 243,  9, 499,  9,\n    11,  9, 267,  9, 139,  9, 395,  9,  75,  9,\n    331,  9, 203,  9, 459,  9,  43,  9, 299,  9,\n    171,  9, 427,  9, 107,  9, 363,  9, 235,  9,\n    491,  9,  27,  9, 283,  9, 155,  9, 411,  9,\n    91,  9, 347,  9, 219,  9, 475,  9,  59,  9,\n    315,  9, 187,  9, 443,  9, 123,  9, 379,  9,\n    251,  9, 507,  9,   7,  9, 263,  9, 135,  9,\n    391,  9,  71,  9, 327,  9, 199,  9, 455,  9,\n    39,  9, 295,  9, 167,  9, 423,  9, 103,  9,\n    359,  9, 231,  9, 487,  9,  23,  9, 279,  9,\n    151,  9, 407,  9,  87,  9, 343,  9, 215,  9,\n    471,  9,  55,  9, 311,  9, 183,  9, 439,  9,\n    119,  9, 375,  9, 247,  9, 503,  9,  15,  9,\n    271,  9, 143,  9, 399,  9,  79,  9, 335,  9,\n    207,  9, 463,  9,  47,  9, 303,  9, 175,  9,\n    431,  9, 111,  9, 367,  9, 239,  9, 495,  9,\n    31,  9, 287,  9, 159,  9, 415,  9,  95,  9,\n    351,  9, 223,  9, 479,  9,  63,  9, 319,  9,\n    191,  9, 447,  9, 127,  9, 383,  9, 255,  9,\n    511,  9,   0,  7,  64,  7,  32,  7,  96,  7,\n    16,  7,  80,  7,  48,  7, 112,  7,   8,  7,\n    72,  7,  40,  7, 104,  7,  24,  7,  88,  7,\n    56,  7, 120,  7,   4,  7,  68,  7,  36,  7,\n    100,  7,  20,  7,  84,  7,  52,  7, 116,  7,\n    3,  8, 131,  8,  67,  8, 195,  8,  35,  8,\n    163,  8,  99,  8, 227,  8\n  };\n\n  static final short[] static_dtree = {\n    0, 5, 16, 5,  8, 5, 24, 5,  4, 5,\n    20, 5, 12, 5, 28, 5,  2, 5, 18, 5,\n    10, 5, 26, 5,  6, 5, 22, 5, 14, 5,\n    30, 5,  1, 5, 17, 5,  9, 5, 25, 5,\n    5, 5, 21, 5, 13, 5, 29, 5,  3, 5,\n    19, 5, 11, 5, 27, 5,  7, 5, 23, 5\n  };\n\n  static StaticTree static_l_desc =\n    new StaticTree(static_ltree, Tree.extra_lbits,\n\t\t   LITERALS+1, L_CODES, MAX_BITS);\n\n  static StaticTree static_d_desc =\n    new StaticTree(static_dtree, Tree.extra_dbits,\n\t\t   0,  D_CODES, MAX_BITS);\n\n  static StaticTree static_bl_desc =\n    new StaticTree(null, Tree.extra_blbits,\n\t\t   0, BL_CODES, MAX_BL_BITS);\n\n  short[] static_tree;     // static tree or null\n  int[] extra_bits;        // extra bits for each code or null\n  int extra_base;          // base index for extra_bits\n  int elems;               // max number of elements in the tree\n  int max_length;          // max bit length for the codes\n\n  private StaticTree(short[] static_tree,\n                     int[] extra_bits,\n                     int extra_base,\n                     int elems,\n                     int max_length){\n    this.static_tree=static_tree;\n    this.extra_bits=extra_bits;\n    this.extra_base=extra_base;\n    this.elems=elems;\n    this.max_length=max_length;\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/Tree.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\nfinal class Tree{\n  static final private int MAX_BITS=15;\n  static final private int BL_CODES=19;\n  static final private int D_CODES=30;\n  static final private int LITERALS=256;\n  static final private int LENGTH_CODES=29;\n  static final private int L_CODES=(LITERALS+1+LENGTH_CODES);\n  static final private int HEAP_SIZE=(2*L_CODES+1);\n\n  // Bit length codes must not exceed MAX_BL_BITS bits\n  static final int MAX_BL_BITS=7; \n\n  // end of block literal code\n  static final int END_BLOCK=256; \n\n  // repeat previous bit length 3-6 times (2 bits of repeat count)\n  static final int REP_3_6=16; \n\n  // repeat a zero length 3-10 times  (3 bits of repeat count)\n  static final int REPZ_3_10=17; \n\n  // repeat a zero length 11-138 times  (7 bits of repeat count)\n  static final int REPZ_11_138=18; \n\n  // extra bits for each length code\n  static final int[] extra_lbits={\n    0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0\n  };\n\n  // extra bits for each distance code\n  static final int[] extra_dbits={\n    0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13\n  };\n\n  // extra bits for each bit length code\n  static final int[] extra_blbits={\n    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7\n  };\n\n  static final byte[] bl_order={\n    16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};\n\n\n  // The lengths of the bit length codes are sent in order of decreasing\n  // probability, to avoid transmitting the lengths for unused bit\n  // length codes.\n\n  static final int Buf_size=8*2;\n\n  // see definition of array dist_code below\n  static final int DIST_CODE_LEN=512;\n\n  static final byte[] _dist_code = {\n    0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,\n    8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,\n    10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n    11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,\n    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,\n    13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,\n    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,\n    18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,\n    23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n    24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\n    26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n    26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,\n    27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\n    27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n    28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n    28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n    28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\n    29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\n    29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\n    29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29\n  };\n\n  static final byte[] _length_code={\n    0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,\n    13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,\n    17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,\n    19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,\n    22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,\n    23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n    25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\n    25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,\n    26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n    26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\n    27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28\n  };\n\n  static final int[] base_length = {\n    0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,\n    64, 80, 96, 112, 128, 160, 192, 224, 0\n  };\n\n  static final int[] base_dist = {\n       0,   1,      2,     3,     4,    6,     8,    12,    16,     24,\n      32,  48,     64,    96,   128,  192,   256,   384,   512,    768,\n    1024, 1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576\n  };\n\n  // Mapping from a distance to a distance code. dist is the distance - 1 and\n  // must not have side effects. _dist_code[256] and _dist_code[257] are never\n  // used.\n  static int d_code(int dist){\n    return ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>>7)]);\n  }\n\n  short[] dyn_tree;      // the dynamic tree\n  int     max_code;      // largest code with non zero frequency\n  StaticTree stat_desc;  // the corresponding static tree\n\n  // Compute the optimal bit lengths for a tree and update the total bit length\n  // for the current block.\n  // IN assertion: the fields freq and dad are set, heap[heap_max] and\n  //    above are the tree nodes sorted by increasing frequency.\n  // OUT assertions: the field len is set to the optimal bit length, the\n  //     array bl_count contains the frequencies for each bit length.\n  //     The length opt_len is updated; static_len is also updated if stree is\n  //     not null.\n  void gen_bitlen(Deflate s){\n    short[] tree = dyn_tree;\n    short[] stree = stat_desc.static_tree;\n    int[] extra = stat_desc.extra_bits;\n    int base = stat_desc.extra_base;\n    int max_length = stat_desc.max_length;\n    int h;              // heap index\n    int n, m;           // iterate over the tree elements\n    int bits;           // bit length\n    int xbits;          // extra bits\n    short f;            // frequency\n    int overflow = 0;   // number of elements with bit length too large\n\n    for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;\n\n    // In a first pass, compute the optimal bit lengths (which may\n    // overflow in the case of the bit length tree).\n    tree[s.heap[s.heap_max]*2+1] = 0; // root of the heap\n\n    for(h=s.heap_max+1; h<HEAP_SIZE; h++){\n      n = s.heap[h];\n      bits = tree[tree[n*2+1]*2+1] + 1;\n      if (bits > max_length){ bits = max_length; overflow++; }\n      tree[n*2+1] = (short)bits;\n      // We overwrite tree[n*2+1] which is no longer needed\n\n      if (n > max_code) continue;  // not a leaf node\n\n      s.bl_count[bits]++;\n      xbits = 0;\n      if (n >= base) xbits = extra[n-base];\n      f = tree[n*2];\n      s.opt_len += f * (bits + xbits);\n      if (stree!=null) s.static_len += f * (stree[n*2+1] + xbits);\n    }\n    if (overflow == 0) return;\n\n    // This happens for example on obj2 and pic of the Calgary corpus\n    // Find the first bit length which could increase:\n    do {\n      bits = max_length-1;\n      while(s.bl_count[bits]==0) bits--;\n      s.bl_count[bits]--;      // move one leaf down the tree\n      s.bl_count[bits+1]+=2;   // move one overflow item as its brother\n      s.bl_count[max_length]--;\n      // The brother of the overflow item also moves one step up,\n      // but this does not affect bl_count[max_length]\n      overflow -= 2;\n    }\n    while (overflow > 0);\n\n    for (bits = max_length; bits != 0; bits--) {\n      n = s.bl_count[bits];\n      while (n != 0) {\n\tm = s.heap[--h];\n\tif (m > max_code) continue;\n\tif (tree[m*2+1] != bits) {\n\t  s.opt_len += ((long)bits - (long)tree[m*2+1])*(long)tree[m*2];\n\t  tree[m*2+1] = (short)bits;\n\t}\n\tn--;\n      }\n    }\n  }\n\n  // Construct one Huffman tree and assigns the code bit strings and lengths.\n  // Update the total bit length for the current block.\n  // IN assertion: the field freq is set for all tree elements.\n  // OUT assertions: the fields len and code are set to the optimal bit length\n  //     and corresponding code. The length opt_len is updated; static_len is\n  //     also updated if stree is not null. The field max_code is set.\n  void build_tree(Deflate s){\n    short[] tree=dyn_tree;\n    short[] stree=stat_desc.static_tree;\n    int elems=stat_desc.elems;\n    int n, m;          // iterate over heap elements\n    int max_code=-1;   // largest code with non zero frequency\n    int node;          // new node being created\n\n    // Construct the initial heap, with least frequent element in\n    // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].\n    // heap[0] is not used.\n    s.heap_len = 0;\n    s.heap_max = HEAP_SIZE;\n\n    for(n=0; n<elems; n++) {\n      if(tree[n*2] != 0) {\n\ts.heap[++s.heap_len] = max_code = n;\n\ts.depth[n] = 0;\n      }\n      else{\n\ttree[n*2+1] = 0;\n      }\n    }\n\n    // The pkzip format requires that at least one distance code exists,\n    // and that at least one bit should be sent even if there is only one\n    // possible code. So to avoid special checks later on we force at least\n    // two codes of non zero frequency.\n    while (s.heap_len < 2) {\n      node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);\n      tree[node*2] = 1;\n      s.depth[node] = 0;\n      s.opt_len--; if (stree!=null) s.static_len -= stree[node*2+1];\n      // node is 0 or 1 so it does not have extra bits\n    }\n    this.max_code = max_code;\n\n    // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,\n    // establish sub-heaps of increasing lengths:\n\n    for(n=s.heap_len/2;n>=1; n--)\n      s.pqdownheap(tree, n);\n\n    // Construct the Huffman tree by repeatedly combining the least two\n    // frequent nodes.\n\n    node=elems;                 // next internal node of the tree\n    do{\n      // n = node of least frequency\n      n=s.heap[1];\n      s.heap[1]=s.heap[s.heap_len--];\n      s.pqdownheap(tree, 1);\n      m=s.heap[1];                // m = node of next least frequency\n\n      s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency\n      s.heap[--s.heap_max] = m;\n\n      // Create a new node father of n and m\n      tree[node*2] = (short)(tree[n*2] + tree[m*2]);\n      s.depth[node] = (byte)(Math.max(s.depth[n],s.depth[m])+1);\n      tree[n*2+1] = tree[m*2+1] = (short)node;\n\n      // and insert the new node in the heap\n      s.heap[1] = node++;\n      s.pqdownheap(tree, 1);\n    }\n    while(s.heap_len>=2);\n\n    s.heap[--s.heap_max] = s.heap[1];\n\n    // At this point, the fields freq and dad are set. We can now\n    // generate the bit lengths.\n\n    gen_bitlen(s);\n\n    // The field len is now set, we can generate the bit codes\n    gen_codes(tree, max_code, s.bl_count, s.next_code);\n  }\n\n  // Generate the codes for a given tree and bit counts (which need not be\n  // optimal).\n  // IN assertion: the array bl_count contains the bit length statistics for\n  // the given tree and the field len is set for all tree elements.\n  // OUT assertion: the field code is set for all tree elements of non\n  //     zero code length.\n  private final static void gen_codes(\n                        short[] tree, // the tree to decorate\n                        int max_code, // largest code with non zero frequency\n                        short[] bl_count, // number of codes at each bit length\n                        short[] next_code){\n    short code = 0;            // running code value\n    int bits;                  // bit index\n    int n;                     // code index\n\n    // The distribution counts are first used to generate the code values\n    // without bit reversal.\n    next_code[0]=0;\n    for (bits = 1; bits <= MAX_BITS; bits++) {\n      next_code[bits] = code = (short)((code + bl_count[bits-1]) << 1);\n    }\n\n    // Check that the bit counts in bl_count are consistent. The last code\n    // must be all ones.\n    //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,\n    //        \"inconsistent bit counts\");\n    //Tracev((stderr,\"\\ngen_codes: max_code %d \", max_code));\n\n    for (n = 0;  n <= max_code; n++) {\n      int len = tree[n*2+1];\n      if (len == 0) continue;\n      // Now reverse the bits\n      tree[n*2] = (short)(bi_reverse(next_code[len]++, len));\n    }\n  }\n\n  // Reverse the first len bits of a code, using straightforward code (a faster\n  // method would use a table)\n  // IN assertion: 1 <= len <= 15\n  private final static int bi_reverse(\n                        int code, // the value to invert\n\t\t\tint len   // its bit length\n\t\t\t){\n    int res = 0;\n    do{\n      res|=code&1;\n      code>>>=1;\n      res<<=1;\n    } \n    while(--len>0);\n    return res>>>1;\n  }\n}\n\n"
  },
  {
    "path": "java/com/jcraft/jzlib/ZInputStream.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\npackage com.jcraft.jzlib;\nimport java.io.*;\n\n/**\n * ZInputStream\n *\n * @deprecated  use DeflaterOutputStream or InflaterInputStream\n */\n@Deprecated\npublic class ZInputStream extends FilterInputStream {\n\n  protected int flush=JZlib.Z_NO_FLUSH;\n  protected boolean compress;\n  protected InputStream in=null;\n\n  protected Deflater deflater;\n  protected InflaterInputStream iis;\n\n  public ZInputStream(InputStream in) throws IOException {\n    this(in, false);\n  }\n  public ZInputStream(InputStream in, boolean nowrap) throws IOException {\n    super(in);\n    iis = new InflaterInputStream(in, nowrap);\n    compress=false;\n  }\n\n  public ZInputStream(InputStream in, int level) throws IOException {\n    super(in);\n    this.in=in;\n    deflater = new Deflater();\n    deflater.init(level);\n    compress=true;\n  }\n\n  private byte[] buf1 = new byte[1];\n  public int read() throws IOException {\n    if(read(buf1, 0, 1)==-1) return -1;\n    return(buf1[0]&0xFF);\n  }\n\n  private byte[] buf = new byte[512];\n\n  public int read(byte[] b, int off, int len) throws IOException {\n    if(compress){\n      deflater.setOutput(b, off, len);\n      while(true){\n        int datalen = in.read(buf, 0, buf.length);\n        if(datalen == -1) return -1;\n        deflater.setInput(buf, 0, datalen, true);\n        int err = deflater.deflate(flush);\n        if(deflater.next_out_index>0)\n          return deflater.next_out_index;\n        if(err == JZlib.Z_STREAM_END)\n          return 0;\n        if(err == JZlib.Z_STREAM_ERROR ||\n           err == JZlib.Z_DATA_ERROR){\n          throw new ZStreamException(\"deflating: \"+deflater.msg);\n        }\n      }\n    }\n    else{\n      return iis.read(b, off, len); \n    }\n  }\n\n  public long skip(long n) throws IOException {\n    int len=512;\n    if(n<len)\n      len=(int)n;\n    byte[] tmp=new byte[len];\n    return((long)read(tmp));\n  }\n\n  public int getFlushMode() {\n    return flush;\n  }\n\n  public void setFlushMode(int flush) {\n    this.flush=flush;\n  }\n\n  public long getTotalIn() {\n    if(compress) return deflater.total_in;\n    else return iis.getTotalIn();\n  }\n\n  public long getTotalOut() {\n    if(compress) return deflater.total_out;\n    else return iis.getTotalOut();\n  }\n\n  public void close() throws IOException{\n    if(compress) deflater.end();\n    else iis.close();\n  }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/ZOutputStream.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\npackage com.jcraft.jzlib;\nimport java.io.*;\n\n/**\n * ZOutputStream\n *\n * @deprecated  use DeflaterOutputStream or InflaterInputStream\n */\n@Deprecated\npublic class ZOutputStream extends FilterOutputStream {\n\n  protected int bufsize=512;\n  protected int flush=JZlib.Z_NO_FLUSH;\n  protected byte[] buf=new byte[bufsize];\n  protected boolean compress;\n\n  protected OutputStream out;\n  private boolean end=false;\n\n  private DeflaterOutputStream dos;\n  private Inflater inflater;\n\n  public ZOutputStream(OutputStream out) throws IOException {\n    super(out);\n    this.out=out;\n    inflater = new Inflater();\n    inflater.init();\n    compress=false;\n  }\n\n  public ZOutputStream(OutputStream out, int level) throws IOException {\n    this(out, level, false);\n  }\n\n  public ZOutputStream(OutputStream out, int level, boolean nowrap) throws IOException {\n    super(out);\n    this.out=out;\n    Deflater deflater = new Deflater(level, nowrap);\n    dos = new DeflaterOutputStream(out, deflater);\n    compress=true;\n  }\n\n  private byte[] buf1 = new byte[1];\n  public void write(int b) throws IOException {\n    buf1[0]=(byte)b;\n    write(buf1, 0, 1);\n  }\n\n  public void write(byte b[], int off, int len) throws IOException {\n    if(len==0) return;\n    if(compress){\n      dos.write(b, off, len);\n    }\n    else {\n      inflater.setInput(b, off, len, true);\n      int err = JZlib.Z_OK;\n      while(inflater.avail_in>0){\n        inflater.setOutput(buf, 0, buf.length);\n        err = inflater.inflate(flush);\n        if(inflater.next_out_index>0)\n          out.write(buf, 0, inflater.next_out_index);\n        if(err != JZlib.Z_OK)\n          break;\n      }\n      if(err != JZlib.Z_OK)\n        throw new ZStreamException(\"inflating: \"+inflater.msg);\n      return;\n    }\n  }\n\n  public int getFlushMode() {\n    return flush;\n  }\n\n  public void setFlushMode(int flush) {\n    this.flush=flush;\n  }\n\n  public void finish() throws IOException {\n    int err;\n    if(compress){\n      int tmp = flush;\n      int flush = JZlib.Z_FINISH;\n      try{\n        write(\"\".getBytes(), 0, 0);\n      }\n      finally { flush = tmp; }\n    }\n    else{\n      dos.finish();\n    }\n    flush();\n  }\n  public synchronized void end() {\n    if(end) return;\n    if(compress){\n      try { dos.finish(); } catch(Exception e){}\n    }\n    else{\n      inflater.end();\n    }\n    end=true;\n  }\n  public void close() throws IOException {\n    try{\n      try{finish();}\n      catch (IOException ignored) {}\n    }\n    finally{\n      end();\n      out.close();\n      out=null;\n    }\n  }\n\n  public long getTotalIn() {\n    if(compress) return dos.getTotalIn();\n    else return inflater.total_in;\n  }\n\n  public long getTotalOut() {\n    if(compress) return dos.getTotalOut();\n    else return inflater.total_out;\n  }\n\n  public void flush() throws IOException {\n    out.flush();\n  }\n\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/ZStream.java",
    "content": "/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */\n/*\nCopyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\n/**\n * ZStream\n *\n * @deprecated  Not for public use in the future.\n */\n@Deprecated\npublic class ZStream{\n\n  static final private int MAX_WBITS=15;        // 32K LZ77 window\n  static final private int DEF_WBITS=MAX_WBITS;\n\n  static final private int Z_NO_FLUSH=0;\n  static final private int Z_PARTIAL_FLUSH=1;\n  static final private int Z_SYNC_FLUSH=2;\n  static final private int Z_FULL_FLUSH=3;\n  static final private int Z_FINISH=4;\n\n  static final private int MAX_MEM_LEVEL=9;\n\n  static final private int Z_OK=0;\n  static final private int Z_STREAM_END=1;\n  static final private int Z_NEED_DICT=2;\n  static final private int Z_ERRNO=-1;\n  static final private int Z_STREAM_ERROR=-2;\n  static final private int Z_DATA_ERROR=-3;\n  static final private int Z_MEM_ERROR=-4;\n  static final private int Z_BUF_ERROR=-5;\n  static final private int Z_VERSION_ERROR=-6;\n\n  public byte[] next_in;     // next input byte\n  public int next_in_index;\n  public int avail_in;       // number of bytes available at next_in\n  public long total_in;      // total nb of input bytes read so far\n\n  public byte[] next_out;    // next output byte should be put there\n  public int next_out_index;\n  public int avail_out;      // remaining free space at next_out\n  public long total_out;     // total nb of bytes output so far\n\n  public String msg;\n\n  Deflate dstate; \n  Inflate istate; \n\n  int data_type; // best guess about the data type: ascii or binary\n\n  Checksum adler;\n\n  public ZStream(){\n    this(new Adler32());\n  }\n\n  public ZStream(Checksum adler){\n    this.adler=adler;\n  }\n\n  public int inflateInit(){\n    return inflateInit(DEF_WBITS);\n  }\n  public int inflateInit(boolean nowrap){\n    return inflateInit(DEF_WBITS, nowrap);\n  }\n  public int inflateInit(int w){\n    return inflateInit(w, false);\n  }\n  public int inflateInit(JZlib.WrapperType wrapperType) {\n    return inflateInit(DEF_WBITS, wrapperType);\n  }\n  public int inflateInit(int w, JZlib.WrapperType wrapperType) {\n    boolean nowrap = false;\n    if(wrapperType == JZlib.W_NONE){\n      nowrap = true;\n    }\n    else if(wrapperType == JZlib.W_GZIP) {\n      w += 16;\n    }\n    else if(wrapperType == JZlib.W_ANY) {\n      w |= Inflate.INFLATE_ANY;\n    }\n    else if(wrapperType == JZlib.W_ZLIB) {\n    }\n    return inflateInit(w, nowrap);\n  }\n  public int inflateInit(int w, boolean nowrap){\n    istate=new Inflate(this);\n    return istate.inflateInit(nowrap?-w:w);\n  }\n\n  public int inflate(int f){\n    if(istate==null) return Z_STREAM_ERROR;\n    return istate.inflate(f);\n  }\n  public int inflateEnd(){\n    if(istate==null) return Z_STREAM_ERROR;\n    int ret=istate.inflateEnd();\n//    istate = null;\n    return ret;\n  }\n  public int inflateSync(){\n    if(istate == null)\n      return Z_STREAM_ERROR;\n    return istate.inflateSync();\n  }\n  public int inflateSyncPoint(){\n    if(istate == null)\n      return Z_STREAM_ERROR;\n    return istate.inflateSyncPoint();\n  }\n  public int inflateSetDictionary(byte[] dictionary, int dictLength){\n    if(istate == null)\n      return Z_STREAM_ERROR;\n    return istate.inflateSetDictionary(dictionary, dictLength);\n  }\n  public boolean inflateFinished(){\n    return istate.mode==12 /*DONE*/;\n  }\n\n  public int deflateInit(int level){\n    return deflateInit(level, MAX_WBITS);\n  }\n  public int deflateInit(int level, boolean nowrap){\n    return deflateInit(level, MAX_WBITS, nowrap);\n  }\n  public int deflateInit(int level, int bits){\n    return deflateInit(level, bits, false);\n  }\n  public int deflateInit(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){\n    if(bits < 9 || bits > 15){\n      return Z_STREAM_ERROR;\n    }\n    if(wrapperType == JZlib.W_NONE) {\n      bits *= -1;\n    }\n    else if(wrapperType == JZlib.W_GZIP) {\n        bits += 16;\n    }\n    else if(wrapperType == JZlib.W_ANY) {\n        return Z_STREAM_ERROR;\n    }\n    else if(wrapperType == JZlib.W_ZLIB) {\n    }\n    return this.deflateInit(level, bits, memlevel);\n  }\n  public int deflateInit(int level, int bits, int memlevel){\n    dstate=new Deflate(this);\n    return dstate.deflateInit(level, bits, memlevel);\n  }\n  public int deflateInit(int level, int bits, boolean nowrap){\n    dstate=new Deflate(this);\n    return dstate.deflateInit(level, nowrap?-bits:bits);\n  }\n  public int deflate(int flush){\n    if(dstate==null){\n      return Z_STREAM_ERROR;\n    }\n    return dstate.deflate(flush);\n  }\n  public int deflateEnd(){\n    if(dstate==null) return Z_STREAM_ERROR;\n    int ret=dstate.deflateEnd();\n    dstate=null;\n    return ret;\n  }\n  public int deflateParams(int level, int strategy){\n    if(dstate==null) return Z_STREAM_ERROR;\n    return dstate.deflateParams(level, strategy);\n  }\n  public int deflateSetDictionary (byte[] dictionary, int dictLength){\n    if(dstate == null)\n      return Z_STREAM_ERROR;\n    return dstate.deflateSetDictionary(dictionary, dictLength);\n  }\n\n  // Flush as much pending output as possible. All deflate() output goes\n  // through this function so some applications may wish to modify it\n  // to avoid allocating a large strm->next_out buffer and copying into it.\n  // (See also read_buf()).\n  void flush_pending(){\n    int len=dstate.pending;\n\n    if(len>avail_out) len=avail_out;\n    if(len==0) return;\n\n    if(dstate.pending_buf.length<=dstate.pending_out ||\n       next_out.length<=next_out_index ||\n       dstate.pending_buf.length<(dstate.pending_out+len) ||\n       next_out.length<(next_out_index+len)){\n      //System.out.println(dstate.pending_buf.length+\", \"+dstate.pending_out+\n      //\t\t \", \"+next_out.length+\", \"+next_out_index+\", \"+len);\n      //System.out.println(\"avail_out=\"+avail_out);\n    }\n\n    System.arraycopy(dstate.pending_buf, dstate.pending_out,\n\t\t     next_out, next_out_index, len);\n\n    next_out_index+=len;\n    dstate.pending_out+=len;\n    total_out+=len;\n    avail_out-=len;\n    dstate.pending-=len;\n    if(dstate.pending==0){\n      dstate.pending_out=0;\n    }\n  }\n\n  // Read a new buffer from the current input stream, update the adler32\n  // and total number of bytes read.  All deflate() input goes through\n  // this function so some applications may wish to modify it to avoid\n  // allocating a large strm->next_in buffer and copying from it.\n  // (See also flush_pending()).\n  int read_buf(byte[] buf, int start, int size) {\n    int len=avail_in;\n\n    if(len>size) len=size;\n    if(len==0) return 0;\n\n    avail_in-=len;\n\n    if(dstate.wrap!=0) {\n      adler.update(next_in, next_in_index, len);\n    }\n    System.arraycopy(next_in, next_in_index, buf, start, len);\n    next_in_index  += len;\n    total_in += len;\n    return len;\n  }\n\n  public long getAdler(){\n    return adler.getValue();\n  }\n\n  public void free(){\n    next_in=null;\n    next_out=null;\n    msg=null;\n  }\n\n  public void setOutput(byte[] buf){\n    setOutput(buf, 0, buf.length); \n  }\n\n  public void setOutput(byte[] buf, int off, int len){\n    next_out = buf;\n    next_out_index = off;\n    avail_out = len;\n  }\n\n  public void setInput(byte[] buf){\n    setInput(buf, 0, buf.length, false); \n  }\n\n  public void setInput(byte[] buf, boolean append){\n    setInput(buf, 0, buf.length, append); \n  }\n\n  public void setInput(byte[] buf, int off, int len, boolean append){\n    if(len<=0 && append && next_in!=null) return;\n\n    if(avail_in>0 && append){  \n      byte[] tmp = new byte[avail_in+len];\n      System.arraycopy(next_in, next_in_index, tmp, 0, avail_in);\n      System.arraycopy(buf, off, tmp, avail_in, len);\n      next_in=tmp;\n      next_in_index=0;\n      avail_in+=len;\n    }\n    else{\n      next_in=buf;\n      next_in_index=off;\n      avail_in=len;\n    }\n  }\n\n  public byte[] getNextIn(){\n    return next_in;\n  }\n\n  public void setNextIn(byte[] next_in){\n    this.next_in = next_in;\n  }\n\n  public int getNextInIndex(){\n    return next_in_index;\n  }\n\n  public void setNextInIndex(int next_in_index){\n    this.next_in_index = next_in_index;\n  }\n\n  public int getAvailIn(){\n    return avail_in;\n  }\n\n  public void setAvailIn(int avail_in){\n    this.avail_in = avail_in;\n  }\n\n  public byte[] getNextOut(){\n    return next_out;\n  }\n\n  public void setNextOut(byte[] next_out){\n    this.next_out = next_out;\n  }\n\n  public int getNextOutIndex(){\n    return next_out_index;\n  }\n\n  public void setNextOutIndex(int next_out_index){\n    this.next_out_index = next_out_index;\n  }\n\n  public int getAvailOut(){\n    return avail_out;\n\n  }\n\n  public void setAvailOut(int avail_out){\n    this.avail_out = avail_out;\n  }\n\n  public long getTotalOut(){\n    return total_out;\n  }\n\n  public long getTotalIn(){\n    return total_in;\n  }\n\n  public String getMessage(){\n    return msg;\n  }\n\n  /**\n   * Those methods are expected to be override by Inflater and Deflater.\n   * In the future, they will become abstract methods.\n   */ \n  public int end(){ return Z_OK; }\n  public boolean finished(){ return false; }\n}\n"
  },
  {
    "path": "java/com/jcraft/jzlib/ZStreamException.java",
    "content": "/* -*-mode:java; c-basic-offset:2; -*- */\n/*\nCopyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright \n     notice, this list of conditions and the following disclaimer in \n     the documentation and/or other materials provided with the distribution.\n\n  3. The names of the authors may not be used to endorse or promote products\n     derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\nINC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\nOR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/*\n * This program is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\npackage com.jcraft.jzlib;\n\npublic class ZStreamException extends java.io.IOException {\n  public ZStreamException() {\n    super();\n  }\n  public ZStreamException(String s) {\n    super(s);\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/network/FileDescriptor.java",
    "content": "/* Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\npackage com.tigervnc.network;\n\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport com.tigervnc.rdr.Exception;\n\npublic interface FileDescriptor {\n\n  public int read(ByteBuffer buf, int length) throws Exception;\n  public int write(ByteBuffer buf, int length) throws Exception;\n  public int select(int interestOps, Integer timeout) throws Exception;\n  public void close() throws IOException;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/network/SSLEngineManager.java",
    "content": "/* Copyright (C) 2012,2014 Brian P. Hinz\n * Copyright (C) 2012 D. R. Commander.  All Rights Reserved.\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA\n */\n package com.tigervnc.network;\n\nimport java.io.*;\nimport java.nio.*;\nimport java.nio.channels.*;\nimport javax.net.ssl.*;\nimport javax.net.ssl.SSLEngineResult.*;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Executors;\n\nimport com.tigervnc.rdr.FdInStream;\nimport com.tigervnc.rdr.FdOutStream;\n\npublic class SSLEngineManager {\n\n  private SSLEngine engine = null;\n\n  private ByteBuffer myNetData;\n  private ByteBuffer peerNetData;\n\n  private Executor executor;\n  private FdInStream in;\n  private FdOutStream os;\n\n  public SSLEngineManager(SSLEngine sslEngine, FdInStream is_,\n                          FdOutStream os_) throws IOException {\n\n    in = is_;\n    os = os_;\n    engine = sslEngine;\n\n    executor = Executors.newSingleThreadExecutor();\n\n    int pktBufSize = engine.getSession().getPacketBufferSize();\n    myNetData = ByteBuffer.allocate(pktBufSize);\n    peerNetData = ByteBuffer.allocate(pktBufSize);\n  }\n\n  public void doHandshake() throws Exception {\n\n    // Begin handshake\n    engine.beginHandshake();\n    SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();\n\n    // Process handshaking message\n    SSLEngineResult res = null;\n    int appBufSize = engine.getSession().getApplicationBufferSize();\n    ByteBuffer peerAppData = ByteBuffer.allocate(appBufSize);\n    ByteBuffer myAppData = ByteBuffer.allocate(appBufSize);\n    while (hs != SSLEngineResult.HandshakeStatus.FINISHED &&\n           hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {\n\n      switch (hs) {\n\n      case NEED_UNWRAP:\n        // Receive handshaking data from peer\n        peerNetData.flip();\n        res = engine.unwrap(peerNetData, peerAppData);\n        peerNetData.compact();\n        hs = res.getHandshakeStatus();\n\n        // Check status\n        switch (res.getStatus()) {\n          case BUFFER_UNDERFLOW:\n            int avail = in.check(1, peerNetData.remaining(), false);\n            in.readBytes(peerNetData, avail);\n            break;\n          case OK:\n            // Process incoming handshaking data\n            break;\n          case CLOSED:\n            engine.closeInbound();\n            break;\n        }\n        break;\n\n      case NEED_WRAP:\n        // Generate handshaking data\n        res = engine.wrap(myAppData, myNetData);\n        hs = res.getHandshakeStatus();\n\n        // Check status\n        switch (res.getStatus()) {\n          case OK:\n            myNetData.flip();\n            os.writeBytes(myNetData, myNetData.remaining());\n            os.flush();\n            myNetData.compact();\n            break;\n          case CLOSED:\n            engine.closeOutbound();\n            break;\n        }\n        break;\n\n      case NEED_TASK:\n        // Handle blocking tasks\n        executeTasks();\n        break;\n      }\n      hs = engine.getHandshakeStatus();\n    }\n  }\n\n  private void executeTasks() {\n    Runnable task;\n    while ((task = engine.getDelegatedTask()) != null) {\n      executor.execute(task);\n    }\n  }\n\n  public int read(ByteBuffer data, int length) throws IOException {\n    // Read SSL/TLS encoded data from peer\n    peerNetData.flip();\n    SSLEngineResult res = engine.unwrap(peerNetData, data);\n    peerNetData.compact();\n    switch (res.getStatus()) {\n      case OK :\n        return res.bytesProduced();\n\n      case BUFFER_UNDERFLOW:\n        // attempt to drain the underlying buffer first\n        int need = peerNetData.remaining();\n        in.readBytes(peerNetData, in.check(1, need, true));\n        break;\n\n      case CLOSED:\n        engine.closeInbound();\n        break;\n\n    }\n    return 0;\n  }\n\n  public int write(ByteBuffer data, int length) throws IOException {\n    int n = 0;\n    while (data.hasRemaining()) {\n      SSLEngineResult res = engine.wrap(data, myNetData);\n      n += res.bytesConsumed();\n      switch (res.getStatus()) {\n        case OK:\n          myNetData.flip();\n          os.writeBytes(myNetData, myNetData.remaining());\n          os.flush();\n          myNetData.compact();\n          break;\n\n        case BUFFER_OVERFLOW:\n          // Make room in the buffer by flushing the outstream\n          myNetData.flip();\n          os.writeBytes(myNetData, myNetData.remaining());\n          myNetData.compact();\n          break;\n\n        case CLOSED:\n          engine.closeOutbound();\n          break;\n      }\n    }\n    return n;\n  }\n\n  public SSLSession getSession() {\n    return engine.getSession();\n  }\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/network/Socket.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n// -=- Socket - abstract base-class for any kind of network stream/socket\n\npackage com.tigervnc.network;\n\nimport com.tigervnc.rdr.*;\nimport java.nio.channels.*;\nimport java.nio.channels.spi.SelectorProvider;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\n\nabstract public class Socket {\n\n  public Socket(FileDescriptor fd) {\n    instream = new FdInStream(fd);\n    outstream = new FdOutStream(fd);\n    ownStreams = true; isShutdown_ = false;\n    queryConnection = false;\n  }\n\n  public FdInStream inStream() {return instream;}\n  public FdOutStream outStream() {return outstream;}\n  public FileDescriptor getFd() {return outstream.getFd();}\n\n  // if shutdown() is overridden then the override MUST call on to here\n  public void shutdown() {isShutdown_ = true;}\n  public void close() throws IOException {getFd().close();}\n  public final boolean isShutdown() {return isShutdown_;}\n\n  // information about this end of the socket\n  abstract public int getMyPort();\n\n  // information about the remote end of the socket\n  abstract public String getPeerAddress(); // a string e.g. \"192.168.0.1\"\n  abstract public String getPeerName();\n  abstract public int getPeerPort();\n  abstract public String getPeerEndpoint(); // <address>::<port>\n\n  // Is the remote end on the same machine?\n  abstract public boolean sameMachine();\n\n  public void setRequiresQuery() {queryConnection = true;}\n  public final boolean requiresQuery() {return queryConnection;}\n\n  protected Socket() {\n    instream = null; outstream = null; ownStreams = false;\n    isShutdown_ = false; queryConnection = false;\n  }\n\n  protected Socket(FdInStream i, FdOutStream o, boolean own) {\n    instream = i; outstream = o; ownStreams = own;\n    isShutdown_ = false; queryConnection = false;\n  }\n\n  protected FdInStream instream;\n  protected FdOutStream outstream;\n  boolean ownStreams;\n  boolean isShutdown_;\n  boolean queryConnection;\n}\n"
  },
  {
    "path": "java/com/tigervnc/network/SocketDescriptor.java",
    "content": "/* Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\npackage com.tigervnc.network;\n\nimport java.io.IOException;\n\nimport java.net.SocketAddress;\nimport java.nio.*;\nimport java.nio.channels.*;\nimport java.nio.channels.spi.SelectorProvider;\n\nimport java.util.Set;\nimport java.util.Iterator;\n\nimport com.tigervnc.rdr.Exception;\n\npublic class SocketDescriptor implements FileDescriptor {\n\n  public SocketDescriptor() throws Exception {\n    DefaultSelectorProvider();\n    try {\n      channel = SocketChannel.open();\n      channel.configureBlocking(false);\n      writeSelector = Selector.open();\n      readSelector = Selector.open();\n    } catch (IOException e) {\n      throw new Exception(e.getMessage());\n    }\n    try {\n      channel.register(writeSelector, SelectionKey.OP_WRITE);\n      channel.register(readSelector, SelectionKey.OP_READ);\n    } catch (java.nio.channels.ClosedChannelException e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n\n  public void shutdown() throws IOException {\n    try {\n      channel.socket().shutdownInput();\n      channel.socket().shutdownOutput();\n    } catch(IOException e) {\n      throw new IOException(e.getMessage());\n    }\n  }\n\n  public void close() throws IOException {\n    try {\n      channel.close();\n    } catch(IOException e) {\n      throw new IOException(e.getMessage());\n    }\n  }\n\n  private static SelectorProvider DefaultSelectorProvider() {\n    // kqueue() selector provider on OS X is not working, fall back to select() for now\n    //String os = System.getProperty(\"os.name\");\n    //if (os.startsWith(\"Mac OS X\"))\n    //  System.setProperty(\"java.nio.channels.spi.SelectorProvider\",\"sun.nio.ch.PollSelectorProvider\");\n    return SelectorProvider.provider();\n  }\n\n  synchronized public int select(int interestOps, Integer timeout) throws Exception {\n    int n;\n    Selector selector;\n    if ((interestOps & SelectionKey.OP_READ) != 0) {\n      selector = readSelector;\n    } else {\n      selector = writeSelector;\n    }\n    selector.selectedKeys().clear();\n    try {\n      if (timeout == null) {\n        n = selector.select();\n      } else {\n        int tv = timeout.intValue();\n        switch(tv) {\n        case 0:\n          n = selector.selectNow();\n          break;\n        default:\n          n = selector.select((long)tv);\n          break;\n        }\n      }\n    } catch (java.io.IOException e) {\n      throw new Exception(e.getMessage());\n    }\n    return n;\n  }\n\n  public int write(ByteBuffer buf, int len) throws Exception {\n    try {\n      int n = channel.write((ByteBuffer)buf.slice().limit(len));\n      buf.position(buf.position()+n);\n      return n;\n    } catch (java.io.IOException e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n\n  public int read(ByteBuffer buf, int len) throws Exception {\n    try {\n      int n = channel.read((ByteBuffer)buf.slice().limit(len));\n      buf.position(buf.position()+n);\n      return (n < 0) ? 0 : n;\n    } catch (java.lang.Exception e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n\n  public java.net.Socket socket() {\n    return channel.socket();\n  }\n\n  public SocketAddress getRemoteAddress() throws IOException {\n    if (isConnected())\n      return channel.socket().getRemoteSocketAddress();\n    return null;\n  }\n\n  public SocketAddress getLocalAddress() throws IOException {\n    if (isConnected())\n      return channel.socket().getLocalSocketAddress();\n    return null;\n  }\n\n  public boolean isConnectionPending() {\n    return channel.isConnectionPending();\n  }\n\n  public boolean connect(SocketAddress remote) throws IOException {\n    return channel.connect(remote);\n  }\n\n  public boolean finishConnect() throws IOException {\n    return channel.finishConnect();\n  }\n\n  public boolean isConnected() {\n    return channel.isConnected();\n  }\n\n  protected void setChannel(SocketChannel channel_) {\n    try {\n      if (channel != null)\n        channel.close();\n      if (readSelector != null)\n        readSelector.close();\n      if (writeSelector != null)\n        writeSelector.close();\n      channel = channel_;\n      channel.configureBlocking(false);\n      writeSelector = Selector.open();\n      readSelector = Selector.open();\n    } catch (java.io.IOException e) {\n      throw new Exception(e.getMessage());\n    }\n    try {\n      channel.register(writeSelector, SelectionKey.OP_WRITE);\n      channel.register(readSelector, SelectionKey.OP_READ);\n    } catch (java.nio.channels.ClosedChannelException e) {\n      System.out.println(e.toString());\n    }\n  }\n\n  protected SocketChannel channel;\n  protected Selector writeSelector;\n  protected Selector readSelector;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/network/SocketException.java",
    "content": "/* Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.network;\n\nimport com.tigervnc.rdr.SystemException;\n\npublic class SocketException extends SystemException {\n  public SocketException(String s) {\n    super(s);\n  }\n}\n\n"
  },
  {
    "path": "java/com/tigervnc/network/SocketListener.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n// -=- SocketListener - abstract base-class for any kind of network stream/socket\n\npackage com.tigervnc.network;\n\nimport java.nio.channels.*;\nimport java.nio.channels.spi.SelectorProvider;\n\nabstract public class SocketListener {\n\n  public SocketListener() {}\n\n  // shutdown() stops the socket from accepting further connections\n  abstract public void shutdown() throws Exception;\n\n  // accept() returns a new Socket object if there is a connection\n  // attempt in progress AND if the connection passes the filter\n  // if one is installed.  Otherwise, returns 0.\n  abstract public Socket accept();\n\n  public FileDescriptor getFd() {return fd;}\n\n  protected FileDescriptor fd;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/network/TcpListener.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.network;\n\nimport java.io.IOException;\nimport java.lang.Exception;\nimport java.nio.*;\nimport java.nio.channels.*;\nimport java.net.InetAddress;\nimport java.net.InetSocketAddress;\nimport java.net.SocketAddress;\nimport java.net.UnknownHostException;\nimport java.util.Set;\nimport java.util.Iterator;\n\npublic class TcpListener extends SocketListener  {\n\n  public static boolean socketsInitialised = false;\n\n  public TcpListener(String listenaddr, int port, boolean localhostOnly,\n\t\t\t               SocketDescriptor sock, boolean close_) throws Exception {\n    closeFd = close_;\n    if (sock != null) {\n      fd = sock;\n      return;\n    }\n\n    TcpSocket.initSockets();\n    try {\n      channel = ServerSocketChannel.open();\n      channel.configureBlocking(false);\n    } catch(IOException e) {\n      throw new Exception(\"unable to create listening socket: \"+e.toString());\n    }\n\n    // - Bind it to the desired port\n    InetAddress addr = null;\n\n    try {\n      if (localhostOnly) {\n        addr = InetAddress.getByName(null);\n      } else if (listenaddr != null) {\n          addr = java.net.InetAddress.getByName(listenaddr);\n      } else {\n        addr = InetAddress.getByName(\"0.0.0.0\");\n      }\n    } catch (UnknownHostException e) {\n      throw new Exception(e.getMessage());\n    }\n\n    try {\n      channel.socket().bind(new InetSocketAddress(addr, port));\n    } catch (IOException e) {\n      throw new Exception(\"unable to bind listening socket: \"+e.toString());\n    }\n\n    // - Set it to be a listening socket\n    try {\n      selector = Selector.open();\n      channel.register(selector, SelectionKey.OP_ACCEPT);\n    } catch (IOException e) {\n      throw new Exception(\"unable to set socket to listening mode: \"+e.toString());\n    }\n  }\n\n  public TcpListener(String listenaddr, int port) throws Exception {\n    this(listenaddr, port, false, null, true);\n  }\n\n  protected void finalize() throws Exception {\n    if (closeFd)\n      try {\n        ((SocketDescriptor)getFd()).close();\n      } catch (IOException e) {\n        throw new Exception(e.getMessage());\n      }\n  }\n\n  public void shutdown() throws Exception {\n    try {\n      ((SocketDescriptor)getFd()).shutdown();\n    } catch (IOException e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n\n  public TcpSocket accept() {\n    SocketChannel new_sock = null;\n\n    // Accept an incoming connection\n    try {\n      if (selector.select(0) > 0) {\n        Set<SelectionKey> keys = selector.selectedKeys();\n        Iterator<SelectionKey> iter = keys.iterator();\n        while (iter.hasNext()) {\n          SelectionKey key = (SelectionKey)iter.next();\n          iter.remove();\n          if (key.isAcceptable()) {\n            new_sock = channel.accept();\n            break;\n          }\n        }\n        keys.clear();\n        if (new_sock == null)\n          return null;\n      }\n    } catch (IOException e) {\n      throw new SocketException(\"unable to accept new connection: \"+e.toString());\n    }\n\n    // Disable Nagle's algorithm, to reduce latency\n    try {\n      new_sock.socket().setTcpNoDelay(true);\n    } catch (java.net.SocketException e) {\n      throw new SocketException(e.getMessage());\n    }\n\n    // Create the socket object & check connection is allowed\n    SocketDescriptor fd = null;\n    try {\n      fd = new SocketDescriptor();\n    } catch (java.lang.Exception e) {\n      throw new SocketException(e.getMessage());\n    }\n    fd.setChannel(new_sock);\n    TcpSocket s = new TcpSocket(fd);\n    return s;\n  }\n\n  public int getMyPort() {\n    return ((SocketDescriptor)getFd()).socket().getLocalPort();\n  }\n\n  private boolean closeFd;\n  private ServerSocketChannel channel;\n  private Selector selector;\n\n}\n\n"
  },
  {
    "path": "java/com/tigervnc/network/TcpSocket.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.network;\n\nimport com.tigervnc.rdr.FdInStream;\nimport com.tigervnc.rdr.FdOutStream;\nimport com.tigervnc.rdr.Exception;\nimport com.tigervnc.rfb.LogWriter;\n\nimport java.io.IOException;\nimport java.net.InetAddress;\nimport java.net.InetSocketAddress;\nimport java.net.SocketAddress;\nimport java.net.UnknownHostException;\nimport java.nio.*;\nimport java.nio.channels.*;\n\nimport java.util.Set;\nimport java.util.Iterator;\n\npublic class TcpSocket extends Socket {\n\n  // -=- Socket initialisation\n  public static boolean socketsInitialised = false;\n  public static void initSockets() {\n    if (socketsInitialised)\n      return;\n    socketsInitialised = true;\n  }\n\n  // -=- TcpSocket\n\n  public TcpSocket(SocketDescriptor sock, boolean close) {\n    super(new FdInStream(sock), new FdOutStream(sock), true);\n    closeFd = close;\n  }\n\n  public TcpSocket(SocketDescriptor sock) {\n    this(sock, true);\n  }\n\n  public TcpSocket(String host, int port) throws Exception {\n    closeFd = true;\n    SocketDescriptor sock = null;\n    InetAddress addr = null;\n    boolean result = false;\n\n    // - Create a socket\n    initSockets();\n\n    try {\n      addr = java.net.InetAddress.getByName(host);\n    } catch(UnknownHostException e) {\n      throw new Exception(\"unable to resolve host by name: \"+e.toString());\n    }\n\n    try {\n      sock = new SocketDescriptor();\n    } catch(Exception e) {\n      throw new SocketException(\"unable to create socket: \"+e.toString());\n    }\n\n    /* Attempt to connect to the remote host */\n    try {\n      result = sock.connect(new InetSocketAddress(addr, port));\n      Selector selector = Selector.open();\n      SelectionKey connect_key =\n        sock.socket().getChannel().register(selector, SelectionKey.OP_CONNECT);\n      // Try for the connection for 3000ms\n      while (selector.select(3000) > 0) {\n        while (!result) {\n\n          Set keys = selector.selectedKeys();\n          Iterator i = keys.iterator();\n\n          while (i.hasNext()) {\n            SelectionKey key = (SelectionKey)i.next();\n\n            // Remove the current key\n            i.remove();\n\n            // Attempt a connection\n            if (key.isConnectable()) {\n              if (sock.isConnectionPending())\n                sock.finishConnect();\n              result = true;\n            }\n          }\n        }\n      }\n      if (!result)\n        throw new SocketException(\"unable to connect to socket: Host is down\");\n    } catch(java.io.IOException e) {\n      throw new SocketException(\"unable to connect:\"+e.getMessage());\n    }\n\n    // Disable Nagle's algorithm, to reduce latency\n    enableNagles(sock, false);\n\n    // Create the input and output streams\n    instream = new FdInStream(sock);\n    outstream = new FdOutStream(sock);\n    ownStreams = true;\n  }\n\n  protected void finalize() throws Exception {\n    if (closeFd)\n      try {\n        ((SocketDescriptor)getFd()).close();\n      } catch (IOException e) {\n        throw new Exception(e.getMessage());\n      }\n  }\n\n  public int getMyPort() {\n    return getSockPort();\n  }\n\n  public String getPeerAddress() {\n    InetAddress peer = ((SocketDescriptor)getFd()).socket().getInetAddress();\n    if (peer != null)\n      return peer.getHostAddress();\n    return \"\";\n  }\n\n  public String getPeerName() {\n    InetAddress peer = ((SocketDescriptor)getFd()).socket().getInetAddress();\n    if (peer != null)\n      return peer.getHostName();\n    return \"\";\n  }\n\n  public int getPeerPort() {\n    int port = ((SocketDescriptor)getFd()).socket().getPort();\n    return port;\n  }\n\n  public String getPeerEndpoint() {\n    String address = getPeerAddress();\n    int port = getPeerPort();\n    return address+\"::\"+port;\n  }\n\n  public boolean sameMachine() throws Exception {\n    try {\n      SocketAddress peeraddr = ((SocketDescriptor)getFd()).getRemoteAddress();\n      SocketAddress myaddr = ((SocketDescriptor)getFd()).getLocalAddress();\n      return myaddr.equals(peeraddr);\n    } catch (IOException e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n\n  public void shutdown() throws Exception {\n    super.shutdown();\n    try {\n      ((SocketDescriptor)getFd()).shutdown();\n    } catch (IOException e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n\n  public void close() throws IOException {\n    ((SocketDescriptor)getFd()).close();\n  }\n\n  public static boolean enableNagles(SocketDescriptor sock, boolean enable) {\n    try {\n      sock.channel.socket().setTcpNoDelay(!enable);\n    } catch(java.net.SocketException e) {\n      vlog.error(\"Unable to setsockopt TCP_NODELAY: \"+e.getMessage());\n      return false;\n    }\n    return true;\n  }\n\n  public static boolean isSocket(java.net.Socket sock) {\n    return sock.getClass().toString().equals(\"com.tigervnc.net.Socket\");\n  }\n\n  public boolean isConnected() {\n    return ((SocketDescriptor)getFd()).isConnected();\n  }\n\n  public int getSockPort() {\n    return ((SocketDescriptor)getFd()).socket().getLocalPort();\n  }\n\n  /* Tunnelling support. */\n  public static int findFreeTcpPort() {\n    java.net.ServerSocket sock;\n    int port;\n    try {\n      sock = new java.net.ServerSocket(0);\n      port = sock.getLocalPort();\n      sock.close();\n    } catch (java.io.IOException e) {\n      throw new SocketException(\"unable to create socket: \"+e.toString());\n    }\n    return port;\n  }\n\n  private boolean closeFd;\n  static LogWriter vlog = new LogWriter(\"TcpSocket\");\n\n}\n\n\n"
  },
  {
    "path": "java/com/tigervnc/rdr/AESEAXCipher.java",
    "content": "/* Copyright (C) 2022 Dinglan Peng\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\nimport java.util.Arrays;\n\nimport java.security.InvalidKeyException;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.InvalidAlgorithmParameterException;\n\nimport javax.crypto.Cipher;\nimport javax.crypto.spec.IvParameterSpec;\nimport javax.crypto.spec.SecretKeySpec;\nimport javax.crypto.BadPaddingException;\nimport javax.crypto.IllegalBlockSizeException;\nimport javax.crypto.NoSuchPaddingException;\n\npublic class AESEAXCipher {\n    \n  private static final byte[] zeroBlock = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\n  private static final byte[] prefixBlock0 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\n  private static final byte[] prefixBlock1 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};\n  private static final byte[] prefixBlock2 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2};\n  private static final int[] lut = {0x0,0x87,0x0e,0x89};\n\n  public AESEAXCipher(byte[] key)\n  {\n    try {\n      Cipher blockCipher = Cipher.getInstance(\"AES\");\n      cbcCipher = Cipher.getInstance(\"AES/CBC/NOPADDING\");\n      ctrCipher = Cipher.getInstance(\"AES/CTR/NOPADDING\");\n      keySpec = new SecretKeySpec(key, \"AES\");\n      blockCipher.init(Cipher.ENCRYPT_MODE, keySpec);\n      cbcCipher.init(Cipher.ENCRYPT_MODE, keySpec,\n                     new IvParameterSpec(zeroBlock));\n      subKey1 = Arrays.copyOfRange(blockCipher.doFinal(zeroBlock), 0, 16);\n      subKey2 = new byte[16];\n      int v = (subKey1[0] & 0xff) >>> 6;\n      for (int i = 0; i < 15; i++) {\n        subKey2[i] = (byte)(((subKey1[i + 1] & 0xff) >>> 6) |\n                            ((subKey1[i] & 0xff) << 2));\n        subKey1[i] = (byte)(((subKey1[i + 1] & 0xff) >>> 7) |\n                            ((subKey1[i] & 0xff) << 1));\n      }\n      subKey2[14] ^= v >>> 1;\n      subKey2[15] = (byte)(((subKey1[15] & 0xff) << 2) ^ lut[v]);\n      subKey1[15] = (byte)(((subKey1[15] & 0xff) << 1) ^ lut[v >>> 1]);\n    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {\n      throw new Exception(\"AESEAXCipher: AES algorithm is not supported\");\n    } catch (IllegalBlockSizeException | BadPaddingException |\n             InvalidKeyException | InvalidAlgorithmParameterException e) {\n      throw new Exception(\"AESEAXCipher: invalid key\");\n    }\n  }\n\n  private void encryptCTR(byte[] input, int inputOffset, int inputLength,\n                          byte[] output, int outputOffset, byte[] iv)\n  {\n    try {\n      ctrCipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));\n      ctrCipher.doFinal(input, inputOffset, inputLength, output, outputOffset);\n    } catch (java.lang.Exception e) {\n      throw new Exception(\"AESEAXCipher: \" + e.toString());\n    }\n  }\n\n  private byte[] computeCMAC(byte[] input, int offset,\n                             int length, byte[] prefix)\n  {\n    int n = length / 16;\n    int m = (length + 15) / 16;\n    int r = length - n * 16;\n    byte[] cbcData = new byte[(m + 1) * 16];\n    System.arraycopy(prefix, 0, cbcData, 0, 16);\n    System.arraycopy(input, offset, cbcData, 16, length);\n    \n    if (r == 0) {\n      for (int i = 0; i < 16; i++) {\n        cbcData[n * 16 + i] ^= subKey1[i] & 0xff;\n      }\n    } else {\n      cbcData[(n + 1) * 16 + r] = (byte)0x80;\n      for (int i = 0; i < 16; i++) {\n        cbcData[(n + 1) * 16 + i] ^= subKey2[i] & 0xff;\n      }\n    }\n    try {\n      byte[] encrypted = cbcCipher.doFinal(cbcData);\n      return Arrays.copyOfRange(encrypted, encrypted.length - 16, encrypted.length - 0);\n    } catch (java.lang.Exception e) {\n      throw new Exception(\"AESEAXCipher: \" + e.getMessage());\n    }\n  }\n\n  public void encrypt(byte[] input, int inputOffset, int inputLength,\n                      byte[] ad,  int adOffset, int adLength,\n                      byte[] nonce,\n                      byte[] output, int outputOffset,\n                      byte[] mac, int macOffset)\n  {\n    byte[] nCMAC = computeCMAC(nonce, 0, nonce.length, prefixBlock0);\n    encryptCTR(input, inputOffset, inputLength, output, outputOffset, nCMAC);\n    byte[] adCMAC = computeCMAC(ad, adOffset, adLength, prefixBlock1);\n    byte[] m = computeCMAC(output, outputOffset, inputLength, prefixBlock2);\n    for (int i = 0; i < 16; i++) {\n      mac[macOffset + i] = (byte)((m[i] & 0xff) ^\n                                  (nCMAC[i] & 0xff) ^\n                                  (adCMAC[i] & 0xff));\n    }\n  }\n\n  public void decrypt(byte[] input, int inputOffset, int inputLength,\n                      byte[] ad,  int adOffset, int adLength,\n                      byte[] nonce,\n                      byte[] output, int outputOffset,\n                      byte[] mac, int macOffset)\n  {\n    byte[] nCMAC = computeCMAC(nonce, 0, nonce.length, prefixBlock0);\n    byte[] adCMAC = computeCMAC(ad, adOffset, adLength, prefixBlock1);\n    byte[] m = computeCMAC(input, inputOffset, inputLength, prefixBlock2);\n    for (int i = 0; i < 16; i++) {\n      byte x = (byte)((m[i] & 0xff) ^ (nCMAC[i] & 0xff) ^ (adCMAC[i] & 0xff));\n      if (x != mac[macOffset + i])\n        throw new Exception(\"AESEAXCipher: failed to authenticate message\"); \n    }\n    encryptCTR(input, inputOffset, inputLength, output, outputOffset, nCMAC);\n  }\n\n  private SecretKeySpec keySpec;\n  private Cipher ctrCipher;\n  private Cipher cbcCipher;\n  private byte[] subKey1;\n  private byte[] subKey2;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/AESInStream.java",
    "content": "/* Copyright (C) 2022 Dinglan Peng\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\nimport java.nio.ByteBuffer;\n\npublic class AESInStream extends InStream {\n\n  private static final int maxMessageSize = 65536;\n\n  public AESInStream(InStream _in, byte[] key)\n  {\n    in = _in;\n    offset = 0;\n    bufSize = maxMessageSize;\n    b = new byte[bufSize];\n    ptr = end = start = 0;\n    cipher = new AESEAXCipher(key);\n    messageSize = 0;\n    messageOffset = 0;\n    message = new byte[maxMessageSize + 16];\n    decryptedMessageOffset = 0;\n    decryptedMessage = new byte[maxMessageSize];\n    counter = new byte[16];\n    state = 0;\n  }\n\n  public final int pos()\n  {\n    return offset + ptr - start;\n  }\n\n  protected final int overrun(int itemSize, int nItems, boolean wait)\n  {\n    if (itemSize > bufSize)\n      throw new Exception(\"AESInStream overrun: max itemSize exceeded\");\n\n    if (end - ptr != 0)\n      System.arraycopy(b, ptr, b, 0, end - ptr);\n\n    offset += ptr - start;\n    end -= ptr - start;\n    ptr = start;\n\n    while ((end - start) < itemSize) {\n      int n = readMessage(b, end, start + bufSize - end, wait);\n      if (!wait && n == 0)\n        return 0;\n      end += n;\n    }\n\n    int nAvail;\n    nAvail = (end - ptr) / itemSize;\n    if (nAvail < nItems)\n      return nAvail;\n\n    return nItems;\n  }\n\n  private int readMessage(byte[] buf, int bufPtr, int len, boolean wait)\n  {\n    if (state == 0 || state == 1) {\n      if (!fillDecryptedMessageBuffer(wait) && !wait)\n        return 0;\n    }\n    if (state == 2) {\n      int readSize = messageSize - decryptedMessageOffset;\n      if (readSize > len)\n        readSize = len;\n      System.arraycopy(decryptedMessage, decryptedMessageOffset,\n                       buf, bufPtr, readSize);\n      decryptedMessageOffset += readSize;\n      if (decryptedMessageOffset == messageSize)\n        state = 0;\n      return readSize;\n    }\n    return 0;\n  }\n\n  private boolean fillDecryptedMessageBuffer(boolean wait)\n  {\n    if (state == 0) {\n      while (true) {\n        if (in.check(2, 1, wait) != 0) {\n          messageSize = in.readU16();\n          messageOffset = 0;\n          state = 1;\n          break;\n        } else if (!wait) {\n          return false;\n        }\n      }\n    }\n    if (state == 1) {\n      if (wait) {\n        in.readBytes(ByteBuffer.wrap(message, messageOffset,\n                                     messageSize + 16 - messageOffset),\n                     messageSize + 16 - messageOffset);\n      } else {\n        while (true) {\n          int readSize = messageSize + 16 - messageOffset;\n          if (in.check(1, readSize, false) != 0) {\n            int availSize = in.getend() - in.getptr();\n            if (readSize > availSize)\n              readSize = availSize;\n            in.readBytes(ByteBuffer.wrap(message, messageOffset, readSize),\n                         readSize);\n            messageOffset += readSize;\n            if (messageSize + 16 == messageOffset) {\n              break;\n            }\n          } else {\n            return false;\n          }\n        }\n      }\n    }\n    byte[] ad = new byte[] {\n      (byte)((messageSize & 0xff00) >> 8),\n      (byte)(messageSize & 0xff)\n    };\n    cipher.decrypt(message, 0, messageSize,\n                   ad, 0, 2,\n                   counter,\n                   decryptedMessage, 0,\n                   message, messageSize);\n    // Update nonce by incrementing the counter as a\n    // 128bit little endian unsigned integer\n    for (int i = 0; i < 16; ++i) {\n      // increment until there is no carry\n      if (++counter[i] != 0) {\n        break;\n      }\n    }\n    decryptedMessageOffset = 0;\n    state = 2;\n    return true;\n  }\n\n\n  private AESEAXCipher cipher;\n  private int offset;\n  private int start;\n  private int bufSize;\n  private int state;\n  private int messageSize;\n  private int messageOffset;\n  private byte[] message;\n  private int decryptedMessageOffset;\n  private byte[] decryptedMessage;\n  private byte[] counter;\n  private InStream in;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/AESOutStream.java",
    "content": "/* Copyright (C) 2022 Dinglan Peng\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\nimport java.nio.ByteBuffer;\n\npublic class AESOutStream extends OutStream {\n\n  static final int maxMessageSize = 8192;\n\n  public AESOutStream(OutStream _out, byte[] key)\n  {\n    out = _out;\n    bufSize = maxMessageSize;\n    b = new byte[bufSize];\n    buffer = new byte[bufSize + 16 + 2];\n    ptr = offset = start = 0;\n    end = start + bufSize;\n    cipher = new AESEAXCipher(key);\n    counter = new byte[16];\n  }\n\n  public int length()\n  {\n    return offset + ptr - start;\n  }\n\n  public void flush()\n  {\n    int sentUpTo = start;\n    while (sentUpTo < ptr) {\n      int n = writeMessage(b, sentUpTo, ptr - sentUpTo);\n      sentUpTo += n;\n      offset += n;\n    }\n\n    ptr = start;\n  }\n\n  protected int overrun(int itemSize, int nItems)\n  {\n    if (itemSize > bufSize)\n      throw new Exception(\"AESOutStream overrun: max itemSize exceeded\");\n\n    flush();\n\n    int nAvail;\n    nAvail = (end - ptr) / itemSize;\n    if (nAvail < nItems)\n      return nAvail;\n\n    return nItems;\n  }\n\n  protected int writeMessage(byte[] data, int dataPtr, int length)\n  {\n    if (length == 0)\n      return 0;\n    buffer[0] = (byte)((length & 0xff00) >> 8);\n    buffer[1] = (byte)(length & 0xff);\n    cipher.encrypt(data, dataPtr, length,\n                   buffer, 0, 2,\n                   counter,\n                   buffer, 2,\n                   buffer, 2 + length);\n    out.writeBytes(ByteBuffer.wrap(buffer, 0, length + 16 + 2),\n                   length + 16 + 2);\n    out.flush();\n    // Update nonce by incrementing the counter as a\n    // 128bit little endian unsigned integer\n    for (int i = 0; i < 16; ++i) {\n      // increment until there is no carry\n      if (++counter[i] != 0) {\n        break;\n      }\n    }\n    return length;\n  }\n\n  private AESEAXCipher cipher;\n  private int start;\n  private int offset;\n  private int bufSize;\n  private byte[] buffer;\n  private byte[] counter;\n  private OutStream out;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/EndOfStream.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\npublic class EndOfStream extends Exception {\n  public EndOfStream() {\n    super(\"EndOfStream\");\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/Exception.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\npublic class Exception extends RuntimeException {\n  public Exception(String s) {\n    super(s);\n  }\n}\n\nclass FrameException extends Exception {\n  public FrameException() {\n    super(\"Frame Exception\");\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/FdInStream.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2012-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\nimport java.nio.*;\nimport java.nio.channels.Selector;\nimport java.nio.channels.SelectionKey;\nimport java.util.Set;\nimport java.util.Iterator;\n\nimport com.tigervnc.network.*;\n\npublic class FdInStream extends InStream {\n\n  static final int DEFAULT_BUF_SIZE = 16384;\n  static final int minBulkSize = 1024;\n\n  public FdInStream(FileDescriptor fd_, int timeoutms_, int bufSize_,\n                    boolean closeWhenDone_)\n  {\n    fd = fd_; closeWhenDone = closeWhenDone_;\n    timeoutms = timeoutms_; blockCallback = null;\n    timing = false; timeWaitedIn100us = 5; timedKbits = 0;\n    bufSize = ((bufSize_ > 0) ? bufSize_ : DEFAULT_BUF_SIZE);\n    b = new byte[bufSize];\n    ptr = end = offset = 0;\n  }\n\n  public FdInStream(FileDescriptor fd_) { this(fd_, -1, 0, false); }\n\n  public FdInStream(FileDescriptor fd_, FdInStreamBlockCallback blockCallback_,\n                    int bufSize_)\n  {\n    fd = fd_; timeoutms = 0; blockCallback = blockCallback_;\n    timing = false; timeWaitedIn100us = 5; timedKbits = 0;\n    bufSize = ((bufSize_ > 0) ? bufSize_ : DEFAULT_BUF_SIZE);\n    b = new byte[bufSize];\n    ptr = end = offset = 0;\n  }\n\n  public FdInStream(FileDescriptor fd_,\n                    FdInStreamBlockCallback blockCallback_) {\n    this(fd_, blockCallback_, 0);\n  }\n\n  public final void readBytes(ByteBuffer data, int length) {\n    if (length < minBulkSize) {\n      super.readBytes(data, length);\n      return;\n    }\n\n    int dataPtr = data.position();\n\n    int n = end - ptr;\n    if (n > length) n = length;\n\n    data.put(b, ptr, n);\n    dataPtr += n;\n    length -= n;\n    ptr += n;\n\n    while (length > 0) {\n      n = readWithTimeoutOrCallback(data, length);\n      dataPtr += n;\n      length -= n;\n      offset += n;\n    }\n  }\n\n  public void setTimeout(int timeoutms_) {\n    timeoutms = timeoutms_;\n  }\n\n  public void setBlockCallback(FdInStreamBlockCallback blockCallback_)\n  {\n    blockCallback = blockCallback_;\n    timeoutms = 0;\n  }\n\n  public final int pos() { return offset + ptr; }\n\n  public final void startTiming() {\n    timing = true;\n\n    // Carry over up to 1s worth of previous rate for smoothing.\n\n    if (timeWaitedIn100us > 10000) {\n      timedKbits = timedKbits * 10000 / timeWaitedIn100us;\n      timeWaitedIn100us = 10000;\n    }\n  }\n\n  public final void stopTiming() {\n    timing = false;\n    if (timeWaitedIn100us < timedKbits/2)\n      timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s\n  }\n\n  public final long kbitsPerSecond() {\n    return timedKbits * 10000 / timeWaitedIn100us;\n  }\n\n  public final long timeWaited() { return timeWaitedIn100us; }\n\n  protected int overrun(int itemSize, int nItems, boolean wait)\n  {\n    if (itemSize > bufSize)\n      throw new Exception(\"FdInStream overrun: max itemSize exceeded\");\n\n    if (end - ptr != 0)\n      System.arraycopy(b, ptr, b, 0, end - ptr);\n\n    offset += ptr;\n    end -= ptr;\n    ptr = 0;\n\n    int bytes_to_read;\n    while (end < itemSize) {\n      bytes_to_read = bufSize - end;\n      if (!timing) {\n        // When not timing, we must be careful not to read too much\n        // extra data into the buffer. Otherwise, the line speed\n        // estimation might stay at zero for a long time: All reads\n        // during timing=1 can be satisfied without calling\n        // readWithTimeoutOrCallback. However, reading only 1 or 2 bytes\n        // bytes is ineffecient.\n        bytes_to_read = Math.min(bytes_to_read, Math.max(itemSize*nItems, 8));\n      }\n      Buffer buf = ByteBuffer.wrap(b).position(end);\n      int n = readWithTimeoutOrCallback((ByteBuffer)buf, bytes_to_read, wait);\n      if (n == 0) return 0;\n      end += n;\n    }\n\n    int nAvail;\n    nAvail = (end - ptr) / itemSize;\n    if (nAvail < nItems)\n      return nAvail;\n\n    return nItems;\n  }\n\n  protected int readWithTimeoutOrCallback(ByteBuffer buf, int len, boolean wait) {\n    long before = 0;\n    if (timing)\n      before = System.nanoTime();\n\n    int n;\n    while (true) {\n      do {\n        Integer tv;\n\n        if (!wait) {\n          tv = new Integer(0);\n        } else if (timeoutms != -1) {\n          tv = new Integer(timeoutms);\n        } else {\n          tv = null;\n        }\n\n        try {\n          n = fd.select(SelectionKey.OP_READ, tv);\n        } catch (Exception e) {\n          throw new SystemException(\"select:\"+e.toString());\n        }\n      } while (n < 0);\n\n\n      if (n > 0) break;\n      if (!wait) return 0;\n      if (blockCallback == null) throw new TimedOut();\n\n      blockCallback.blockCallback();\n    }\n\n    try {\n      n = fd.read(buf, len);\n    } catch (Exception e) {\n      throw new SystemException(\"read:\"+e.toString());\n    }\n\n    if (n == 0) throw new EndOfStream();\n\n    if (timing) {\n      long after = System.nanoTime();\n      long newTimeWaited = (after - before) / 100000;\n      int newKbits = n * 8 / 1000;\n\n      // limit rate to between 10kbit/s and 40Mbit/s\n\n      if (newTimeWaited > newKbits*1000) {\n        newTimeWaited = newKbits*1000;\n      } else if (newTimeWaited < newKbits/4) {\n        newTimeWaited = newKbits/4;\n      }\n\n      timeWaitedIn100us += newTimeWaited;\n      timedKbits += newKbits;\n    }\n\n    return n;\n  }\n\n  private int readWithTimeoutOrCallback(ByteBuffer buf, int len) {\n    return readWithTimeoutOrCallback(buf, len, true);\n  }\n\n  public FileDescriptor getFd() {\n    return fd;\n  }\n\n  public void setFd(FileDescriptor fd_) {\n    fd = fd_;\n  }\n\n  public int getBufSize() {\n    return bufSize;\n  }\n\n  private FileDescriptor fd;\n  boolean closeWhenDone;\n  protected int timeoutms;\n  private FdInStreamBlockCallback blockCallback;\n  private int offset;\n  private int bufSize;\n\n  protected boolean timing;\n  protected long timeWaitedIn100us;\n  protected long timedKbits;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/FdInStreamBlockCallback.java",
    "content": "/* Copyright (C) 2011-2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\npublic interface FdInStreamBlockCallback {\n  abstract public void blockCallback();\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/FdOutStream.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011 Pierre Ossman for Cendio AB\n * Copyright (C) 2012-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\nimport java.nio.ByteBuffer;\nimport java.nio.channels.SelectionKey;\n\nimport com.tigervnc.network.*;\n\npublic class FdOutStream extends OutStream {\n\n  static final int DEFAULT_BUF_SIZE = 16384;\n  static final int minBulkSize = 1024;\n\n  public FdOutStream(FileDescriptor fd_, boolean blocking_, int timeoutms_, int bufSize_)\n  {\n    fd = fd_; blocking = blocking_; timeoutms = timeoutms_;\n    bufSize = ((bufSize_ > 0) ? bufSize_ : DEFAULT_BUF_SIZE);\n    b = new byte[bufSize];\n    offset = 0;\n    ptr = sentUpTo = start = 0;\n    end = start + bufSize;\n\n    lastWrite = System.currentTimeMillis();\n  }\n\n  public FdOutStream(FileDescriptor fd_) { this(fd_, true, -1, 0); }\n\n  public void setTimeout(int timeoutms_) {\n    timeoutms = timeoutms_;\n  }\n\n  public void setBlocking(boolean blocking_) {\n    blocking = blocking_;\n  }\n\n  public int length()\n  {\n    return offset + ptr - sentUpTo;\n  }\n\n  int bufferUsage()\n  {\n    return ptr - sentUpTo;\n  }\n\n  long getIdleTime()\n  {\n    return System.currentTimeMillis()-lastWrite;\n  }\n\n  public void flush()\n  {\n    while (sentUpTo < ptr) {\n      int n = writeWithTimeout(b, sentUpTo,\n                               ptr - sentUpTo,\n                               blocking ? timeoutms : 0);\n\n      // Timeout?\n      if (n == 0) {\n        // If non-blocking then we're done here\n        if (!blocking)\n          break;\n\n        throw new TimedOut();\n      }\n\n      sentUpTo += n;\n      offset += n;\n    }\n\n    // Managed to flush everything?\n    if (sentUpTo == ptr)\n      ptr = sentUpTo = start;\n  }\n\n  protected int overrun(int itemSize, int nItems)\n  {\n    if (itemSize > bufSize)\n      throw new Exception(\"FdOutStream overrun: max itemSize exceeded\");\n\n    // First try to get rid of the data we have\n    flush();\n\n    // Still not enough space?\n    if (itemSize > end - ptr) {\n      // Can we shuffle things around?\n      // (don't do this if it gains us less than 25%)\n      if ((sentUpTo - start > bufSize / 4) &&\n          (itemSize < bufSize - (ptr - sentUpTo))) {\n        System.arraycopy(b, ptr, b, start, ptr - sentUpTo);\n        ptr = start + (ptr - sentUpTo);\n        sentUpTo = start;\n      } else {\n        // Have to get rid of more data, so turn off non-blocking\n        // for a bit...\n        boolean realBlocking;\n\n        realBlocking = blocking;\n        blocking = true;\n        flush();\n        blocking = realBlocking;\n      }\n    }\n\n    int nAvail;\n    nAvail = (end - ptr) / itemSize;\n    if (nAvail < nItems)\n      return nAvail;\n\n    return nItems;\n  }\n\n  private int writeWithTimeout(byte[] data, int dataPtr, int length, int timeoutms)\n  {\n    int n;\n\n    do {\n\n      Integer tv;\n      if (timeoutms != -1) {\n        tv = new Integer(timeoutms);\n      } else {\n        tv = null;\n      }\n\n      try {\n        n = fd.select(SelectionKey.OP_WRITE, tv);\n      } catch (java.lang.Exception e) {\n        System.out.println(e.toString());\n        throw new Exception(e.getMessage());\n      }\n\n    } while (n < 0);\n\n    if (n == 0) return 0;\n\n    try {\n      n = fd.write(ByteBuffer.wrap(data, dataPtr, length), length);\n    } catch (java.lang.Exception e) {\n      throw new Exception(e.getMessage());\n    }\n\n    lastWrite = System.currentTimeMillis();\n\n    return n;\n  }\n\n  public FileDescriptor getFd() {\n    return fd;\n  }\n\n  public void setFd(FileDescriptor fd_) {\n    fd = fd_;\n  }\n\n  public int getBufSize() {\n    return bufSize;\n  }\n\n  protected FileDescriptor fd;\n  protected boolean blocking;\n  protected int timeoutms;\n  protected int start;\n  protected int sentUpTo;\n  protected int offset;\n  protected int bufSize;\n  private long lastWrite;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/InStream.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// rdr::InStream marshalls data from a buffer stored in RDR (RFB Data\n// Representation).\n//\n\npackage com.tigervnc.rdr;\n\nimport java.nio.*;\n\nimport com.tigervnc.network.*;\n\nabstract public class InStream {\n\n  // check() ensures there is buffer data for at least one item of size\n  // itemSize bytes.  Returns the number of items in the buffer (up to a\n  // maximum of nItems).\n\n  public int check(int itemSize, int nItems, boolean wait) {\n    int nAvail;\n\n    if (itemSize > (end - ptr))\n        return overrun(itemSize, nItems, wait);\n\n    nAvail = (end - ptr) / itemSize;\n    if (nAvail < nItems)\n      return nAvail;\n\n    return nItems;\n  }\n\n  public int check(int itemSize, int nItems) { return check(itemSize, nItems, true); }\n  public int check(int itemSize) { return check(itemSize, 1); }\n\n  // checkNoWait() tries to make sure that the given number of bytes can\n  // be read without blocking.  It returns true if this is the case, false\n  // otherwise.  The length must be \"small\" (less than the buffer size).\n\n  public final boolean checkNoWait(int length) { return check(length, 1, false)!=0; }\n\n  // readU/SN() methods read unsigned and signed N-bit integers.\n\n  public final int readS8()  { check(1); return b[ptr++]; }\n  public final int readS16() { check(2); int b0 = b[ptr++];\n                               int b1 = b[ptr++] & 0xff; return b0 << 8 | b1; }\n  public final int readS32() { check(4); int b0 = b[ptr++];\n                               int b1 = b[ptr++] & 0xff;\n                               int b2 = b[ptr++] & 0xff;\n                               int b3 = b[ptr++] & 0xff;\n                               return b0 << 24 | b1 << 16 | b2 << 8 | b3; }\n\n  public final int readU8()  { return readS8()  & 0xff;  }\n  public final int readU16() { return readS16() & 0xffff; }\n  public final int readU32() { return readS32() & 0xffffffff; }\n\n  // readString() reads a string - a U32 length followed by the data.\n\n  public final String readString() {\n    int len = readU32();\n    if (len > maxStringLength)\n      throw new Exception(\"InStream max string length exceeded\");\n\n    ByteBuffer str = ByteBuffer.allocate(len);\n    readBytes(str, len);\n    String utf8string = new String();\n    try {\n      utf8string = new String(str.array(),\"UTF8\");\n    } catch(java.io.UnsupportedEncodingException e) {\n      e.printStackTrace();\n    }\n    return utf8string;\n  }\n\n  // maxStringLength protects against allocating a huge buffer.  Set it\n  // higher if you need longer strings.\n\n  public static int maxStringLength = 65535;\n\n  public final void skip(int bytes) {\n    while (bytes > 0) {\n      int n = check(1, bytes);\n      ptr += n;\n      bytes -= n;\n    }\n  }\n\n  // readBytes() reads an exact number of bytes\n\n  public void readBytes(ByteBuffer data, int length) {\n    while (length > 0) {\n      int n = check(1, length);\n      data.put(b, ptr, n);\n      ptr += n;\n      length -= n;\n    }\n  }\n\n  // readOpaqueN() reads a quantity \"without byte-swapping\".  Because java has\n  // no byte-ordering, we just use big-endian.\n\n  public final int readOpaque8()  { return readU8(); }\n  public final int readOpaque16() { return readU16(); }\n  public final int readOpaque32() { return readU32(); }\n\n  // pos() returns the position in the stream.\n\n  abstract public int pos();\n\n  // bytesAvailable() returns true if at least one byte can be read from the\n  // stream without blocking.  i.e. if false is returned then readU8() would\n  // block.\n\n  public boolean bytesAvailable() { return end != ptr; }\n\n  // getbuf(), getptr(), getend() and setptr() are \"dirty\" methods which allow\n  // you to manipulate the buffer directly.  This is useful for a stream which\n  // is a wrapper around an underlying stream.\n\n  public final byte[] getbuf() { return b; }\n  public final int getptr() { return ptr; }\n  public final int getend() { return end; }\n  public final void setptr(int p) { ptr = p; }\n\n  // overrun() is implemented by a derived class to cope with buffer overrun.\n  // It ensures there are at least itemSize bytes of buffer data.  Returns\n  // the number of items in the buffer (up to a maximum of nItems).  itemSize\n  // is supposed to be \"small\" (a few bytes).\n\n  abstract protected int overrun(int itemSize, int nItems, boolean wait);\n  protected int overrun(int itemSize, int nItems) {\n    return overrun(itemSize, nItems, true);\n  }\n\n  protected InStream() {}\n  protected byte[] b;\n  protected int ptr;\n  protected int end;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/MemInStream.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\npublic class MemInStream extends InStream {\n\n  public MemInStream(byte[] data, int offset, int len) {\n    b = data;\n    start = offset;\n    ptr = start;\n    end = start + len;\n  }\n\n  public int pos() { return ptr; }\n  public void reposition(int pos) { ptr = start + pos; }\n\n  protected int overrun(int itemSize, int nItems, boolean wait) {\n    throw new EndOfStream();\n  }\n\n  int start;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/MemOutStream.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// A MemOutStream grows as needed when data is written to it.\n//\n\npackage com.tigervnc.rdr;\n\npublic class MemOutStream extends OutStream {\n\n  public MemOutStream(int len) {\n    b = new byte[len];\n    ptr = 0;\n    end = len;\n  }\n  public MemOutStream() { this(1024); }\n\n  public int length() { return ptr; }\n  public void clear() { ptr = 0; };\n  public void reposition(int pos) { ptr = pos; }\n\n  // data() returns a pointer to the buffer.\n\n  public final byte[] data() { return b; }\n\n  // overrun() either doubles the buffer or adds enough space for nItems of\n  // size itemSize bytes.\n\n  protected int overrun(int itemSize, int nItems) {\n    int len = ptr + itemSize * nItems;\n    if (len < end * 2)\n      len = end * 2;\n\n    if (len < end)\n      throw new Exception(\"Overflow in MemOutStream::overrun()\");\n\n    byte[] newBuf = new byte[len];\n    System.arraycopy(b, 0, newBuf, 0, ptr);\n    b = newBuf;\n    end = len;\n\n    return nItems;\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/OutStream.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// rdr::OutStream marshalls data into a buffer stored in RDR (RFB Data\n// Representation).\n//\n\npackage com.tigervnc.rdr;\n\nimport java.nio.*;\n\nimport com.tigervnc.network.*;\n\nabstract public class OutStream {\n\n  // check() ensures there is buffer space for at least one item of size\n  // itemSize bytes.  Returns the number of items which fit (up to a maximum\n  // of nItems).\n\n  public final int check(int itemSize, int nItems) {\n    int nAvail;\n\n    if (itemSize > (end - ptr))\n      return overrun(itemSize, nItems);\n\n    nAvail = (end - ptr) / itemSize;\n    if (nAvail < nItems)\n      return nAvail;\n\n    return nItems;\n  }\n\n  public final void check(int itemSize) {\n    if (ptr + itemSize > end)\n      overrun(itemSize, 1);\n  }\n\n  // writeU/SN() methods write unsigned and signed N-bit integers.\n\n  public final void writeU8( int u) { check(1); b[ptr++] = (byte)u; }\n  public final void writeU16(int u) { check(2); b[ptr++] = (byte)(u >> 8);\n                                      b[ptr++] = (byte)u; }\n  public final void writeU32(int u) { check(4); b[ptr++] = (byte)(u >> 24);\n                                      b[ptr++] = (byte)(u >> 16);\n                                      b[ptr++] = (byte)(u >> 8);\n                                      b[ptr++] = (byte)u; }\n\n  public final void writeS8( int s) { writeU8( s); }\n  public final void writeS16(int s) { writeU16(s); }\n  public final void writeS32(int s) { writeU32(s); }\n\n  // writeCompactLength() writes 1..3 bytes representing length of the data\n  // following.  This method is used by the Tight encoder.\n\n  public final void writeCompactLength(int len) {\n    byte b = (byte)(len & 0x7F);\n    if (len <= 0x7F) {\n      writeU8(b);\n    } else {\n      writeU8(b | 0x80);\n      b = (byte)(len >> 7 & 0x7F);\n      if (len <= 0x3FFF) {\n        writeU8(b);\n      } else {\n        writeU8(b | 0x80);\n        writeU8(len >> 14 & 0xFF);\n      }\n    }\n  }\n\n  // writeString() writes a string - a U32 length followed by the data.\n\n  public final void writeString(String str) {\n    int len = str.length();\n    writeU32(len);\n    try {\n      byte[] utf8str = str.getBytes(\"UTF8\");\n      writeBytes(utf8str, 0, len);\n    } catch(java.io.UnsupportedEncodingException e) {\n      e.printStackTrace();\n    }\n  }\n\n  public final void pad(int bytes) {\n    while (bytes-- > 0) writeU8(0);\n  }\n\n  public final void skip(int bytes) {\n    while (bytes > 0) {\n      int n = check(1, bytes);\n      ptr += n;\n      bytes -= n;\n    }\n  }\n\n  // writeBytes() writes an exact number of bytes from an array at an offset.\n\n  public void writeBytes(byte[] data, int dataPtr, int length) {\n    int dataEnd = dataPtr + length;\n    while (dataPtr < dataEnd) {\n      int n = check(1, dataEnd - dataPtr);\n      System.arraycopy(data, dataPtr, b, ptr, n);\n      ptr += n;\n      dataPtr += n;\n    }\n  }\n\n  public void writeBytes(ByteBuffer data, int length) {\n    while (length > 0) {\n      int n = check(1, length);\n      data.get(b, ptr, n);\n      ptr += n;\n      length -= n;\n    }\n  }\n\n  // copyBytes() efficiently transfers data between streams\n\n  public void copyBytes(InStream is, int length) {\n    while (length > 0) {\n      int n = check(1, length);\n      is.readBytes(ByteBuffer.wrap(b, ptr, n), n);\n      ptr += n;\n      length -= n;\n    }\n  }\n\n  // writeOpaqueN() writes a quantity without byte-swapping.  Because java has\n  // no byte-ordering, we just use big-endian.\n\n  public final void writeOpaque8( int u) { writeU8( u); }\n  public final void writeOpaque16(int u) { writeU16(u); }\n  public final void writeOpaque32(int u) { writeU32(u); }\n  public final void writeOpaque24A(int u) { check(3);\n                                            b[ptr++] = (byte)(u >> 24);\n                                            b[ptr++] = (byte)(u >> 16);\n                                            b[ptr++] = (byte)(u >> 8); }\n  public final void writeOpaque24B(int u) { check(3);\n                                            b[ptr++] = (byte)(u >> 16);\n                                            b[ptr++] = (byte)(u >> 8);\n                                            b[ptr++] = (byte)u; }\n\n  // length() returns the length of the stream.\n\n  abstract public int length();\n\n  // flush() requests that the stream be flushed.\n\n  public void flush() {}\n\n  // getptr(), getend() and setptr() are \"dirty\" methods which allow you to\n  // manipulate the buffer directly.  This is useful for a stream which is a\n  // wrapper around an underlying stream.\n\n  public final byte[] getbuf() { return b; }\n  public final int getptr() { return ptr; }\n  public final int getend() { return end; }\n  public final void setptr(int p) { ptr = p; }\n\n  // overrun() is implemented by a derived class to cope with buffer overrun.\n  // It ensures there are at least itemSize bytes of buffer space.  Returns\n  // the number of items which fit (up to a maximum of nItems).  itemSize is\n  // supposed to be \"small\" (a few bytes).\n\n  abstract protected int overrun(int itemSize, int nItems);\n\n  protected OutStream() {}\n  protected byte[] b;\n  protected int ptr;\n  protected int end;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/SystemException.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\npublic class SystemException extends Exception {\n  public SystemException(String s) {\n    super(s);\n  }\n}\n\n"
  },
  {
    "path": "java/com/tigervnc/rdr/TLSException.java",
    "content": "/*\n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2011 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\nclass TLSException extends Exception {\n  public TLSException(String s, int n) {\n    // FIXME: append enumerated n\n    super(s);\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/TLSInStream.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\nimport java.nio.ByteBuffer;\nimport java.nio.channels.*;\nimport javax.net.ssl.*;\n\nimport com.tigervnc.network.*;\n\npublic class TLSInStream extends InStream {\n\n  static final int defaultBufSize = 16384;\n\n  public TLSInStream(InStream _in, SSLEngineManager _manager) {\n    in = (FdInStream)_in;\n    manager = _manager;\n    offset = 0;\n    SSLSession session = manager.getSession();\n    bufSize = session.getApplicationBufferSize();\n    b = new byte[bufSize];\n    ptr = end = start = 0;\n  }\n\n  public final int pos() {\n    return offset + ptr - start;\n  }\n\n  public final void startTiming() {\n    in.startTiming();\n  }\n\n  public final void stopTiming() {\n    in.stopTiming();\n  }\n\n  public final long kbitsPerSecond() {\n    return in.kbitsPerSecond();\n  }\n\n  public final long timeWaited() {\n    return in.timeWaited();\n  }\n\n  protected final int overrun(int itemSize, int nItems, boolean wait) {\n    if (itemSize > bufSize)\n      throw new Exception(\"TLSInStream overrun: max itemSize exceeded\");\n\n    if (end - ptr != 0)\n      System.arraycopy(b, ptr, b, 0, end - ptr);\n\n    offset += ptr - start;\n    end -= ptr - start;\n    ptr = start;\n\n    while ((end - start) < itemSize) {\n      int n = readTLS(b, end, start + bufSize - end, wait);\n      if (!wait && n == 0)\n        return 0;\n      end += n;\n    }\n\n    int nAvail;\n    nAvail = (end - ptr) / itemSize;\n    if (nAvail < nItems)\n      return nAvail;\n\n    return nItems;\n  }\n\n  protected int readTLS(byte[] buf, int bufPtr, int len, boolean wait)\n  {\n    int n = -1;\n\n    try {\n      n = manager.read(ByteBuffer.wrap(buf, bufPtr, len), len);\n    } catch (java.io.IOException e) {\n      e.printStackTrace();\n    }\n\n    if (n < 0) throw new TLSException(\"readTLS\", n);\n\n    return n;\n  }\n\n  private SSLEngineManager manager;\n  private int offset;\n  private int start;\n  private int bufSize;\n  private FdInStream in;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/TLSOutStream.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\nimport java.nio.ByteBuffer;\nimport java.nio.channels.*;\nimport javax.net.ssl.*;\n\nimport com.tigervnc.network.*;\n\npublic class TLSOutStream extends OutStream {\n\n  static final int defaultBufSize = 16384;\n\n  public TLSOutStream(OutStream _out, SSLEngineManager _manager) {\n    manager = _manager;\n    out = (FdOutStream)_out;\n    SSLSession session = manager.getSession();\n    bufSize = session.getApplicationBufferSize();\n    b = new byte[bufSize];\n    ptr = offset = start = 0;\n    end = start + bufSize;\n  }\n\n  public int length()\n  {\n    return offset + ptr - start;\n  }\n\n  public void flush()\n  {\n    int sentUpTo = start;\n    while (sentUpTo < ptr) {\n      int n = writeTLS(b, sentUpTo, ptr - sentUpTo);\n      sentUpTo += n;\n      offset += n;\n    }\n\n    ptr = start;\n  }\n\n  protected int overrun(int itemSize, int nItems)\n  {\n    if (itemSize > bufSize)\n      throw new Exception(\"TLSOutStream overrun: max itemSize exceeded\");\n\n    flush();\n\n    int nAvail;\n    nAvail = (end - ptr) / itemSize;\n    if (nAvail < nItems)\n      return nAvail;\n\n    return nItems;\n  }\n\n  protected int writeTLS(byte[] data, int dataPtr, int length)\n  {\n    int n = 0;\n\n    try {\n      n = manager.write(ByteBuffer.wrap(data, dataPtr, length), length);\n    } catch (java.io.IOException e) {\n      throw new Exception(e.getMessage());\n    }\n\n    return n;\n  }\n\n  private SSLEngineManager manager;\n  private FdOutStream out;\n  private int start;\n  private int offset;\n  private int bufSize;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/TimedOut.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\nclass TimedOut extends Exception {\n  public TimedOut() {\n    super(\"Timed out\");\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/WarningException.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 Brian P. Hinz\n * Copyright (C) 2012 D. R. Commander.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rdr;\n\n/* We use this to communicate exceptions that are generally the result of user\n   actions. */\n\npublic class WarningException extends RuntimeException {\n  public WarningException(String s) {\n    super(s);\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rdr/ZlibInStream.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// A ZlibInStream reads from a zlib.io.InputStream\n//\n\npackage com.tigervnc.rdr;\nimport com.jcraft.jzlib.*;\n\npublic class ZlibInStream extends InStream {\n\n  static final int defaultBufSize = 16384;\n\n  public ZlibInStream(int bufSize_)\n  {\n    bufSize = bufSize_;\n    b = new byte[bufSize];\n    bytesIn = offset = 0;\n    ptr = end = start = 0;\n    init();\n  }\n\n  public ZlibInStream() { this(defaultBufSize); }\n\n  public void setUnderlying(InStream is, int bytesIn_)\n  {\n    underlying = is;\n    bytesIn = bytesIn_;\n    ptr = end = start;\n  }\n\n  public int pos()\n  {\n    return offset + ptr - start;\n  }\n\n  public void flushUnderlying()\n  {\n    ptr = end = start;\n\n    while (bytesIn > 0) {\n      decompress(true);\n      end = start; // throw away any data\n    }\n\n    setUnderlying(null, 0);\n  }\n\n  public void reset()\n  {\n    deinit();\n    init();\n  }\n\n  public void init()\n  {\n    assert(zs == null);\n\n    zs = new ZStream();\n    zs.next_in = null;\n    zs.next_in_index = 0;\n    zs.avail_in = 0;\n    if (zs.inflateInit() != JZlib.Z_OK) {\n      zs = null;\n      throw new Exception(\"ZlinInStream: inflateInit failed\");\n    }\n  }\n\n  public void deinit()\n  {\n    assert(zs != null);\n    setUnderlying(null, 0);\n    zs.inflateEnd();\n    zs = null;\n  }\n\n  protected int overrun(int itemSize, int nItems, boolean wait)\n  {\n    if (itemSize > bufSize)\n      throw new Exception(\"ZlibInStream overrun: max itemSize exceeded\");\n\n    if (end - ptr != 0)\n      System.arraycopy(b, ptr, b, start, end - ptr);\n\n    offset += ptr - start;\n    end -= ptr - start;\n    ptr = start;\n\n    while (end - ptr < itemSize) {\n      if (!decompress(wait))\n        return 0;\n    }\n\n    int nAvail;\n    nAvail = (end - ptr) / itemSize;\n    if (nAvail < nItems)\n      return nAvail;\n\n    return nItems;\n  }\n\n  // decompress() calls the decompressor once.  Note that this won't\n  // necessarily generate any output data - it may just consume some input\n  // data.  Returns false if wait is false and we would block on the underlying\n  // stream.\n\n  private boolean decompress(boolean wait)\n  {\n    if (underlying == null)\n      throw new Exception(\"ZlibInStream overrun: no underlying stream\");\n\n    zs.next_out = b;\n    zs.next_out_index = end;\n    zs.avail_out = start + bufSize - end;\n\n    int n = underlying.check(1, 1, wait);\n    if (n == 0) return false;\n    zs.next_in = underlying.getbuf();\n    zs.next_in_index = underlying.getptr();\n    zs.avail_in = underlying.getend() - underlying.getptr();\n    if (zs.avail_in > bytesIn)\n      zs.avail_in = bytesIn;\n\n    int rc = zs.inflate(JZlib.Z_SYNC_FLUSH);\n    if (rc != JZlib.Z_OK) {\n      throw new Exception(\"ZlibInStream: inflate failed\");\n    }\n\n    bytesIn -= zs.next_in_index - underlying.getptr();\n    end = zs.next_out_index;\n    underlying.setptr(zs.next_in_index);\n    return true;\n  }\n\n  private InStream underlying;\n  private int bufSize;\n  private int offset;\n  private com.jcraft.jzlib.ZStream zs;\n  private int bytesIn;\n  private int start;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/AliasParameter.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2004-2005 Cendio AB.\n * Copyright 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class AliasParameter extends VoidParameter {\n  public AliasParameter(String name_, String desc_, VoidParameter param_,\n                        Configuration.ConfigurationObject co)\n  {\n    super(name_, desc_, co);\n    param = param_;\n  }\n\n  public AliasParameter(String name_, String desc_, VoidParameter param_) {\n    this(name_, desc_, param_, Configuration.ConfigurationObject.ConfGlobal);\n  }\n\n  public boolean setParam(String v) { return param.setParam(v); }\n  public boolean setParam() { return param.setParam(); }\n\n  public String getDefaultStr() { return param.getDefaultStr(); }\n  public String getValueStr() { return param.getValueStr(); }\n  public boolean isBool() { return param.isBool(); }\n\n  public void setImmutable() {\n    vlog.debug(\"Set immutable \"+getName()+\" (Alias)\");\n    param.setImmutable();\n  }\n\n  public void setHasBeenSet() {\n    param.setHasBeenSet();\n  }\n\n  public boolean hasBeenSet() {\n    return param.hasBeenSet();\n  }\n\n  protected VoidParameter param;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/AuthFailureException.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class AuthFailureException extends Exception {\n  public AuthFailureException() { super(\"Authentication failure\"); }\n  public AuthFailureException(String reason) {\n    super(\"Authentication failure: \"+reason);\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/BoolParameter.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2004-2005 Cendio AB.\n * Copyright 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class BoolParameter extends VoidParameter {\n  public BoolParameter(String name_, String desc_, boolean v,\n                       Configuration.ConfigurationObject co)\n  {\n    super(name_, desc_, co);\n    value = v;\n    defValue = v;\n  }\n\n  public BoolParameter(String name_, String desc_, boolean v) {\n    this(name_, desc_, v, Configuration.ConfigurationObject.ConfGlobal);\n  }\n\n  public boolean setParam(String v) {\n    if (immutable) return true;\n\n    if (v == null || v.equals(\"1\") || v.equalsIgnoreCase(\"on\") ||\n        v.equalsIgnoreCase(\"true\") || v.equalsIgnoreCase(\"yes\"))\n      value = true;\n    else if (v.equals(\"0\") || v.equalsIgnoreCase(\"off\") ||\n        v.equalsIgnoreCase(\"false\") || v.equalsIgnoreCase(\"no\"))\n      value = false;\n    else {\n      vlog.error(\"Bool parameter \"+getName()+\": invalid value '\"+v+\"'\");\n      return false;\n    }\n    return true;\n  }\n\n  public boolean setParam() { setParam(true); return true; }\n  public void setParam(boolean b) {\n    if (immutable) return;\n    value = b;\n  }\n\n  public String getDefaultStr() { return defValue ? \"1\" : \"0\"; }\n  public String getValueStr() { return value ? \"1\" : \"0\"; }\n  public boolean isBool() { return true; }\n\n  final public boolean getValue() { return value; }\n\n  protected boolean value;\n  protected boolean defValue;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CConnection.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.awt.color.*;\nimport java.awt.image.*;\nimport java.nio.*;\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport com.tigervnc.network.*;\nimport com.tigervnc.rdr.*;\n\nabstract public class CConnection extends CMsgHandler {\n\n  static LogWriter vlog = new LogWriter(\"CConnection\");\n\n  private static final String osName = \n    System.getProperty(\"os.name\").toLowerCase(Locale.ENGLISH);\n\n  public CConnection()\n  {\n    super();\n    csecurity = null;\n    supportsLocalCursor = false; supportsDesktopResize = false;\n    is = null; os = null; reader_ = null; writer_ = null;\n    shared = false;\n    state_ = stateEnum.RFBSTATE_UNINITIALISED;\n    pendingPFChange = false; preferredEncoding = Encodings.encodingTight;\n    compressLevel = 2; qualityLevel = -1;\n    formatChange = false; encodingChange = false;\n    firstUpdate = true; pendingUpdate = false; continuousUpdates = false;\n    forceNonincremental = true;\n    framebuffer = null; decoder = new DecodeManager(this);\n    security = new SecurityClient();\n  }\n\n  // Methods to initialise the connection\n\n  // setServerName() is used to provide a unique(ish) name for the server to\n  // which we are connected.  This might be the result of getPeerEndpoint on\n  // a TcpSocket, for example, or a host specified by DNS name & port.\n  // The serverName is used when verifying the Identity of a host (see RA2).\n  public void setServerName(String name_) { serverName = name_; }\n\n  public void setServerPort(int port_) { serverPort = port_; }\n\n  // setStreams() sets the streams to be used for the connection.  These must\n  // be set before initialiseProtocol() and processMsg() are called.  The\n  // CSecurity object may call setStreams() again to provide alternative\n  // streams over which the RFB protocol is sent (i.e. encrypting/decrypting\n  // streams).  Ownership of the streams remains with the caller\n  // (i.e. SConnection will not delete them).\n  public final void setStreams(InStream is_, OutStream os_)\n  {\n    is = is_;\n    os = os_;\n  }\n\n  // setShared sets the value of the shared flag which will be sent to the\n  // server upon initialisation.\n  public final void setShared(boolean s) { shared = s; }\n\n  // setFramebuffer configures the PixelBuffer that the CConnection\n  // should render all pixel data in to. Note that the CConnection\n  // takes ownership of the PixelBuffer and it must not be deleted by\n  // anyone else. Call setFramebuffer again with NULL or a different\n  // PixelBuffer to delete the previous one.\n  public void setFramebuffer(ModifiablePixelBuffer fb)\n  {\n    decoder.flush();\n\n    if (fb != null) {\n      assert(fb.width() == server.width());\n      assert(fb.height() == server.height());\n    }\n\n    if ((framebuffer != null) && (fb != null)) {\n      Rect rect = new Rect();\n\n      Raster data;\n\n      byte[] black = new byte[4];\n\n      // Copy still valid area\n\n      rect.setXYWH(0, 0,\n                   Math.min(fb.width(), framebuffer.width()),\n                   Math.min(fb.height(), framebuffer.height()));\n      data = framebuffer.getBuffer(rect);\n      fb.imageRect(framebuffer.getPF(), rect, data);\n\n      // Black out any new areas\n\n      if (fb.width() > framebuffer.width()) {\n        rect.setXYWH(framebuffer.width(), 0,\n                     fb.width() - framebuffer.width(),\n                     fb.height());\n        fb.fillRect(rect, black);\n      }\n\n      if (fb.height() > framebuffer.height()) {\n        rect.setXYWH(0, framebuffer.height(),\n                     fb.width(),\n                     fb.height() - framebuffer.height());\n        fb.fillRect(rect, black);\n      }\n    }\n\n    framebuffer = fb;\n  }\n\n  // initialiseProtocol() should be called once the streams and security\n  // types are set.  Subsequently, processMsg() should be called whenever\n  // there is data to read on the InStream.\n  public final void initialiseProtocol()\n  {\n    state_ = stateEnum.RFBSTATE_PROTOCOL_VERSION;\n  }\n\n  // processMsg() should be called whenever there is data to read on the\n  // InStream.  You must have called initialiseProtocol() first.\n  public void processMsg()\n  {\n    switch (state_) {\n\n    case RFBSTATE_PROTOCOL_VERSION: processVersionMsg();        break;\n    case RFBSTATE_SECURITY_TYPES:   processSecurityTypesMsg();  break;\n    case RFBSTATE_SECURITY:         processSecurityMsg();       break;\n    case RFBSTATE_SECURITY_RESULT:  processSecurityResultMsg(); break;\n    case RFBSTATE_INITIALISATION:   processInitMsg();           break;\n    case RFBSTATE_NORMAL:           reader_.readMsg();          break;\n    case RFBSTATE_UNINITIALISED:\n      throw new Exception(\"CConnection.processMsg: not initialised yet?\");\n    default:\n      throw new Exception(\"CConnection.processMsg: invalid state\");\n    }\n  }\n\n  private void processVersionMsg()\n  {\n    ByteBuffer verStr = ByteBuffer.allocate(12);\n    int majorVersion;\n    int minorVersion;\n\n    vlog.debug(\"Reading protocol version\");\n\n    if (!is.checkNoWait(12))\n      return;\n\n    is.readBytes(verStr, 12);\n\n    if ((new String(verStr.array())).matches(\"RFB \\\\d{3}\\\\.\\\\d{3}\\\\n\")) {\n      majorVersion =\n        Integer.parseInt((new String(verStr.array())).substring(4,7));\n      minorVersion =\n        Integer.parseInt((new String(verStr.array())).substring(8,11));\n    } else {\n      state_ = stateEnum.RFBSTATE_INVALID;\n      throw new Exception(\"reading version failed: not an RFB server?\");\n    }\n\n    server.setVersion(majorVersion, minorVersion);\n\n    vlog.info(\"Server supports RFB protocol version \"\n              +server.majorVersion+\".\"+ server.minorVersion);\n\n    // The only official RFB protocol versions are currently 3.3, 3.7 and 3.8\n    if (server.beforeVersion(3,3)) {\n      String msg = (\"Server gave unsupported RFB protocol version \"+\n                    server.majorVersion+\".\"+server.minorVersion);\n      vlog.error(msg);\n      state_ = stateEnum.RFBSTATE_INVALID;\n      throw new Exception(msg);\n    } else if (server.beforeVersion(3,7)) {\n      server.setVersion(3,3);\n    } else if (server.afterVersion(3,8)) {\n      server.setVersion(3,8);\n    }\n\n    verStr.clear();\n    verStr.put(String.format(\"RFB %03d.%03d\\n\",\n               server.majorVersion, server.minorVersion).getBytes()).flip();\n    os.writeBytes(verStr.array(), 0, 12);\n    os.flush();\n\n    state_ = stateEnum.RFBSTATE_SECURITY_TYPES;\n\n    vlog.info(\"Using RFB protocol version \"+\n              server.majorVersion+\".\"+server.minorVersion);\n  }\n\n  private void processSecurityTypesMsg()\n  {\n    vlog.debug(\"Processing security types message\");\n\n    int secType = Security.secTypeInvalid;\n\n    List<Integer> secTypes = new ArrayList<Integer>();\n    secTypes = security.GetEnabledSecTypes();\n\n    if (server.isVersion(3,3)) {\n\n      // legacy 3.3 server may only offer \"vnc authentication\" or \"none\"\n\n      secType = is.readU32();\n      if (secType == Security.secTypeInvalid) {\n        throwConnFailedException();\n\n      } else if (secType == Security.secTypeNone || secType == Security.secTypeVncAuth) {\n        Iterator<Integer> i;\n        for (i = secTypes.iterator(); i.hasNext(); ) {\n          int refType = (Integer)i.next();\n          if (refType == secType) {\n            secType = refType;\n            break;\n          }\n        }\n\n        if (!secTypes.contains(secType))\n          secType = Security.secTypeInvalid;\n      } else {\n        vlog.error(\"Unknown 3.3 security type \"+secType);\n        throw new Exception(\"Unknown 3.3 security type\");\n      }\n\n    } else {\n\n      // 3.7 server will offer us a list\n\n      int nServerSecTypes = is.readU8();\n      if (nServerSecTypes == 0)\n        throwConnFailedException();\n\n      Iterator<Integer> j;\n\n      for (int i = 0; i < nServerSecTypes; i++) {\n        int serverSecType = is.readU8();\n        vlog.debug(\"Server offers security type \"+\n                   Security.secTypeName(serverSecType)+\"(\"+serverSecType+\")\");\n\n        /*\n        * Use the first type sent by server which matches client's type.\n        * It means server's order specifies priority.\n        */\n        if (secType == Security.secTypeInvalid) {\n          for (j = secTypes.iterator(); j.hasNext(); ) {\n            int refType = (Integer)j.next();\n            if (refType == serverSecType) {\n              secType = refType;\n              break;\n            }\n          }\n        }\n      }\n\n      // Inform the server of our decision\n      if (secType != Security.secTypeInvalid) {\n        os.writeU8(secType);\n        os.flush();\n        vlog.debug(\"Choosing security type \"+Security.secTypeName(secType)+\n                   \"(\"+secType+\")\");\n      }\n    }\n\n    if (secType == Security.secTypeInvalid) {\n      state_ = stateEnum.RFBSTATE_INVALID;\n      vlog.error(\"No matching security types\");\n      throw new Exception(\"No matching security types\");\n    }\n\n    state_ = stateEnum.RFBSTATE_SECURITY;\n    csecurity = security.GetCSecurity(secType);\n    processSecurityMsg();\n  }\n\n  private void processSecurityMsg() {\n    vlog.debug(\"Processing security message\");\n    if (csecurity.processMsg(this)) {\n      state_ = stateEnum.RFBSTATE_SECURITY_RESULT;\n      processSecurityResultMsg();\n    }\n  }\n\n  private void processSecurityResultMsg() {\n    vlog.debug(\"Processing security result message\");\n    int result;\n    if (server.beforeVersion(3,8) && csecurity.getType() == Security.secTypeNone) {\n      result = Security.secResultOK;\n    } else {\n      if (!is.checkNoWait(1)) return;\n      result = is.readU32();\n    }\n    switch (result) {\n    case Security.secResultOK:\n      securityCompleted();\n      return;\n    case Security.secResultFailed:\n      vlog.debug(\"Auth failed\");\n      break;\n    case Security.secResultTooMany:\n      vlog.debug(\"Auth failed: Too many tries\");\n      break;\n    default:\n      throw new Exception(\"Unknown security result from server\");\n    }\n    state_ = stateEnum.RFBSTATE_INVALID;\n    if (server.beforeVersion(3,8))\n      throw new AuthFailureException();\n    String reason = is.readString();\n    throw new AuthFailureException(reason);\n  }\n\n  private void processInitMsg() {\n    vlog.debug(\"Reading server initialisation\");\n    reader_.readServerInit();\n  }\n\n  private void throwConnFailedException() {\n    state_ = stateEnum.RFBSTATE_INVALID;\n    String reason;\n    reason = is.readString();\n    throw new ConnFailedException(reason);\n  }\n\n  private void securityCompleted() {\n    state_ = stateEnum.RFBSTATE_INITIALISATION;\n    reader_ = new CMsgReader(this, is);\n    writer_ = new CMsgWriter(server, os);\n    vlog.debug(\"Authentication success!\");\n    authSuccess();\n    writer_.writeClientInit(shared);\n  }\n\n  // Methods overridden from CMsgHandler\n\n  // Note: These must be called by any deriving classes\n\n  public void setDesktopSize(int w, int h) {\n    decoder.flush();\n\n    super.setDesktopSize(w,h);\n\n    if (continuousUpdates)\n      writer().writeEnableContinuousUpdates(true, 0, 0,\n                                            server.width(),\n                                            server.height());\n\n    resizeFramebuffer();\n    assert(framebuffer != null);\n    assert(framebuffer.width() == server.width());\n    assert(framebuffer.height() == server.height());\n  }\n\n  public void setExtendedDesktopSize(int reason,\n                                     int result,\n                                     int w, int h,\n                                     ScreenSet layout) {\n    decoder.flush();\n\n    super.setExtendedDesktopSize(reason, result, w, h, layout);\n\n    if (continuousUpdates)\n      writer().writeEnableContinuousUpdates(true, 0, 0,\n                                            server.width(),\n                                            server.height());\n\n    resizeFramebuffer();\n    assert(framebuffer != null);\n    assert(framebuffer.width() == server.width());\n    assert(framebuffer.height() == server.height());\n  }\n\n  public void endOfContinuousUpdates()\n  {\n    super.endOfContinuousUpdates();\n\n    // We've gotten the marker for a format change, so make the pending\n    // one active\n    if (pendingPFChange) {\n      server.setPF(pendingPF);\n      pendingPFChange = false;\n\n      // We might have another change pending\n      if (formatChange)\n        requestNewUpdate();\n    }\n  }\n  // serverInit() is called when the ServerInit message is received.  The\n  // derived class must call on to CConnection::serverInit().\n  public void serverInit(int width, int height,\n                         PixelFormat pf, String name)\n  {\n    super.serverInit(width, height, pf, name);\n    \n    state_ = stateEnum.RFBSTATE_NORMAL;\n    vlog.debug(\"Initialisation done\");\n\n    initDone();\n    assert(framebuffer != null);\n    // FIXME: even if the client is scaling?\n    assert(framebuffer.width() == server.width());\n    assert(framebuffer.height() == server.height());\n\n    // We want to make sure we call SetEncodings at least once\n    encodingChange = true;\n\n    requestNewUpdate();\n\n    // This initial update request is a bit of a corner case, so we need\n    // to help out setting the correct format here.\n    if (pendingPFChange) {\n      server.setPF(pendingPF);\n      pendingPFChange = false;\n    }\n  }\n\n  public void readAndDecodeRect(Rect r, int encoding,\n                                ModifiablePixelBuffer pb)\n  {\n    decoder.decodeRect(r, encoding, pb);\n    decoder.flush();\n  }\n\n  public void framebufferUpdateStart()\n  {\n    super.framebufferUpdateStart();\n\n    assert(framebuffer != null);\n\n    // Note: This might not be true if continuous updates are supported\n    pendingUpdate = false;\n\n    requestNewUpdate();\n  }\n\n  public void framebufferUpdateEnd()\n  {\n    decoder.flush();\n\n    super.framebufferUpdateEnd();\n\n    // A format change has been scheduled and we are now past the update\n    // with the old format. Time to active the new one.\n    if (pendingPFChange && !continuousUpdates) {\n      server.setPF(pendingPF);\n      pendingPFChange = false;\n    }\n\n    if (firstUpdate) {\n      if (server.supportsContinuousUpdates) {\n        vlog.info(\"Enabling continuous updates\");\n        continuousUpdates = true;\n        writer().writeEnableContinuousUpdates(true, 0, 0,\n                                              server.width(),\n                                              server.height());\n      }\n\n      firstUpdate = false;\n    }\n  }\n\n  public void dataRect(Rect r, int encoding)\n  {\n    decoder.decodeRect(r, encoding, framebuffer);\n  }\n\n  // Methods to be overridden in a derived class\n\n  // authSuccess() is called when authentication has succeeded.\n  public void authSuccess() { }\n\n  // initDone() is called when the connection is fully established\n  // and standard messages can be sent. This is called before the\n  // initial FramebufferUpdateRequest giving a derived class the\n  // chance to modify pixel format and settings. The derived class\n  // must also make sure it has provided a valid framebuffer before\n  // returning.\n  public void initDone() { }\n\n  // resizeFramebuffer() is called whenever the framebuffer\n  // dimensions or the screen layout changes. A subclass must make\n  // sure the pixel buffer has been updated once this call returns.\n  public void resizeFramebuffer()\n  {\n    assert(false);\n  }\n\n  // refreshFramebuffer() forces a complete refresh of the entire\n  // framebuffer\n  public void refreshFramebuffer()\n  {\n    forceNonincremental = true;\n\n    // Without fences, we cannot safely trigger an update request directly\n    // but must wait for the next update to arrive.\n    if (continuousUpdates)\n      requestNewUpdate();\n  }\n\n  // setPreferredEncoding()/getPreferredEncoding() adjusts which\n  // encoding is listed first as a hint to the server that it is the\n  // preferred one\n  public void setPreferredEncoding(int encoding)\n  {\n    if (preferredEncoding == encoding)\n      return;\n  \n    preferredEncoding = encoding;\n    encodingChange = true;\n  }\n  \n  public int getPreferredEncoding()\n  {\n    return preferredEncoding;\n  }\n  \n  // setCompressLevel()/setQualityLevel() controls the encoding hints\n  // sent to the server\n  public void setCompressLevel(int level)\n  {\n    if (compressLevel == level)\n      return;\n  \n    compressLevel = level;\n    encodingChange = true;\n  }\n  \n  public void setQualityLevel(int level)\n  {\n    if (qualityLevel == level)\n      return;\n  \n    qualityLevel = level;\n    encodingChange = true;\n  }\n\n  // setPF() controls the pixel format requested from the server.\n  // server.pf() will automatically be adjusted once the new format\n  // is active.\n  public void setPF(PixelFormat pf)\n  {\n    if (server.pf().equal(pf) && !formatChange)\n      return;\n\n    nextPF = pf;\n    formatChange = true;\n  }\n\n  public CMsgReader reader() { return reader_; }\n  public CMsgWriter writer() { return writer_; }\n\n  public InStream getInStream() { return is; }\n  public OutStream getOutStream() { return os; }\n\n  // Access method used by SSecurity implementations that can verify servers'\n  // Identities, to determine the unique(ish) name of the server.\n  public String getServerName() { return serverName; }\n  public int getServerPort() { return serverPort; }\n\n  boolean isSecure() { return csecurity != null ? csecurity.isSecure() : false; }\n\n  public enum stateEnum {\n    RFBSTATE_UNINITIALISED,\n    RFBSTATE_PROTOCOL_VERSION,\n    RFBSTATE_SECURITY_TYPES,\n    RFBSTATE_SECURITY,\n    RFBSTATE_SECURITY_RESULT,\n    RFBSTATE_INITIALISATION,\n    RFBSTATE_NORMAL,\n    RFBSTATE_INVALID\n  };\n\n  public stateEnum state() { return state_; }\n\n  protected void setState(stateEnum s) { state_ = s; }\n\n  protected void setReader(CMsgReader r) { reader_ = r; }\n  protected void setWriter(CMsgWriter w) { writer_ = w; }\n\n  protected ModifiablePixelBuffer getFramebuffer() { return framebuffer; }\n\n  public void fence(int flags, int len, byte[] data)\n  {\n    super.fence(flags, len, data);\n\n    if ((flags & fenceTypes.fenceFlagRequest) != 0)\n      return;\n\n    // We cannot guarantee any synchronisation at this level\n    flags = 0;\n\n    writer().writeFence(flags, len, data);\n  }\n\n  // requestNewUpdate() requests an update from the server, having set the\n  // format and encoding appropriately.\n  private void requestNewUpdate()\n  {\n    if (formatChange && !pendingPFChange) {\n      /* Catch incorrect requestNewUpdate calls */\n      assert(!pendingUpdate || continuousUpdates);\n\n      // We have to make sure we switch the internal format at a safe\n      // time. For continuous updates we temporarily disable updates and\n      // look for a EndOfContinuousUpdates message to see when to switch.\n      // For classical updates we just got a new update right before this\n      // function was called, so we need to make sure we finish that\n      // update before we can switch.\n\n      pendingPFChange = true;\n      pendingPF = nextPF;\n\n      if (continuousUpdates)\n        writer().writeEnableContinuousUpdates(false, 0, 0, 0, 0);\n\n      writer().writeSetPixelFormat(pendingPF);\n\n      if (continuousUpdates)\n        writer().writeEnableContinuousUpdates(true, 0, 0,\n                                              server.width(),\n                                              server.height());\n      formatChange = false;\n    }\n\n    if (encodingChange) {\n      updateEncodings();\n      encodingChange = false;\n    }\n\n    if (forceNonincremental || !continuousUpdates) {\n      pendingUpdate = true;\n      writer().writeFramebufferUpdateRequest(new Rect(0, 0,\n                                                      server.width(),\n                                                      server.height()),\n                                             !forceNonincremental);\n    }\n\n    forceNonincremental = false;\n  }\n\n  // Ask for encodings based on which decoders are supported.  Assumes higher\n  // encoding numbers are more desirable.\n\n  private void updateEncodings()\n  {\n    List<Integer> encodings = new ArrayList<Integer>();\n\n    if (server.supportsLocalCursor) {\n      // JRE on Windows does not support cursors with alpha\n      if (!osName.contains(\"windows\")) {\n        encodings.add(Encodings.pseudoEncodingCursorWithAlpha);\n        encodings.add(Encodings.pseudoEncodingVMwareCursor);\n      }\n      encodings.add(Encodings.pseudoEncodingCursor);\n      encodings.add(Encodings.pseudoEncodingXCursor);\n    }\n    if (server.supportsDesktopResize) {\n      encodings.add(Encodings.pseudoEncodingDesktopSize);\n      encodings.add(Encodings.pseudoEncodingExtendedDesktopSize);\n    }\n    if (server.supportsClientRedirect)\n      encodings.add(Encodings.pseudoEncodingClientRedirect);\n\n    encodings.add(Encodings.pseudoEncodingDesktopName);\n    encodings.add(Encodings.pseudoEncodingLastRect);\n    encodings.add(Encodings.pseudoEncodingContinuousUpdates);\n    encodings.add(Encodings.pseudoEncodingFence);\n\n    if (Decoder.supported(preferredEncoding)) {\n      encodings.add(preferredEncoding);\n    }\n\n    encodings.add(Encodings.encodingCopyRect);\n\n    for (int i = Encodings.encodingMax; i >= 0; i--) {\n      if ((i != preferredEncoding) && Decoder.supported(i))\n        encodings.add(i);\n    }\n\n    if (compressLevel >= 0 && compressLevel <= 9)\n      encodings.add(Encodings.pseudoEncodingCompressLevel0 + compressLevel);\n    if (qualityLevel >= 0 && qualityLevel <= 9)\n      encodings.add(Encodings.pseudoEncodingQualityLevel0 + qualityLevel);\n\n    writer().writeSetEncodings(encodings);\n  }\n\n  private void throwAuthFailureException() {\n    String reason;\n    vlog.debug(\"state=\"+state()+\", ver=\"+server.majorVersion+\".\"+server.minorVersion);\n    if (state() == stateEnum.RFBSTATE_SECURITY_RESULT && !server.beforeVersion(3,8)) {\n      reason = is.readString();\n    } else {\n      reason = \"Authentication failure\";\n    }\n    state_ = stateEnum.RFBSTATE_INVALID;\n    vlog.error(reason);\n    throw new AuthFailureException(reason);\n  }\n\n  public CSecurity csecurity;\n  public SecurityClient security;\n\n  protected boolean supportsLocalCursor;\n  protected boolean supportsDesktopResize;\n\n  private InStream is;\n  private OutStream os;\n  private CMsgReader reader_;\n  private CMsgWriter writer_;\n  private boolean deleteStreamsWhenDone;\n  private boolean shared;\n  private stateEnum state_;\n\n  private String serverName;\n  private int serverPort;\n\n  private boolean pendingPFChange;\n  private PixelFormat pendingPF;\n\n  private int preferredEncoding;\n  private int compressLevel;\n  private int qualityLevel;\n\n  private boolean formatChange;\n  private PixelFormat nextPF;\n  private boolean encodingChange;\n\n  private boolean firstUpdate;\n  private boolean pendingUpdate;\n  private boolean continuousUpdates;\n\n  private boolean forceNonincremental;\n\n  protected ModifiablePixelBuffer framebuffer;\n  private DecodeManager decoder;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CMsgHandler.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2011 Pierre Ossman for Cendio AB\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// CMsgHandler\n//\n\npackage com.tigervnc.rfb;\n\nabstract public class CMsgHandler {\n\n  static LogWriter vlog = new LogWriter(\"CMsgHandler\");\n\n  public CMsgHandler() {\n    server = new ServerParams();\n  }\n\n  public void setDesktopSize(int width, int height)\n  {\n    server.setDimensions(width, height);\n  }\n\n  public void setExtendedDesktopSize(int reason, int result,\n                                     int width, int height,\n                                     ScreenSet layout)\n  {\n    server.supportsSetDesktopSize = true;\n\n    if ((reason == screenTypes.reasonClient) && (result != screenTypes.resultSuccess))\n      return;\n\n    server.setDimensions(width, height, layout);\n  }\n\n  abstract public void setCursor(int width, int height, Point hotspot,\n                                 byte[] data);\n\n  public void setPixelFormat(PixelFormat pf)\n  {\n    server.setPF(pf);\n  }\n\n  public void setName(String name)\n  {\n    server.setName(name);\n  }\n\n  public void fence(int flags, int len, byte[] data)\n  {\n    server.supportsFence = true;\n  }\n\n  public void endOfContinuousUpdates()\n  {\n    server.supportsContinuousUpdates = true;\n  }\n\n  abstract public void clientRedirect(int port, String host,\n                                      String x509subject);\n\n  public void serverInit(int width, int height,\n                         PixelFormat pf, String name)\n  {\n    server.setDimensions(width, height);\n    server.setPF(pf);\n    server.setName(name);\n  }\n\n  abstract public void readAndDecodeRect(Rect r, int encoding,\n                                         ModifiablePixelBuffer pb);\n\n  public void framebufferUpdateStart() {};\n  public void framebufferUpdateEnd() {};\n  abstract public void dataRect(Rect r, int encoding);\n\n  abstract public void setColourMapEntries(int firstColour, int nColours,\n    int[] rgbs);\n  abstract public void bell();\n  abstract public void serverCutText(String str, int len);\n\n  public ServerParams server;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CMsgReader.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n * Copyright (C) 2017 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// CMsgReader - class for reading RFB messages on the client side\n// (i.e. messages from server to client).\n//\n\npackage com.tigervnc.rfb;\n\nimport java.awt.image.*;\nimport java.nio.ByteBuffer;\nimport java.nio.CharBuffer;\nimport java.nio.charset.Charset;\n\nimport com.tigervnc.rdr.*;\n\npublic class CMsgReader {\n\n  static LogWriter vlog = new LogWriter(\"CMsgReader\");\n\n  protected CMsgReader(CMsgHandler handler_, InStream is_)\n  {\n    imageBufIdealSize = 0;\n    handler = handler_;\n    is = is_;\n    nUpdateRectsLeft = 0;\n    imageBuf = null;\n    imageBufSize = 0;\n  }\n\n  public void readServerInit()\n  {\n    int width = is.readU16();\n    int height = is.readU16();\n    PixelFormat pf = new PixelFormat();\n    pf.read(is);\n    String name = is.readString();\n    handler.serverInit(width, height, pf, name);\n  }\n\n  public void readMsg()\n  {\n    if (nUpdateRectsLeft == 0) {\n      int type = is.readU8();\n\n      switch (type) {\n      case MsgTypes.msgTypeSetColourMapEntries:\n        readSetColourMapEntries();\n        break;\n      case MsgTypes.msgTypeBell:\n        readBell();\n        break;\n      case MsgTypes.msgTypeServerCutText:\n        readServerCutText();\n        break;\n      case MsgTypes.msgTypeFramebufferUpdate:\n        readFramebufferUpdate();\n        break;\n      case MsgTypes.msgTypeServerFence:\n        readFence();\n        break;\n      case MsgTypes.msgTypeEndOfContinuousUpdates:\n        readEndOfContinuousUpdates();\n        break;\n      default:\n        vlog.error(\"Unknown message type \"+type);\n        throw new Exception(\"Unknown message type\");\n      }\n    } else {\n      int x = is.readU16();\n      int y = is.readU16();\n      int w = is.readU16();\n      int h = is.readU16();\n      int encoding = is.readS32();\n\n      switch (encoding) {\n      case Encodings.pseudoEncodingLastRect:\n        nUpdateRectsLeft = 1;     // this rectangle is the last one\n        break;\n      case Encodings.pseudoEncodingXCursor:\n        readSetXCursor(w, h, new Point(x,y));\n        break;\n      case Encodings.pseudoEncodingCursor:\n        readSetCursor(w, h, new Point(x,y));\n        break;\n      case Encodings.pseudoEncodingCursorWithAlpha:\n        readSetCursorWithAlpha(w, h, new Point(x,y));\n        break;\n      case Encodings.pseudoEncodingVMwareCursor:\n        readSetVMwareCursor(w, h, new Point(x,y));\n        break;\n      case Encodings.pseudoEncodingDesktopName:\n        readSetDesktopName(x, y, w, h);\n        break;\n      case Encodings.pseudoEncodingDesktopSize:\n        handler.setDesktopSize(w, h);\n        break;\n      case Encodings.pseudoEncodingExtendedDesktopSize:\n        readExtendedDesktopSize(x, y, w, h);\n        break;\n      case Encodings.pseudoEncodingClientRedirect:\n        nUpdateRectsLeft = 0;\n        readClientRedirect(x, y, w, h);\n        return;\n      default:\n        readRect(new Rect(x, y, x+w, y+h), encoding);\n        break;\n      };\n\n      nUpdateRectsLeft--;\n      if (nUpdateRectsLeft == 0)\n        handler.framebufferUpdateEnd();\n    }\n  }\n\n  protected void readSetColourMapEntries()\n  {\n    is.skip(1);\n    int firstColour = is.readU16();\n    int nColours = is.readU16();\n    int[] rgbs = new int[nColours * 3];\n    for (int i = 0; i < nColours * 3; i++)\n      rgbs[i] = is.readU16();\n    handler.setColourMapEntries(firstColour, nColours, rgbs);\n  }\n\n  protected void readBell()\n  {\n    handler.bell();\n  }\n\n  protected void readServerCutText()\n  {\n    is.skip(3);\n    int len = is.readU32();\n\n    if (len > 256*1024) {\n      is.skip(len);\n      vlog.error(\"Cut text too long (\"+len+\" bytes) - ignoring\");\n      return;\n    }\n\n    ByteBuffer buf = ByteBuffer.allocate(len);\n    is.readBytes(buf, len);\n    Charset latin1 = Charset.forName(\"ISO-8859-1\");\n    CharBuffer chars = latin1.decode(buf.compact());\n    handler.serverCutText(chars.toString(), len);\n  }\n\n  protected void readFence()\n  {\n    int flags;\n    int len;\n    ByteBuffer data = ByteBuffer.allocate(64);\n\n    is.skip(3);\n\n    flags = is.readU32();\n\n    len = is.readU8();\n    if (len > data.capacity()) {\n      System.out.println(\"Ignoring fence with too large payload\\n\");\n      is.skip(len);\n      return;\n    }\n\n    is.readBytes(data, len);\n\n    handler.fence(flags, len, data.array());\n  }\n\n  protected void readEndOfContinuousUpdates()\n  {\n    handler.endOfContinuousUpdates();\n  }\n\n  protected void readFramebufferUpdate()\n  {\n    is.skip(1);\n    nUpdateRectsLeft = is.readU16();\n    handler.framebufferUpdateStart();\n  }\n\n  protected void readRect(Rect r, int encoding)\n  {\n    if ((r.br.x > handler.server.width()) || (r.br.y > handler.server.height())) {\n      vlog.error(\"Rect too big: \"+r.width()+\"x\"+r.height()+\" at \"+\n                  r.tl.x+\",\"+r.tl.y+\" exceeds \"+handler.server.width()+\"x\"+\n                  handler.server.height());\n      throw new Exception(\"Rect too big\");\n    }\n\n    if (r.is_empty())\n      vlog.error(\"Ignoring zero size rect\");\n\n    handler.dataRect(r, encoding);\n  }\n\n  protected void readSetXCursor(int width, int height, Point hotspot)\n  {\n    byte pr, pg, pb;\n    byte sr, sg, sb;\n    int data_len = ((width+7)/8) * height;\n    int mask_len = ((width+7)/8) * height;\n    ByteBuffer data = ByteBuffer.allocate(data_len);\n    ByteBuffer mask = ByteBuffer.allocate(mask_len);\n\n    int x, y;\n    byte[] buf = new byte[width*height*4];\n    ByteBuffer out;\n\n    if (width * height == 0)\n      return;\n\n    pr = (byte)is.readU8();\n    pg = (byte)is.readU8();\n    pb = (byte)is.readU8();\n\n    sr = (byte)is.readU8();\n    sg = (byte)is.readU8();\n    sb = (byte)is.readU8();\n\n    is.readBytes(data, data_len);\n    is.readBytes(mask, mask_len);\n\n    int maskBytesPerRow = (width+7)/8;\n    out = ByteBuffer.wrap(buf);\n    for (y = 0;y < height;y++) {\n      for (x = 0;x < width;x++) {\n        int byte_ = y * maskBytesPerRow + x / 8;\n        int bit = 7 - x % 8;\n\n        // NOTE: BufferedImage needs ARGB, rather than RGBA\n        if ((mask.get(byte_) & (1 << bit)) > 0)\n          out.put(out.position(), (byte)255);\n        else\n          out.put(out.position(), (byte)0);\n\n        if ((data.get(byte_) & (1 << bit)) > 0) {\n          out.put(out.position() + 1, pr);\n          out.put(out.position() + 2, pg);\n          out.put(out.position() + 3, pb);\n        } else {\n          out.put(out.position() + 1, sr);\n          out.put(out.position() + 2, sg);\n          out.put(out.position() + 3, sb);\n        }\n\n        out.position(out.position() + 4);\n      }\n    }\n\n    handler.setCursor(width, height, hotspot, buf);\n  }\n\n  protected void readSetCursor(int width, int height, Point hotspot)\n  {\n    int data_len = width * height * (handler.server.pf().bpp/8);\n    int mask_len = ((width+7)/8) * height;\n    ByteBuffer data = ByteBuffer.allocate(data_len);\n    ByteBuffer mask = ByteBuffer.allocate(mask_len);\n\n    int x, y;\n    byte[] buf = new byte[width*height*4];\n    ByteBuffer in;\n    ByteBuffer out;\n\n    is.readBytes(data, data_len);\n    is.readBytes(mask, mask_len);\n\n    int maskBytesPerRow = (width+7)/8;\n    in = ByteBuffer.wrap(data.array());\n    out = ByteBuffer.wrap(buf);\n    for (y = 0;y < height;y++) {\n      for (x = 0;x < width;x++) {\n        int byte_ = y * maskBytesPerRow + x / 8;\n        int bit = 7 - x % 8;\n\n        // NOTE: BufferedImage needs ARGB, rather than RGBA\n        if ((mask.get(byte_) & (1 << bit)) != 0)\n          out.put((byte)255);\n        else\n          out.put((byte)0);\n\n        handler.server.pf().rgbFromBuffer(out.duplicate(), in.duplicate(), 1);\n\n        in.position(in.position() + handler.server.pf().bpp/8);\n        out.position(out.position() + 3);\n      }\n    }\n\n    handler.setCursor(width, height, hotspot, buf);\n  }\n\n  protected void readSetCursorWithAlpha(int width, int height, Point hotspot)\n  {\n    int encoding;\n\n    PixelFormat rgbaPF =\n      new PixelFormat(32, 32, false, true, 255, 255, 255, 16, 8, 0);\n    ManagedPixelBuffer pb =\n      new ManagedPixelBuffer(rgbaPF, width, height);\n    PixelFormat origPF;\n\n    ByteBuffer buf =\n      ByteBuffer.allocate(pb.area()*4).order(rgbaPF.getByteOrder());;\n\n    encoding = is.readS32();\n\n    origPF = handler.server.pf();\n    handler.server.setPF(rgbaPF);\n    handler.readAndDecodeRect(pb.getRect(), encoding, pb);\n    handler.server.setPF(origPF);\n\n    // ARGB with pre-multiplied alpha works best for BufferedImage\n    if (pb.area() > 0) {\n      // Sometimes a zero width or height cursor is sent.\n      DataBuffer db = pb.getBuffer(pb.getRect()).getDataBuffer();\n      for (int i = 0;i < pb.area();i++)\n        buf.asIntBuffer().put(i, db.getElem(i));\n    }\n\n    for (int i = 0;i < pb.area();i++) {\n      byte alpha = buf.get(buf.position()+3);\n\n      buf.put(i*4+3, buf.get(i*4+2));\n      buf.put(i*4+2, buf.get(i*4+1));\n      buf.put(i*4+1, buf.get(i*4+0));\n      buf.put(i*4+0, alpha);\n\n      buf.position(buf.position() + 4);\n    }\n\n    handler.setCursor(width, height, hotspot, buf.array());\n  }\n\n  protected void readSetVMwareCursor(int width, int height, Point hotspot)\n  {\n    // VMware cursor sends RGBA, java BufferedImage needs ARGB\n    if (width > maxCursorSize || height > maxCursorSize)\n      throw new Exception(\"Too big cursor\");\n\n    byte type;\n\n    type = (byte)is.readU8();\n    is.skip(1);\n\n    if (type == 0) {\n      int len = width * height * (handler.server.pf().bpp/8);\n      ByteBuffer andMask = ByteBuffer.allocate(len);\n      ByteBuffer xorMask = ByteBuffer.allocate(len);\n\n      ByteBuffer data = ByteBuffer.allocate(width*height*4);\n\n      ByteBuffer andIn;\n      ByteBuffer xorIn;\n      ByteBuffer out;\n      int Bpp;\n\n      is.readBytes(andMask, len);\n      is.readBytes(xorMask, len);\n\n      andIn = ByteBuffer.wrap(andMask.array());\n      xorIn = ByteBuffer.wrap(xorMask.array());\n      out = ByteBuffer.wrap(data.array());\n      Bpp = handler.server.pf().bpp/8;\n      for (int y = 0;y < height;y++) {\n        for (int x = 0;x < width;x++) {\n          int andPixel, xorPixel;\n\n          andPixel = handler.server.pf().pixelFromBuffer(andIn.duplicate());\n          xorPixel = handler.server.pf().pixelFromBuffer(xorIn.duplicate());\n          andIn.position(andIn.position() + Bpp);\n          xorIn.position(xorIn.position() + Bpp);\n\n          if (andPixel == 0) {\n            byte r, g, b;\n\n            // Opaque pixel\n\n            r = (byte)handler.server.pf().getColorModel().getRed(xorPixel);\n            g = (byte)handler.server.pf().getColorModel().getGreen(xorPixel);\n            b = (byte)handler.server.pf().getColorModel().getBlue(xorPixel);\n            out.put((byte)0xff);\n            out.put(r);\n            out.put(g);\n            out.put(b);\n          } else if (xorPixel == 0) {\n            // Fully transparent pixel\n            out.put((byte)0);\n            out.put((byte)0);\n            out.put((byte)0);\n            out.put((byte)0);\n          } else if (andPixel == xorPixel) {\n            // Inverted pixel\n\n            // We don't really support this, so just turn the pixel black\n            // FIXME: Do an outline like WinVNC does?\n            out.put((byte)0xff);\n            out.put((byte)0);\n            out.put((byte)0);\n            out.put((byte)0);\n          } else {\n            // Partially transparent/inverted pixel\n\n            // We _really_ can't handle this, just make it black\n            out.put((byte)0xff);\n            out.put((byte)0);\n            out.put((byte)0);\n            out.put((byte)0);\n          }\n        }\n      }\n\n      handler.setCursor(width, height, hotspot, data.array());\n    } else if (type == 1) {\n      ByteBuffer data = ByteBuffer.allocate(width*height*4);\n\n      // FIXME: Is alpha premultiplied?\n      ByteBuffer buf = ByteBuffer.allocate(4);\n      for (int i=0;i < width*height*4;i+=4) {\n        is.readBytes(buf,4);\n        data.put(buf.array(),3,1);\n        data.put(buf.array(),0,3);\n        buf.clear();\n      }\n\n      handler.setCursor(width, height, hotspot, data.array());\n    } else {\n      throw new Exception(\"Unknown cursor type\");\n    }\n  }\n\n  protected void readSetDesktopName(int x, int y, int w, int h)\n  {\n    String name = is.readString();\n\n    if (x != 0 || y != 0 || w != 0 || h != 0) {\n      vlog.error(\"Ignoring DesktopName rect with non-zero position/size\");\n    } else {\n      handler.setName(name);\n    }\n\n  }\n\n  protected void readExtendedDesktopSize(int x, int y, int w, int h)\n  {\n    int screens, i;\n    int id, flags;\n    int sx, sy, sw, sh;\n    ScreenSet layout = new ScreenSet();\n\n    screens = is.readU8();\n    is.skip(3);\n\n    for (i = 0;i < screens;i++) {\n      id = is.readU32();\n      sx = is.readU16();\n      sy = is.readU16();\n      sw = is.readU16();\n      sh = is.readU16();\n      flags = is.readU32();\n\n      layout.add_screen(new Screen(id, sx, sy, sw, sh, flags));\n    }\n\n    handler.setExtendedDesktopSize(x, y, w, h, layout);\n  }\n\n  protected void readClientRedirect(int x, int y, int w, int h)\n  {\n    int port = is.readU16();\n    String host = is.readString();\n    String x509subject = is.readString();\n\n    if (x != 0 || y != 0 || w != 0 || h != 0)\n      vlog.error(\"Ignoring ClientRedirect rect with non-zero position/size\");\n    else\n      handler.clientRedirect(port, host, x509subject);\n  }\n\n  public int[] getImageBuf(int required) { return getImageBuf(required, 0, 0); }\n\n  public int[] getImageBuf(int required, int requested, int nPixels)\n  {\n    int requiredBytes = required;\n    int requestedBytes = requested;\n    int size = requestedBytes;\n    if (size > imageBufIdealSize) size = imageBufIdealSize;\n\n    if (size < requiredBytes)\n      size = requiredBytes;\n\n    if (imageBufSize < size) {\n      imageBufSize = size;\n      imageBuf = new int[imageBufSize];\n    }\n    if (nPixels != 0)\n      nPixels = imageBufSize / (handler.server.pf().bpp / 8);\n    return imageBuf;\n  }\n\n  public InStream getInStream() { return is; }\n\n  public int imageBufIdealSize;\n\n  protected CMsgHandler handler;\n  protected InStream is;\n  protected int nUpdateRectsLeft;\n  protected final int maxCursorSize = 256;\n  protected int[] imageBuf;\n  protected int imageBufSize;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CMsgWriter.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2011 Pierre Ossman for Cendio AB\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport com.tigervnc.rdr.*;\nimport java.nio.ByteBuffer;\nimport java.nio.charset.Charset;\nimport java.util.*;\n\npublic class CMsgWriter {\n\n  protected CMsgWriter(ServerParams server_, OutStream os_)\n  {\n    server = server_;\n    os = os_;\n  }\n\n  synchronized public void writeClientInit(boolean shared) {\n    os.writeU8(shared?1:0);\n    endMsg();\n  }\n\n  synchronized public void writeSetPixelFormat(PixelFormat pf)\n  {\n    startMsg(MsgTypes.msgTypeSetPixelFormat);\n    os.pad(3);\n    pf.write(os);\n    endMsg();\n  }\n\n  synchronized public void writeSetEncodings(List<Integer> encodings)\n  {\n    startMsg(MsgTypes.msgTypeSetEncodings);\n    os.skip(1);\n    os.writeU16(encodings.size());\n    for (Iterator<Integer> i = encodings.iterator(); i.hasNext();)\n      os.writeU32(i.next());\n    endMsg();\n  }\n\n  synchronized public void writeSetDesktopSize(int width, int height,\n                                               ScreenSet layout)\n\t{\n\t  if (!server.supportsSetDesktopSize)\n\t    throw new Exception(\"Server does not support SetDesktopSize\");\n\n\t  startMsg(MsgTypes.msgTypeSetDesktopSize);\n\t  os.pad(1);\n\n\t  os.writeU16(width);\n\t  os.writeU16(height);\n\n\t  os.writeU8(layout.num_screens());\n\t  os.pad(1);\n\n    for (Iterator<Screen> iter = layout.screens.iterator(); iter.hasNext(); ) {\n      Screen refScreen = (Screen)iter.next();\n\t    os.writeU32(refScreen.id);\n\t    os.writeU16(refScreen.dimensions.tl.x);\n\t    os.writeU16(refScreen.dimensions.tl.y);\n\t    os.writeU16(refScreen.dimensions.width());\n\t    os.writeU16(refScreen.dimensions.height());\n\t    os.writeU32(refScreen.flags);\n\t  }\n\n\t  endMsg();\n\t}\n\n  synchronized public void writeFramebufferUpdateRequest(Rect r, boolean incremental)\n  {\n    startMsg(MsgTypes.msgTypeFramebufferUpdateRequest);\n    os.writeU8(incremental?1:0);\n    os.writeU16(r.tl.x);\n    os.writeU16(r.tl.y);\n    os.writeU16(r.width());\n    os.writeU16(r.height());\n    endMsg();\n  }\n\n  synchronized public void writeEnableContinuousUpdates(boolean enable,\n                                           int x, int y, int w, int h)\n  {\n    if (!server.supportsContinuousUpdates)\n      throw new Exception(\"Server does not support continuous updates\");\n\n    startMsg(MsgTypes.msgTypeEnableContinuousUpdates);\n\n    os.writeU8((enable?1:0));\n\n    os.writeU16(x);\n    os.writeU16(y);\n    os.writeU16(w);\n    os.writeU16(h);\n\n    endMsg();\n  }\n\n  synchronized public void writeFence(int flags, int len, byte[] data)\n  {\n    if (!server.supportsFence)\n      throw new Exception(\"Server does not support fences\");\n    if (len > 64)\n      throw new Exception(\"Too large fence payload\");\n    if ((flags & ~fenceTypes.fenceFlagsSupported) != 0)\n      throw new Exception(\"Unknown fence flags\");\n\n    startMsg(MsgTypes.msgTypeClientFence);\n    os.pad(3);\n\n    os.writeU32(flags);\n\n    os.writeU8(len);\n    os.writeBytes(data, 0, len);\n\n    endMsg();\n  }\n\n  synchronized public void writeKeyEvent(int keysym, boolean down)\n  {\n    startMsg(MsgTypes.msgTypeKeyEvent);\n    os.writeU8(down?1:0);\n    os.pad(2);\n    os.writeU32(keysym);\n    endMsg();\n  }\n\n  synchronized public void writePointerEvent(Point pos, int buttonMask)\n  {\n    Point p = new Point(pos.x,pos.y);\n    if (p.x < 0) p.x = 0;\n    if (p.y < 0) p.y = 0;\n    if (p.x >= server.width()) p.x = server.width() - 1;\n    if (p.y >= server.height()) p.y = server.height() - 1;\n\n    startMsg(MsgTypes.msgTypePointerEvent);\n    os.writeU8(buttonMask);\n    os.writeU16(p.x);\n    os.writeU16(p.y);\n    endMsg();\n  }\n\n  synchronized public void writeClientCutText(String str, int len)\n  {\n    startMsg(MsgTypes.msgTypeClientCutText);\n    os.pad(3);\n    os.writeU32(len);\n    Charset latin1 = Charset.forName(\"ISO-8859-1\");\n    ByteBuffer bytes = latin1.encode(str);\n    os.writeBytes(bytes.array(), 0, len);\n    endMsg();\n  }\n\n  synchronized protected void startMsg(int type) {\n    os.writeU8(type);\n  }\n\n  synchronized protected void endMsg() {\n    os.flush();\n  }\n\n  protected ServerParams server;\n  protected OutStream os;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CSecurity.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// CSecurity - class on the client side for handling security handshaking.  A\n// derived class for a particular security type overrides the processMsg()\n// method.  processMsg() is called first when the security type has been\n// decided on, and will keep being called whenever there is data to read from\n// the server until either it returns 0, indicating authentication/security\n// failure, or it returns 1, to indicate success.  A return value of 2\n// (actually anything other than 0 or 1) indicates that it should be called\n// back when there is more data to read.\n//\n// Note that the first time processMsg() is called, there is no guarantee that\n// there is any data to read from the CConnection's InStream, but subsequent\n// calls guarantee there is at least one byte which can be read without\n// blocking.\n\npackage com.tigervnc.rfb;\n\nabstract public class CSecurity {\n  abstract public boolean processMsg(CConnection cc);\n  abstract public int getType();\n  abstract public String description();\n  public boolean isSecure() { return false; }\n\n  /*\n   * Use variable directly instead of dumb get/set methods.\n   * It MUST be set by viewer.\n   */\n  public static UserPasswdGetter upg;\n  public static UserMsgBox msg;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CSecurityIdent.java",
    "content": "/* Copyright (C) 2011-2017 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport com.tigervnc.rdr.*;\nimport com.tigervnc.vncviewer.*;\n\npublic class CSecurityIdent extends CSecurity {\n\n  public CSecurityIdent() { }\n\n  public boolean processMsg(CConnection cc) {\n    OutStream os = cc.getOutStream();\n\n    StringBuffer username = new StringBuffer();\n\n    upg.getUserPasswd(cc.isSecure(), username, null);\n\n    // Return the response to the server\n    os.writeU32(username.length());\n    try {\n      byte[] utf8str = username.toString().getBytes(\"UTF8\");\n      os.writeBytes(utf8str, 0, username.length());\n    } catch(java.io.UnsupportedEncodingException e) {\n      e.printStackTrace();\n    }\n    os.flush();\n    return true;\n  }\n\n  public int getType() { return Security.secTypeIdent; }\n\n  static LogWriter vlog = new LogWriter(\"Ident\");\n  public String description() { return \"No Encryption\"; }\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CSecurityNone.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class CSecurityNone extends CSecurity {\n\n  public boolean processMsg(CConnection cc) { return true; }\n  public int getType() { return Security.secTypeNone; }\n  public String description() { return \"No Encryption\"; }\n  static LogWriter vlog = new LogWriter(\"CSecurityNone\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CSecurityPlain.java",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2011-2017 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport com.tigervnc.rdr.*;\nimport com.tigervnc.vncviewer.*;\n\npublic class CSecurityPlain extends CSecurity {\n\n  public CSecurityPlain() { }\n\n  public boolean processMsg(CConnection cc)\n  {\n    OutStream os = cc.getOutStream();\n\n    StringBuffer username = new StringBuffer();\n    StringBuffer password = new StringBuffer();\n\n    upg.getUserPasswd(cc.isSecure(), username, password);\n\n    // Return the response to the server\n    os.writeU32(username.length());\n    os.writeU32(password.length());\n    byte[] utf8str;\n    try {\n      utf8str = username.toString().getBytes(\"UTF8\");\n      os.writeBytes(utf8str, 0, username.length());\n      utf8str = password.toString().getBytes(\"UTF8\");\n      os.writeBytes(utf8str, 0, password.length());\n    } catch(java.io.UnsupportedEncodingException e) {\n      e.printStackTrace();\n    }\n    os.flush();\n    return true;\n  }\n\n  public int getType() { return Security.secTypePlain; }\n  public String description() { return \"ask for username and password\"; }\n\n  static LogWriter vlog = new LogWriter(\"Plain\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CSecurityRSAAES.java",
    "content": "/* Copyright (C) 2022 Dinglan Peng\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.io.UnsupportedEncodingException;\nimport java.math.BigInteger;\nimport java.nio.ByteBuffer;\nimport java.security.InvalidKeyException;\nimport java.security.KeyFactory;\nimport java.security.KeyPair;\nimport java.security.KeyPairGenerator;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.PrivateKey;\nimport java.security.PublicKey;\nimport java.security.SecureRandom;\nimport java.security.interfaces.RSAPublicKey;\nimport java.security.spec.InvalidKeySpecException;\nimport java.security.spec.RSAPublicKeySpec;\nimport java.util.Arrays;\n\nimport javax.crypto.BadPaddingException;\nimport javax.crypto.Cipher;\nimport javax.crypto.IllegalBlockSizeException;\nimport javax.crypto.NoSuchPaddingException;\nimport javax.swing.JOptionPane;\n\nimport com.tigervnc.rdr.*;\nimport com.tigervnc.vncviewer.*;\n\npublic class CSecurityRSAAES extends CSecurity {\n\n  private static final int MinKeyLength = 1024;\n  private static final int MaxKeyLength = 8192;\n\n  private static final byte[] bigIntToBytes(BigInteger n, int bytes) {\n    int bits = n.bitCount();\n    byte[] arr = n.toByteArray();\n    //int len = bits % 8 == 0 ? arr.length - 1 : arr.length;\n    //System.out.printf(\"%d %d %d\\n\", bits, len, bytes);\n    //if (len > bytes)\n    //  return null;\n    int len = arr.length < bytes ? arr.length : bytes;\n    byte[] res = new byte[bytes];\n    System.arraycopy(arr, arr.length - len, res, bytes - len, len);\n    return res;\n  }\n\n  public CSecurityRSAAES(int secType, int keySize, boolean isAllEncrypted) {\n    this.secType = secType;\n    this.keySize = keySize;\n    this.isAllEncrypted = isAllEncrypted;\n  }\n\n  public boolean processMsg(CConnection cc) {\n    readPubclicKey(cc);\n    verifyServer();\n    writePublicKey(cc);\n    writeRandom(cc);\n    readRandom(cc);\n    setCipher(cc);\n    writeHash(cc);\n    readHash();\n    readSubtype();\n    writeCredentials();\n    return true;\n  }\n\n  private void readPubclicKey(CConnection cc) {\n    InStream is = cc.getInStream();\n    serverKeyLength = is.readU32();\n    if (serverKeyLength < MinKeyLength)\n      throw new AuthFailureException(\"server key is too short\");\n    if (serverKeyLength > MaxKeyLength)\n      throw new AuthFailureException(\"server key is too long\");\n    int size = (serverKeyLength + 7) / 8;\n    serverKeyN = new byte[size];\n    serverKeyE = new byte[size];\n    is.readBytes(ByteBuffer.wrap(serverKeyN), size);\n    is.readBytes(ByteBuffer.wrap(serverKeyE), size);\n    BigInteger modulus = new BigInteger(1, serverKeyN);\n    BigInteger publicExponent = new BigInteger(1, serverKeyE);\n    RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent);\n    try {\n      KeyFactory factory = KeyFactory.getInstance(\"RSA\");\n      serverKey = factory.generatePublic(spec);\n    } catch (NoSuchAlgorithmException e) {\n      throw new AuthFailureException(\"RSA algorithm is not supported\");\n    } catch (InvalidKeySpecException e) {\n      throw new AuthFailureException(\"server key is invalid\");\n    }\n  }\n\n  private void verifyServer() {\n    MessageDigest digest;\n    try {\n      digest = MessageDigest.getInstance(\"SHA-1\");\n    } catch (NoSuchAlgorithmException e) {\n      throw new AuthFailureException(\"SHA-1 algorithm is not supported\");\n    }\n    byte[] length = new byte[4];\n    length[0] = (byte) ((serverKeyLength & 0xff000000) >> 24);\n    length[1] = (byte) ((serverKeyLength & 0xff0000) >> 16);\n    length[2] = (byte) ((serverKeyLength & 0xff00) >> 8);\n    length[3] = (byte) (serverKeyLength & 0xff);\n    digest.update(length);\n    digest.update(serverKeyN);\n    digest.update(serverKeyE);\n    byte[] f = digest.digest();\n    String title = \"Server key fingerprint\";\n    String text = String.format(\n      \"The server has provided the following identifying information:\\n\" +\n      \"Fingerprint: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\\n\" +\n      \"Please verify that the information is correct and press \\\"Yes\\\". \" +\n      \"Otherwise press \\\"No\\\"\", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]);\n    if (!msg.showMsgBox(JOptionPane.YES_NO_OPTION, title, text))\n      throw new AuthFailureException(\"server key mismatch\");\n  }\n\n  private void writePublicKey(CConnection cc) {\n    OutStream os = cc.getOutStream();\n    clientKeyLength = serverKeyLength;\n    KeyPairGenerator kpg;\n    try {\n      kpg = KeyPairGenerator.getInstance(\"RSA\");\n    } catch (NoSuchAlgorithmException e) {\n      throw new AuthFailureException(\"RSA algorithm is not supported\");\n    }\n    kpg.initialize(clientKeyLength);\n    KeyPair kp = kpg.generateKeyPair();\n    clientKey = kp.getPrivate();\n    clientPublicKey = kp.getPublic();\n    RSAPublicKey rsaKey = (RSAPublicKey) clientPublicKey;\n    BigInteger modulus = rsaKey.getModulus();\n    BigInteger publicExponent = rsaKey.getPublicExponent();\n\n    clientKeyN = bigIntToBytes(modulus, (clientKeyLength + 7) / 8);\n    clientKeyE = bigIntToBytes(publicExponent, (clientKeyLength + 7) / 8);\n    if (clientKeyN == null || clientKeyN == null) {\n      throw new AuthFailureException(\"failed to generate RSA keys\");\n    }\n    os.writeU32(clientKeyLength);\n    os.writeBytes(clientKeyN, 0, clientKeyN.length);\n    os.writeBytes(clientKeyE, 0, clientKeyE.length);\n    os.flush();\n  }\n\n  private void writeRandom(CConnection cc) {\n    OutStream os = cc.getOutStream();\n    SecureRandom sr = new SecureRandom();\n    clientRandom = new byte[keySize / 8];\n    sr.nextBytes(clientRandom);\n    byte[] encrypted;\n    try {\n      Cipher cipher = Cipher.getInstance(\"RSA/ECB/PKCS1Padding\");\n      cipher.init(Cipher.ENCRYPT_MODE, serverKey);\n      encrypted = cipher.doFinal(clientRandom);\n    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {\n      throw new AuthFailureException(\"RSA algorithm is not supported\");\n    } catch (InvalidKeyException | IllegalBlockSizeException |\n             BadPaddingException e) {\n      throw new AuthFailureException(\"failed to encrypt random\");\n    }\n    os.writeU16(encrypted.length);\n    os.writeBytes(encrypted, 0, encrypted.length);\n    os.flush();\n  }\n\n  private void readRandom(CConnection cc) {\n    InStream is = cc.getInStream();\n    int size = is.readU16();\n    if (size != clientKeyN.length)\n      throw new AuthFailureException(\"client key length doesn't match\");\n    byte[] buffer = new byte[size];\n    is.readBytes(ByteBuffer.wrap(buffer), size);\n    try {\n      Cipher cipher = Cipher.getInstance(\"RSA/ECB/PKCS1Padding\");\n      cipher.init(Cipher.DECRYPT_MODE, clientKey);\n      serverRandom = cipher.doFinal(buffer);\n    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {\n      throw new AuthFailureException(\"RSA algorithm is not supported\");\n    } catch (InvalidKeyException | IllegalBlockSizeException |\n             BadPaddingException e) {\n      System.out.println(e.getMessage());\n      throw new AuthFailureException(\"failed to decrypt server random\");\n    }\n    if (serverRandom.length != keySize / 8)\n      throw new AuthFailureException(\"server random length doesn't match\");\n  }\n\n  private void setCipher(CConnection cc) {\n    rawis = cc.getInStream();\n    rawos = cc.getOutStream();\n    MessageDigest digest;\n    try {\n      digest = MessageDigest.getInstance(keySize == 128 ? \"SHA-1\" : \"SHA-256\");\n    } catch (NoSuchAlgorithmException e) {\n      throw new AuthFailureException(\"hash algorithm is not supported\");\n    }\n    digest.update(clientRandom);\n    digest.update(serverRandom);\n    byte[] key = Arrays.copyOfRange(digest.digest(), 0, keySize / 8);\n    rais = new AESInStream(rawis, key);\n    digest.reset();\n    digest.update(serverRandom);\n    digest.update(clientRandom);\n    key = Arrays.copyOfRange(digest.digest(), 0, keySize / 8);\n    raos = new AESOutStream(rawos, key);\n    if (isAllEncrypted)\n      cc.setStreams(rais, raos);\n  }\n\n  private void writeHash(CConnection cc) {\n    MessageDigest digest;\n    try {\n      digest = MessageDigest.getInstance(keySize == 128 ? \"SHA-1\" : \"SHA-256\");\n    } catch (NoSuchAlgorithmException e) {\n      throw new AuthFailureException(\"hash algorithm is not supported\");\n    }\n    int len = serverKeyLength;\n    byte[] lenServerKey = new byte[] {\n        (byte) ((len & 0xff000000) >> 24),\n        (byte) ((len & 0xff0000) >> 16),\n        (byte) ((len & 0xff00) >> 8),\n        (byte) (len & 0xff)\n    };\n    len = clientKeyLength;\n    byte[] lenClientKey = new byte[] {\n        (byte) ((len & 0xff000000) >> 24),\n        (byte) ((len & 0xff0000) >> 16),\n        (byte) ((len & 0xff00) >> 8),\n        (byte) (len & 0xff)\n    };\n    digest.update(lenClientKey);\n    digest.update(clientKeyN);\n    digest.update(clientKeyE);\n    digest.update(lenServerKey);\n    digest.update(serverKeyN);\n    digest.update(serverKeyE);\n    byte[] hash = digest.digest();\n    raos.writeBytes(hash, 0, hash.length);\n    raos.flush();\n  }\n\n  void readHash() {\n    MessageDigest digest;\n    try {\n      digest = MessageDigest.getInstance(keySize == 128 ? \"SHA-1\" : \"SHA-256\");\n    } catch (NoSuchAlgorithmException e) {\n      throw new AuthFailureException(\"hash algorithm is not supported\");\n    }\n    int len = serverKeyLength;\n    byte[] lenServerKey = new byte[] {\n        (byte)((len & 0xff000000) >> 24),\n        (byte)((len & 0xff0000) >> 16),\n        (byte)((len & 0xff00) >> 8),\n        (byte)(len & 0xff)\n    };\n    len = clientKeyLength;\n    byte[] lenClientKey = new byte[] {\n        (byte)((len & 0xff000000) >> 24),\n        (byte)((len & 0xff0000) >> 16),\n        (byte)((len & 0xff00) >> 8),\n        (byte)(len & 0xff)\n    };\n    digest.update(lenServerKey);\n    digest.update(serverKeyN);\n    digest.update(serverKeyE);\n    digest.update(lenClientKey);\n    digest.update(clientKeyN);\n    digest.update(clientKeyE);\n    byte[] realHash = digest.digest();\n    ByteBuffer hash = ByteBuffer.allocate(realHash.length);\n    rais.readBytes(hash, realHash.length);\n    if (!Arrays.equals(hash.array(), realHash)) {\n      throw new AuthFailureException(\"hash doesn't match\");\n    }\n  }\n\n  private void readSubtype() {\n    subtype = rais.readU8();\n    if (subtype != Security.secTypeRA2UserPass &&\n        subtype != Security.secTypeRA2Pass)\n      throw new AuthFailureException(\"unknown RSA-AES subtype\");\n  }\n\n  private void writeCredentials() {\n    StringBuffer username = new StringBuffer();\n    StringBuffer password = new StringBuffer();\n    CSecurity.upg.getUserPasswd(secType == Security.secTypeRA256,\n                                subtype == Security.secTypeRA2UserPass ?\n                                  username : null, \n                                password);\n    if (username.length() > 255)\n      throw new AuthFailureException(\"username is too long\");\n    byte[] usernameBytes;\n    try {\n      usernameBytes = username.toString().getBytes(\"UTF-8\");\n    } catch (UnsupportedEncodingException e) {\n      throw new AuthFailureException(\"UTF-8 is not supported\");\n    }\n    raos.writeU8(usernameBytes.length);\n    if (usernameBytes.length != 0)\n      raos.writeBytes(usernameBytes, 0, usernameBytes.length);\n    if (password.length() > 255)\n      throw new AuthFailureException(\"password is too long\");\n    byte[] passwordBytes;\n    try {\n      passwordBytes = password.toString().getBytes(\"UTF-8\");\n    } catch (UnsupportedEncodingException e) {\n      throw new AuthFailureException(\"UTF-8 is not supported\");\n    }\n    raos.writeU8(passwordBytes.length);\n    if (passwordBytes.length != 0)\n      raos.writeBytes(passwordBytes, 0, passwordBytes.length);\n    raos.flush();\n  }\n\n  public int getType() {\n    return secType;\n  }\n\n  public String description() {\n    return \"RSA-ASE security types\";\n  }\n\n  private int secType;\n  private int subtype;\n  private int keySize;\n  private boolean isAllEncrypted;\n\n  private PrivateKey clientKey;\n  private PublicKey clientPublicKey;\n  private PublicKey serverKey;\n  private int serverKeyLength;\n  private byte[] serverKeyN;\n  private byte[] serverKeyE;\n  private int clientKeyLength;\n  private byte[] clientKeyN;\n  private byte[] clientKeyE;\n  private byte[] serverRandom;\n  private byte[] clientRandom;\n\n  private AESInStream rais;\n  private AESOutStream raos;\n  private InStream rawis;\n  private OutStream rawos;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CSecurityStack.java",
    "content": "/* Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2011 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class CSecurityStack extends CSecurity {\n\n  public CSecurityStack(int Type, String Name, CSecurity s0,\n  \t\t\t       CSecurity s1)\n  {\n    name = Name;\n    type = Type;\n    state = 0;\n    state0 = s0;\n    state1 = s1;\n  }\n\n  public boolean processMsg(CConnection cc)\n  {\n    boolean res = true;\n    if (state == 0) {\n      if (state0 != null)\n        res = state0.processMsg(cc);\n\n      if (!res)\n        return res;\n\n      state++;\n    }\n\n    if (state == 1) {\n      if(state1 != null)\n        res = state1.processMsg(cc);\n\n      if(!res)\n        return res;\n\n      state++;\n    }\n\n    return res;\n  }\n\n  public boolean isSecure()\n  {\n    if (state0 != null && state0.isSecure())\n      return true;\n    if (state == 1 && state1 != null && state1.isSecure())\n      return true;\n    return false;\n  }\n\n  public final int getType() { return type; }\n  public final String description() { return name; }\n\n  private int state;\n  private CSecurity state0;\n  private CSecurity state1;\n  private String name;\n  private int type;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CSecurityTLS.java",
    "content": "/*\n * Copyright (C) 2004 Red Hat Inc.\n * Copyright (C) 2005 Martin Koegler\n * Copyright (C) 2010 m-privacy GmbH\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2011-2019 Brian P. Hinz\n * Copyright (C) 2015 D. R. Commander.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport javax.net.ssl.*;\nimport java.security.KeyManagementException;\nimport java.security.KeyStore;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.MessageDigest;\nimport java.security.cert.*;\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.InputStream;\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.nio.charset.Charset;\nimport java.util.ArrayList;\nimport java.util.Base64;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.List;\nimport javax.naming.InvalidNameException;\nimport javax.naming.ldap.LdapName;\nimport javax.naming.ldap.Rdn;\nimport javax.net.ssl.HostnameVerifier;\nimport javax.swing.JOptionPane;\n\nimport com.tigervnc.rdr.*;\nimport com.tigervnc.network.*;\nimport com.tigervnc.vncviewer.*;\n\nimport static javax.swing.JOptionPane.*;\n\npublic class CSecurityTLS extends CSecurity {\n\n  public static StringParameter X509CA\n  = new StringParameter(\"X509CA\",\n                        \"X509 CA certificate\", \"\", Configuration.ConfigurationObject.ConfViewer);\n  public static StringParameter X509CRL\n  = new StringParameter(\"X509CRL\",\n                        \"X509 CRL file\", \"\", Configuration.ConfigurationObject.ConfViewer);\n\n  private void initGlobal()\n  {\n    try {\n      ctx = SSLContext.getInstance(\"TLS\");\n    } catch(NoSuchAlgorithmException e) {\n      throw new Exception(e.toString());\n    }\n  }\n\n  public CSecurityTLS(boolean _anon)\n  {\n    anon = _anon;\n    manager = null;\n\n    setDefaults();\n    cafile = X509CA.getData();\n    crlfile = X509CRL.getData();\n  }\n\n  public static String getDefaultCA() {\n    if (UserPreferences.get(\"viewer\", \"x509ca\") != null)\n      return UserPreferences.get(\"viewer\", \"x509ca\");\n    return FileUtils.getVncConfigDir()+\"x509_ca.pem\";\n  }\n\n  public static String getDefaultCRL() {\n    if (UserPreferences.get(\"viewer\", \"x509crl\") != null)\n      return UserPreferences.get(\"viewer\", \"x509crl\");\n    return FileUtils.getVncConfigDir()+\"x509_crl.pem\";\n  }\n\n  public static void setDefaults()\n  {\n    if (new File(getDefaultCA()).exists())\n      X509CA.setDefaultStr(getDefaultCA());\n    if (new File(getDefaultCRL()).exists())\n      X509CRL.setDefaultStr(getDefaultCRL());\n  }\n\n  public boolean processMsg(CConnection cc) {\n    is = (FdInStream)cc.getInStream();\n    os = (FdOutStream)cc.getOutStream();\n    client = cc;\n\n    initGlobal();\n\n    if (manager == null) {\n      if (!is.checkNoWait(1))\n        return false;\n\n      if (is.readU8() == 0) {\n        int result = is.readU32();\n        String reason;\n        if (result == Security.secResultFailed ||\n            result == Security.secResultTooMany)\n          reason = is.readString();\n        else\n          reason = new String(\"Authentication failure (protocol error)\");\n        throw new AuthFailureException(reason);\n      }\n\n      setParam();\n    }\n\n    try {\n      manager = new SSLEngineManager(engine, is, os);\n      manager.doHandshake();\n    } catch(java.lang.Exception e) {\n      throw new SystemException(e.toString());\n    }\n\n    cc.setStreams(new TLSInStream(is, manager),\n\t\t              new TLSOutStream(os, manager));\n    return true;\n  }\n\n  private void setParam() {\n\n    if (anon) {\n      try {\n        ctx.init(null, null, null);\n      } catch(KeyManagementException e) {\n        throw new AuthFailureException(e.toString());\n      }\n    } else {\n      try {\n        TrustManager[] myTM = new TrustManager[] {\n          new MyX509TrustManager()\n        };\n        ctx.init (null, myTM, null);\n      } catch (java.security.GeneralSecurityException e) {\n        throw new AuthFailureException(e.toString());\n      }\n    }\n    SSLSocketFactory sslfactory = ctx.getSocketFactory();\n    engine = ctx.createSSLEngine(client.getServerName(),\n                                 client.getServerPort());\n    engine.setUseClientMode(true);\n\n    String[] supported = engine.getSupportedProtocols();\n    ArrayList<String> enabled = new ArrayList<String>();\n    for (int i = 0; i < supported.length; i++)\n      if (supported[i].matches(\"TLS.*\"))\n\t      enabled.add(supported[i]);\n    engine.setEnabledProtocols(enabled.toArray(new String[0]));\n\n    if (anon) {\n      supported = engine.getSupportedCipherSuites();\n      enabled = new ArrayList<String>();\n      // prefer ECDH over DHE\n      for (int i = 0; i < supported.length; i++)\n        if (supported[i].matches(\"TLS_ECDH_anon.*\"))\n\t        enabled.add(supported[i]);\n      for (int i = 0; i < supported.length; i++)\n        if (supported[i].matches(\"TLS_DH_anon.*\"))\n\t        enabled.add(supported[i]);\n      engine.setEnabledCipherSuites(enabled.toArray(new String[0]));\n    } else {\n      engine.setEnabledCipherSuites(engine.getSupportedCipherSuites());\n    }\n\n  }\n\n  class MyX509TrustManager implements X509TrustManager\n  {\n\n    X509TrustManager tm;\n\n    MyX509TrustManager() throws java.security.GeneralSecurityException\n    {\n      KeyStore ks = KeyStore.getInstance(\"JKS\");\n      CertificateFactory cf = CertificateFactory.getInstance(\"X.509\");\n      try {\n        ks.load(null, null);\n        String a = TrustManagerFactory.getDefaultAlgorithm();\n        TrustManagerFactory tmf = TrustManagerFactory.getInstance(a);\n        tmf.init((KeyStore)null);\n        for (TrustManager m : tmf.getTrustManagers())\n          if (m instanceof X509TrustManager)\n            for (X509Certificate c : ((X509TrustManager)m).getAcceptedIssuers())\n              ks.setCertificateEntry(getThumbprint((X509Certificate)c), c);\n        File cacert = new File(cafile);\n        if (cacert.exists() && cacert.canRead()) {\n          InputStream caStream = new MyFileInputStream(cacert);\n          Collection<? extends Certificate> cacerts =\n            cf.generateCertificates(caStream);\n          for (Certificate cert : cacerts) {\n            String thumbprint = getThumbprint((X509Certificate)cert);\n            ks.setCertificateEntry(thumbprint, (X509Certificate)cert);\n          }\n        }\n        PKIXBuilderParameters params =\n          new PKIXBuilderParameters(ks, new X509CertSelector());\n        File crlcert = new File(crlfile);\n        if (!crlcert.exists() || !crlcert.canRead()) {\n          params.setRevocationEnabled(false);\n        } else {\n          InputStream crlStream = new FileInputStream(crlfile);\n          Collection<? extends CRL> crls = cf.generateCRLs(crlStream);\n          CertStoreParameters csp = new CollectionCertStoreParameters(crls);\n          CertStore store = CertStore.getInstance(\"Collection\", csp);\n          params.addCertStore(store);\n          params.setRevocationEnabled(true);\n        }\n        tmf = TrustManagerFactory.getInstance(\"PKIX\");\n        tmf.init(new CertPathTrustManagerParameters(params));\n        tm = (X509TrustManager)tmf.getTrustManagers()[0];\n      } catch (java.lang.Exception e) {\n        throw new Exception(e.getMessage());\n      }\n    }\n\n    public void checkClientTrusted(X509Certificate[] chain, String authType)\n      throws CertificateException\n    {\n      tm.checkClientTrusted(chain, authType);\n    }\n\n    private final char[] hexCode = \"0123456789ABCDEF\".toCharArray();\n\n    private String printHexBinary(byte[] data)\n    {\n      StringBuilder r = new StringBuilder(data.length*2);\n      for (byte b : data) {\n        r.append(hexCode[(b >> 4) & 0xF]);\n        r.append(hexCode[(b & 0xF)]); \n      }\n      return r.toString();\n    }\n\n    public void checkServerTrusted(X509Certificate[] chain, String authType)\n      throws CertificateException\n    {\n      Collection<? extends Certificate> certs = null;\n      X509Certificate cert = chain[0];\n      String pk =\n        Base64.getEncoder().encodeToString(cert.getPublicKey().getEncoded());\n      try {\n        cert.checkValidity();\n        verifyHostname(cert);\n      } catch(CertificateParsingException e) {\n        throw new SystemException(e.getMessage());\n      } catch(CertificateNotYetValidException e) {\n        throw new AuthFailureException(\"server certificate has not been activated\");\n      } catch(CertificateExpiredException e) {\n        if (!msg.showMsgBox(YES_NO_OPTION, \"certificate has expired\",\n\t\t\t      \"The certificate of the server has expired, \"+\n\t\t\t      \"do you want to continue?\"))\n          throw new AuthFailureException(\"server certificate has expired\");\n      }\n      File vncDir = new File(FileUtils.getVncStateDir());\n      if (!vncDir.exists()) {\n        try {\n          vncDir.mkdir();\n        } catch(SecurityException e) {\n          throw new AuthFailureException(\"Could not obtain VNC state directory \"+\n                                         \"path for known hosts storage\");\n        }\n      }\n      File dbPath = new File(vncDir, \"x509_known_hosts\");\n      String info =\n        \"  Subject: \"+cert.getSubjectX500Principal().getName()+\"\\n\"+\n        \"  Issuer: \"+cert.getIssuerX500Principal().getName()+\"\\n\"+\n        \"  Serial Number: \"+cert.getSerialNumber()+\"\\n\"+\n        \"  Version: \"+cert.getVersion()+\"\\n\"+\n        \"  Signature Algorithm: \"+cert.getPublicKey().getAlgorithm()+\"\\n\"+\n        \"  Not Valid Before: \"+cert.getNotBefore()+\"\\n\"+\n        \"  Not Valid After: \"+cert.getNotAfter()+\"\\n\"+\n        \"  SHA-1 Fingerprint: \"+getThumbprint(cert)+\"\\n\";\n      try {\n        if (dbPath.exists()) {\n          FileReader db = new FileReader(dbPath);\n          BufferedReader dbBuf = new BufferedReader(db);\n          String line;\n          String server = client.getServerName().toLowerCase();\n          while ((line = dbBuf.readLine())!=null) {\n            String fields[] = line.split(\"\\\\|\");\n            if (fields.length==6) {\n              if (server.equals(fields[2]) && pk.equals(fields[5])) {\n                vlog.debug(\"Server certificate found in known hosts file\");\n                dbBuf.close();\n                return;\n              } else if (server.equals(fields[2]) && !pk.equals(fields[5]) ||\n                         !server.equals(fields[2]) && pk.equals(fields[5])) {\n                throw new CertStoreException();\n              }\n            }\n          }\n          dbBuf.close();\n        }\n        tm.checkServerTrusted(chain, authType);\n      } catch (IOException e) {\n        throw new AuthFailureException(\"Could not load known hosts database\");\n      } catch (CertStoreException e) {\n        vlog.debug(\"Server host key mismatch\");\n        vlog.debug(info);\n        String text =\n          \"This host is previously known with a different \"+\n          \"certificate, and the new certificate has been \"+\n          \"signed by an unknown authority\\n\"+\n          \"\\n\"+info+\"\\n\"+\n          \"Someone could be trying to impersonate the site and you should not continue.\\n\"+\n          \"\\n\"+\n          \"Do you want to make an exception for this server?\";\n        if (!msg.showMsgBox(YES_NO_OPTION, \"Unexpected certificate issuer\", text))\n          throw new AuthFailureException(\"Unexpected certificate issuer\");\n        store_pubkey(dbPath, client.getServerName().toLowerCase(), pk);\n      } catch (java.lang.Exception e) {\n        if (e.getCause() instanceof CertPathBuilderException) {\n          vlog.debug(\"Server host not previously known\");\n          vlog.debug(info);\n          String text =\n            \"This certificate has been signed by an unknown authority\\n\"+\n            \"\\n\"+info+\"\\n\"+\n            \"Someone could be trying to impersonate the site and you should not continue.\\n\"+\n            \"\\n\"+\n            \"Do you want to make an exception for this server?\";\n          if (!msg.showMsgBox(YES_NO_OPTION, \"Unknown certificate issuer\", text))\n            throw new AuthFailureException(\"Unknown certificate issuer\");\n          store_pubkey(dbPath, client.getServerName().toLowerCase(), pk);\n        } else {\n          throw new SystemException(e.getMessage());\n        }\n      }\n    }\n\n    private void store_pubkey(File dbPath, String serverName, String pk)\n    {\n      ArrayList<String> lines = new ArrayList<String>();\n      try {\n        if (dbPath.exists()) {\n          FileReader db = new FileReader(dbPath);\n          BufferedReader dbBuf = new BufferedReader(db);\n          String line;\n          while ((line = dbBuf.readLine())!=null) {\n            String fields[] = line.split(\"\\\\|\");\n            if (fields.length==6)\n              if (!serverName.equals(fields[2]) && !pk.equals(fields[5]))\n                lines.add(line);\n          }\n          dbBuf.close();\n        }\n      } catch (IOException e) {\n        throw new AuthFailureException(\"Could not load known hosts database\");\n      }\n      try {\n        if (!dbPath.exists())\n          dbPath.createNewFile();\n        FileWriter fw = new FileWriter(dbPath.getAbsolutePath(), false);\n        Iterator i = lines.iterator();\n        while (i.hasNext())\n          fw.write((String)i.next()+\"\\n\");\n        fw.write(\"|g0|\"+serverName+\"|*|0|\"+pk+\"\\n\");\n        fw.close();\n      } catch (IOException e) {\n        vlog.error(\"Failed to store server certificate to known hosts database\");\n      }\n    }\n\n    public X509Certificate[] getAcceptedIssuers ()\n    {\n      return tm.getAcceptedIssuers();\n    }\n\n    private String getThumbprint(X509Certificate cert)\n    {\n      String thumbprint = null;\n      try {\n        MessageDigest md = MessageDigest.getInstance(\"SHA-1\");\n        md.update(cert.getEncoded());\n        thumbprint = printHexBinary(md.digest());\n        thumbprint = thumbprint.replaceAll(\"..(?!$)\", \"$0 \");\n      } catch(CertificateEncodingException e) {\n        throw new SystemException(e.getMessage());\n      } catch(NoSuchAlgorithmException e) {\n        throw new SystemException(e.getMessage());\n      }\n      return thumbprint;\n    }\n\n    private void verifyHostname(X509Certificate cert)\n      throws CertificateParsingException\n    {\n      try {\n        Collection sans = cert.getSubjectAlternativeNames();\n        if (sans == null) {\n          String dn = cert.getSubjectX500Principal().getName();\n          LdapName ln = new LdapName(dn);\n          for (Rdn rdn : ln.getRdns()) {\n            if (rdn.getType().equalsIgnoreCase(\"CN\")) {\n              String peer = client.getServerName().toLowerCase();\n              if (peer.equals(((String)rdn.getValue()).toLowerCase()))\n                return;\n            }\n          }\n        } else {\n          Iterator i = sans.iterator();\n          while (i.hasNext()) {\n            List nxt = (List)i.next();\n            if (((Integer)nxt.get(0)).intValue() == 2) {\n              String peer = client.getServerName().toLowerCase();\n              if (peer.equals(((String)nxt.get(1)).toLowerCase()))\n                return;\n            } else if (((Integer)nxt.get(0)).intValue() == 7) {\n              String peer = ((CConn)client).getSocket().getPeerAddress();\n              if (peer.equals(((String)nxt.get(1)).toLowerCase()))\n                return;\n            }\n          }\n        }\n        Object[] answer = {\"YES\", \"NO\"};\n        int ret = JOptionPane.showOptionDialog(null,\n          \"Hostname (\"+client.getServerName()+\") does not match the\"+\n          \" server certificate, do you want to continue?\",\n          \"Certificate hostname mismatch\",\n          JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,\n          null, answer, answer[0]);\n        if (ret != JOptionPane.YES_OPTION)\n          throw new WarningException(\"Certificate hostname mismatch.\");\n      } catch (CertificateParsingException e) {\n        throw new SystemException(e.getMessage());\n      } catch (InvalidNameException e) {\n        throw new SystemException(e.getMessage());\n      }\n    }\n\n    private class MyFileInputStream extends InputStream {\n      // Blank lines in a certificate file will cause Java 6 to throw a\n      // \"DerInputStream.getLength(): lengthTag=127, too big\" exception.\n      ByteBuffer buf;\n\n      public MyFileInputStream(String name) {\n        this(new File(name));\n      }\n\n      public MyFileInputStream(File file) {\n        StringBuffer sb = new StringBuffer();\n        BufferedReader reader = null;\n        try {\n          reader = new BufferedReader(new FileReader(file));\n          String l;\n          while ((l = reader.readLine()) != null) {\n            if (l.trim().length() > 0 )\n              sb.append(l+\"\\n\");\n          }\n        } catch (java.lang.Exception e) {\n          throw new Exception(e.toString());\n        } finally {\n          try {\n            if (reader != null)\n              reader.close();\n          } catch(IOException ioe) {\n            throw new Exception(ioe.getMessage());\n          }\n        }\n        Charset utf8 = Charset.forName(\"UTF-8\");\n        buf = ByteBuffer.wrap(sb.toString().getBytes(utf8));\n        buf.limit(buf.capacity());\n      }\n\n      @Override\n      public int read(byte[] b) throws IOException {\n        return this.read(b, 0, b.length);\n      }\n\n      @Override\n      public int read(byte[] b, int off, int len) throws IOException {\n        if (!buf.hasRemaining())\n          return -1;\n        len = Math.min(len, buf.remaining());\n        buf.get(b, off, len);\n        return len;\n      }\n\n      @Override\n      public int read() throws IOException {\n        if (!buf.hasRemaining())\n          return -1;\n        return buf.get() & 0xFF;\n      }\n    }\n  }\n\n  public final int getType() { return anon ? Security.secTypeTLSNone : Security.secTypeX509None; }\n  public final String description()\n    { return anon ? \"TLS Encryption without VncAuth\" : \"X509 Encryption without VncAuth\"; }\n  public boolean isSecure() { return !anon; }\n\n  protected CConnection client;\n\n  private SSLContext ctx;\n  private SSLEngine engine;\n  private SSLEngineManager manager;\n  private boolean anon;\n\n  private String cafile, crlfile;\n  private FdInStream is;\n  private FdOutStream os;\n\n  static LogWriter vlog = new LogWriter(\"CSecurityTLS\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CSecurityVeNCrypt.java",
    "content": "/*\n * Copyright (C) 2005-2006 Martin Koegler\n * Copyright (C) 2006 OCCAM Financial Technology\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2011 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.util.*;\n\nimport com.tigervnc.rdr.*;\n\npublic class CSecurityVeNCrypt extends CSecurity {\n\n  public CSecurityVeNCrypt(SecurityClient sec)\n  {\n    haveRecvdMajorVersion = false;\n    haveRecvdMinorVersion = false;\n    haveSentVersion = false;\n    haveAgreedVersion = false;\n    haveListOfTypes = false;\n    haveNumberOfTypes = false;\n    haveChosenType = false;\n    majorVersion = 0;\n    minorVersion = 0;\n    chosenType = Security.secTypeVeNCrypt;\n    nAvailableTypes = 0;\n    availableTypes = null;\n    iAvailableType = 0;\n    security = sec;\n  }\n\n  public boolean processMsg(CConnection cc) {\n    InStream is = cc.getInStream();\n    OutStream os = cc.getOutStream();\n\n    /* get major, minor versions, send what we can support (or 0.0 for can't support it) */\n    if (!haveRecvdMajorVersion) {\n      majorVersion = is.readU8();\n      haveRecvdMajorVersion = true;\n\n      return false;\n    }\n\n    if (!haveRecvdMinorVersion) {\n      minorVersion = is.readU8();\n      haveRecvdMinorVersion = true;\n    }\n\n    /* major version in upper 8 bits and minor version in lower 8 bits */\n    int Version = (majorVersion << 8) | minorVersion;\n\n    if (!haveSentVersion) {\n      /* Currently we don't support former VeNCrypt 0.1 */\n\t    if (Version >= 0x0002) {\n        majorVersion = 0;\n        minorVersion = 2;\n\t      os.writeU8(majorVersion);\n\t      os.writeU8(minorVersion);\n        os.flush();\n\t    } else {\n        /* Send 0.0 to indicate no support */\n        majorVersion = 0;\n        minorVersion = 0;\n        os.writeU8(majorVersion);\n        os.writeU8(minorVersion);\n        os.flush();\n\t      throw new Exception(\"Server reported an unsupported VeNCrypt version\");\n      }\n\n      haveSentVersion = true;\n      return false;\n    }\n\n    /* Check that the server is OK */\n    if (!haveAgreedVersion) {\n      if (is.readU8() != 0)\n\t      throw new Exception(\"Server reported it could not support the VeNCrypt version\");\n\n      haveAgreedVersion = true;\n      return false;\n    }\n\n    /* get a number of types */\n    if (!haveNumberOfTypes) {\n      nAvailableTypes = is.readU8();\n      iAvailableType = 0;\n\n      if (nAvailableTypes <= 0)\n\t      throw new Exception(\"The server reported no VeNCrypt sub-types\");\n\n      availableTypes = new int[nAvailableTypes];\n      haveNumberOfTypes = true;\n      return false;\n    }\n\n    if (nAvailableTypes > 0) {\n      /* read in the types possible */\n      if (!haveListOfTypes) {\n        if (is.checkNoWait(4)) {\n\t        availableTypes[iAvailableType++] = is.readU32();\n\t        haveListOfTypes = (iAvailableType >= nAvailableTypes);\n\t        vlog.debug(\"Server offers security type \"+\n\t\t        Security.secTypeName(availableTypes[iAvailableType - 1])+\" (\"+\n\t\t        availableTypes[iAvailableType - 1]+\")\");\n\n\t        if (!haveListOfTypes)\n\t          return false;\n\n        } else\n\t        return false;\n        }\n\n        /* make a choice and send it to the server, meanwhile set up the stack */\n        if (!haveChosenType) {\n          chosenType = Security.secTypeInvalid;\n          int i;\n          Iterator<Integer> j;\n          List<Integer> secTypes = new ArrayList<Integer>();\n\n          secTypes = security.GetEnabledExtSecTypes();\n\n          /* Honor server's security type order */\n          for (i = 0; i < nAvailableTypes; i++) {\n            for (j = secTypes.iterator(); j.hasNext(); ) {\n              int refType = (Integer)j.next();\n\t            if (refType == availableTypes[i]) {\n\t              chosenType = refType;\n\t              break;\n\t            }\n\t          }\n\n\t          if (chosenType != Security.secTypeInvalid)\n\t            break;\n          }\n\n          vlog.debug(\"Choosing security type \"+Security.secTypeName(chosenType)+\n\t\t                 \" (\"+chosenType+\")\");\n\n          /* Set up the stack according to the chosen type: */\n          if (chosenType == Security.secTypeInvalid || chosenType == Security.secTypeVeNCrypt)\n\t          throw new AuthFailureException(\"No valid VeNCrypt sub-type\");\n\n          csecurity = security.GetCSecurity(chosenType);\n\n          /* send chosen type to server */\n          os.writeU32(chosenType);\n          os.flush();\n\n          haveChosenType = true;\n      }\n    } else {\n      /*\n       * Server told us that there are 0 types it can support - this should not\n       * happen, since if the server supports 0 sub-types, it doesn't support\n       * this security type\n       */\n      throw new AuthFailureException(\"The server reported 0 VeNCrypt sub-types\");\n    }\n\n    return csecurity.processMsg(cc);\n  }\n\n  public final int getType() { return chosenType; }\n  public final String description()\n  {\n    if (csecurity != null)\n      return csecurity.description();\n    return \"VeNCrypt\";\n  }\n\n  public final boolean isSecure()\n  {\n    if (csecurity != null && csecurity.isSecure())\n      return true;\n    return false;\n  }\n\n  public static StringParameter secTypesStr;\n\n  private CSecurity csecurity;\n  SecurityClient security;\n  private boolean haveRecvdMajorVersion;\n  private boolean haveRecvdMinorVersion;\n  private boolean haveSentVersion;\n  private boolean haveAgreedVersion;\n  private boolean haveListOfTypes;\n  private boolean haveNumberOfTypes;\n  private boolean haveChosenType;\n  private int majorVersion, minorVersion;\n  private int chosenType;\n  private int nAvailableTypes;\n  private int[] availableTypes;\n  private int iAvailableType;\n  //private final String desc;\n\n  static LogWriter vlog = new LogWriter(\"CSecurityVeNCrypt\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CSecurityVncAuth.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.nio.*;\n\nimport com.tigervnc.rdr.*;\nimport com.tigervnc.vncviewer.*;\n\npublic class CSecurityVncAuth extends CSecurity {\n\n  public CSecurityVncAuth() { }\n\n  private static final int vncAuthChallengeSize = 16;\n\n  public boolean processMsg(CConnection cc)\n  {\n    InStream is = cc.getInStream();\n    OutStream os = cc.getOutStream();\n\n    // Read the challenge & obtain the user's password\n    ByteBuffer challenge = ByteBuffer.allocate(vncAuthChallengeSize);\n    is.readBytes(challenge, vncAuthChallengeSize);\n    StringBuffer passwd = new StringBuffer();\n    upg.getUserPasswd(cc.isSecure(), null, passwd);\n\n    // Calculate the correct response\n    byte[] key = new byte[8];\n    int pwdLen = passwd.length();\n    byte[] utf8str = new byte[pwdLen];\n    try {\n      utf8str = passwd.toString().getBytes(\"UTF8\");\n    } catch(java.io.UnsupportedEncodingException e) {\n      e.printStackTrace();\n    }\n    for (int i=0; i<8; i++)\n      key[i] = i<pwdLen ? utf8str[i] : 0;\n    DesCipher des = new DesCipher(key);\n    for (int j = 0; j < vncAuthChallengeSize; j += 8)\n      des.encrypt(challenge.array(),j,challenge.array(),j);\n\n    // Return the response to the server\n    os.writeBytes(challenge.array(), 0, vncAuthChallengeSize);\n    os.flush();\n    return true;\n  }\n\n  public int getType() { return Security.secTypeVncAuth; }\n  public String description() { return \"No Encryption\"; }\n\n  static LogWriter vlog = new LogWriter(\"VncAuth\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Configuration.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2004-2005 Cendio AB.\n * Copyright 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// Configuration - class for dealing with configuration parameters.\n//\n\npackage com.tigervnc.rfb;\n\nimport java.io.FileInputStream;\nimport java.io.PrintWriter;\nimport java.lang.reflect.Field;\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\n\nimport com.tigervnc.vncviewer.VncViewer;\n\npublic class Configuration {\n\n  static LogWriter vlog = new LogWriter(\"Configuration\");\n\n  private static final String IDENTIFIER_STRING = \"TigerVNC Configuration file Version 1.0\";\n\n  public enum ConfigurationObject { ConfGlobal, ConfServer, ConfViewer };\n\n  // -=- The Global/server/viewer Configuration objects\n  private static Configuration global_ = null;\n  private static Configuration server_ = null;\n  private static Configuration viewer_ = null;\n\n  public static Configuration global() {\n    if (global_ == null)\n      global_ = new Configuration(\"Global\");\n    return global_;\n  }\n\n  public static Configuration server() {\n    if (server_ == null)\n      server_ = new Configuration(\"Server\");\n    return server_;\n  }\n\n  public static Configuration viewer() {\n    if (viewer_ == null)\n      viewer_ = new Configuration(\"Viewer\");\n    return viewer_;\n  }\n\n  // Enable server/viewer specific parameters\n  public static void enableServerParams() { global().appendConfiguration(server()); }\n  public static void enableViewerParams() { global().appendConfiguration(viewer()); }\n\n  // Append configuration object to this instance.\n  // NOTE: conf instance can be only one configuration object\n  public void appendConfiguration(Configuration conf) {\n    conf._next = _next; _next = conf;\n  }\n\n  // -=- Configuration implementation\n  public Configuration(String name_, Configuration attachToGroup) {\n    name = name_; head = null; _next = null;\n    if (attachToGroup != null) {\n      _next = attachToGroup._next;\n      attachToGroup._next = this;\n    }\n  }\n\n  public Configuration(String name_) {\n    this(name_, null);\n  }\n\n  // - Return the buffer containing the Configuration's name\n  final public String getName() { return name; }\n\n  // - Assignment operator.  For every Parameter in this Configuration's\n  //   group, get()s the corresponding source parameter and copies its\n  //   content.\n  public Configuration assign(Configuration src) {\n    VoidParameter current = head;\n    while (current != null) {\n      VoidParameter srcParam = ((Configuration)src).get(current.getName());\n      if (srcParam != null) {\n        current.immutable = false;\n        String value = srcParam.getValueStr();\n        vlog.debug(\"operator=(\"+current.getName()+\", \"+value+\")\");\n        current.setParam(value);\n      }\n      current = current._next;\n    }\n    if (_next != null)\n      _next = src;\n    return this;\n  }\n\n  // - Set named parameter to value\n  public boolean set(String n, String v, boolean immutable) {\n    return set(n, n.length(), v, immutable);\n  }\n\n  public boolean set(String n, String v) {\n    return set(n, n.length(), v, false);\n  }\n\n  // - Set parameter to value (separated by \"=\")\n  public boolean set(String name, int len,\n                     String val, boolean immutable)\n  {\n    VoidParameter current = head;\n    while (current != null) {\n      if (current.getName().length() == len &&\n          current.getName().equalsIgnoreCase(name.substring(0, len)))\n      {\n        boolean b = current.setParam(val);\n        current.setHasBeenSet();\n        if (b && immutable)\n  \t  current.setImmutable();\n        return b;\n      }\n      current = current._next;\n    }\n    return (_next != null) ? _next.set(name, len, val, immutable) : false;\n  }\n\n  // - Set named parameter to value, with name truncated at len\n  boolean set(String config, boolean immutable) {\n    boolean hyphen = false;\n    if (config.charAt(0) == '-') {\n      hyphen = true;\n      config = config.substring(1);\n      if (config.charAt(0) == '-') config = config.substring(1); // allow gnu-style --<option>\n    }\n    int equal = config.indexOf('=');\n    if (equal > -1) {\n      return set(config, equal, config.substring(equal+1), immutable);\n    } else if (hyphen) {\n      VoidParameter current = head;\n      while (current != null) {\n        if (current.getName().equalsIgnoreCase(config)) {\n          boolean b = current.setParam();\n  \t  current.setHasBeenSet();\n          if (b && immutable)\n  \t    current.setImmutable();\n          return b;\n        }\n        current = current._next;\n      }\n    }\n    return (_next != null) ? _next.set(config, immutable) : false;\n  }\n\n  boolean set(String config) {\n    return set(config, false);\n  }\n\n  // - Container for process-wide Global parameters\n  public static boolean setParam(String param, String value, boolean immutable) {\n    return global().set(param, value, immutable);\n  }\n\n  public static boolean setParam(String param, String value) {\n    return setParam(param, value, false);\n  }\n\n  public static boolean setParam(String config, boolean immutable) {\n    return global().set(config, immutable);\n  }\n\n  public static boolean setParam(String config) {\n    return setParam(config, false);\n  }\n\n  public static boolean setParam(String name, int len,\n                                 String val, boolean immutable) {\n    return global().set(name, len, val, immutable);\n  }\n\n\n  // - Get named parameter\n  public VoidParameter get(String param)\n  {\n    VoidParameter current = head;\n    while (current != null) {\n      if (current.getName().equalsIgnoreCase(param))\n        return current;\n      current = current._next;\n    }\n    return (_next != null) ? _next.get(param) : null;\n  }\n\n  public static VoidParameter getParam(String param) { return global().get(param); }\n\n  public static void listParams(int width, int nameWidth) {\n    global().list(width, nameWidth);\n  }\n  public static void listParams() {\n    listParams(79, 10);\n  }\n\n  public void list(int width, int nameWidth) {\n    VoidParameter current = head;\n\n    System.err.format(\"%s Parameters:%n\", name);\n    while (current != null) {\n      String def_str = current.getDefaultStr();\n      String desc = current.getDescription().trim();\n      String format = \"  %-\"+nameWidth+\"s -\";\n      System.err.format(format, current.getName());\n      int column = current.getName().length();\n      if (column < nameWidth) column = nameWidth;\n      column += 4;\n      while (true) {\n        int s = desc.indexOf(' ');\n        int wordLen;\n        if (s > -1) wordLen = s;\n        else wordLen = desc.length();\n\n        if (column + wordLen + 1 > width) {\n          format = \"%n%\"+(nameWidth+4)+\"s\";\n          System.err.format(format, \"\");\n          column = nameWidth+4;\n        }\n        format = \" %\"+wordLen+\"s\";\n        System.err.format(format, desc.substring(0, wordLen));\n        column += wordLen + 1;\n\n        if (s == -1) break;\n        desc = desc.substring(wordLen+1);\n      }\n\n      if (def_str != null) {\n        if (column + def_str.length() + 11 > width)\n          System.err.format(\"%n%\"+(nameWidth+4)+\"s\",\"\");\n        System.err.format(\" (default=%s)%n\",def_str);\n        def_str = null;\n      } else {\n        System.err.format(\"%n\");\n      }\n      current = current._next;\n    }\n\n    if (_next != null)\n      _next.list(width, nameWidth);\n  }\n\n  public void list() {\n    list(79, 10);\n  }\n\n  // Name for this Configuration\n  private String name;\n\n  // - Pointer to first Parameter in this group\n  public VoidParameter head;\n\n  // Pointer to next Configuration in this group\n  public Configuration _next;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/ConnFailedException.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class ConnFailedException extends Exception {\n  public ConnFailedException() { super(\"Connection failed\"); }\n  public ConnFailedException(String reason) {\n    super(\"Connection faied: \"+reason);\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/CopyRectDecoder.java",
    "content": "/* Copyright 2014 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * Copyright 2016-2019 Brian P. Hinz\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport com.tigervnc.rdr.*;\n\npublic class CopyRectDecoder extends Decoder {\n\n  public CopyRectDecoder() { super(DecoderFlags.DecoderPlain); }\n\n  public void readRect(Rect r, InStream is,\n                       ServerParams server, OutStream os)\n  {\n    os.copyBytes(is, 4);\n  }\n\n  public void getAffectedRegion(Rect rect, Object buffer,\n                                int buflen, ServerParams server,\n                                Region region)\n  {\n    MemInStream is = new MemInStream((byte[])buffer, 0, buflen);\n    int srcX = is.readU16();\n    int srcY = is.readU16();\n\n    super.getAffectedRegion(rect, buffer, buflen, server, region);\n\n    region.assign_union(new Region(rect.translate(new Point(srcX-rect.tl.x,\n                                                            srcY-rect.tl.y))));\n  }\n\n  public void decodeRect(Rect r, Object buffer,\n                         int buflen, ServerParams server,\n                         ModifiablePixelBuffer pb)\n  {\n    MemInStream is = new MemInStream((byte[])buffer, 0, buflen);\n    int srcX = is.readU16();\n    int srcY = is.readU16();\n    pb.copyRect(r, new Point(r.tl.x-srcX, r.tl.y-srcY));\n  }\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Cursor.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class Cursor extends ManagedPixelBuffer {\n\n  public Cursor(PixelFormat pf, int w, int h) {\n    super(pf, w, h);\n    hotspot = new Point(0, 0);\n  }\n\n  public void setSize(int w, int h) {\n    int oldMaskLen = maskLen();\n    super.setSize(w, h);\n    if (mask == null || maskLen() > oldMaskLen)\n      mask = new byte[maskLen()];\n  }\n\n  public int maskLen() { return (width() + 7) / 8 * height(); }\n\n  public Point hotspot;\n  public byte[] mask;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/DecodeManager.java",
    "content": "/* Copyright 2015 Pierre Ossman for Cendio AB\n * Copyright 2016-2019 Brian P. Hinz\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.lang.Runtime;\nimport java.util.*;\nimport java.util.concurrent.*;\nimport java.util.concurrent.locks.*;\n\nimport com.tigervnc.rdr.*;\nimport com.tigervnc.rdr.Exception;\n\nimport static com.tigervnc.rfb.Decoder.DecoderFlags.*;\n\npublic class DecodeManager {\n\n  static LogWriter vlog = new LogWriter(\"DecodeManager\");\n\n  public DecodeManager(CConnection conn) {\n    int cpuCount;\n\n    this.conn = conn; threadException = null;\n    decoders = new Decoder[Encodings.encodingMax+1];\n\n    queueMutex = new ReentrantLock();\n    producerCond = queueMutex.newCondition();\n    consumerCond = queueMutex.newCondition();\n\n    cpuCount = Runtime.getRuntime().availableProcessors();\n    if (cpuCount == 0) {\n      vlog.error(\"Unable to determine the number of CPU cores on this system\");\n      cpuCount = 1;\n    } else {\n      vlog.info(\"Detected \"+cpuCount+\" CPU core(s)\");\n      // No point creating more threads than this, they'll just end up\n      // wasting CPU fighting for locks\n      if (cpuCount > 4)\n        cpuCount = 4;\n      // The overhead of threading is small, but not small enough to\n      // ignore on single CPU systems\n      if (cpuCount == 1)\n        vlog.info(\"Decoding data on main thread\");\n      else\n        vlog.info(\"Creating \"+cpuCount+\" decoder thread(s)\");\n    }\n\n    freeBuffers = new ArrayDeque<MemOutStream>(cpuCount*2);\n    workQueue = new ArrayDeque<QueueEntry>(cpuCount);\n    threads = new ArrayList<DecodeThread>(cpuCount);\n    while (cpuCount-- > 0) {\n      // Twice as many possible entries in the queue as there\n      // are worker threads to make sure they don't stall\n      try {\n      freeBuffers.addLast(new MemOutStream());\n      freeBuffers.addLast(new MemOutStream());\n\n      threads.add(new DecodeThread(this));\n      } catch (IllegalStateException e) { }\n    }\n\n  }\n\n  public void decodeRect(Rect r, int encoding,\n                         ModifiablePixelBuffer pb)\n  {\n    Decoder decoder;\n    MemOutStream bufferStream;\n\n    QueueEntry entry;\n\n    assert(pb != null);\n\n    if (!Decoder.supported(encoding)) {\n      vlog.error(\"Unknown encoding \" + encoding);\n      throw new Exception(\"Unknown encoding\");\n    }\n\n    if (decoders[encoding] == null) {\n      decoders[encoding] = Decoder.createDecoder(encoding);\n      if (decoders[encoding] == null) {\n        vlog.error(\"Unknown encoding \" + encoding);\n        throw new Exception(\"Unknown encoding\");\n      }\n    }\n\n    decoder = decoders[encoding];\n\n    // Fast path for single CPU machines to avoid the context\n    // switching overhead\n    if (threads.size() == 1) {\n      bufferStream = freeBuffers.getFirst();\n      bufferStream.clear();\n      decoder.readRect(r, conn.getInStream(), conn.server, bufferStream);\n      decoder.decodeRect(r, (Object)bufferStream.data(), bufferStream.length(),\n                         conn.server, pb);\n      return;\n    }\n\n    // Wait for an available memory buffer\n    queueMutex.lock();\n\n    try {\n      while (freeBuffers.isEmpty())\n        try {\n        producerCond.await();\n        } catch (InterruptedException e) { }\n\n      // Don't pop the buffer in case we throw an exception\n      // whilst reading\n      bufferStream = freeBuffers.getFirst();\n    } finally {\n      queueMutex.unlock();\n    }\n\n    // First check if any thread has encountered a problem\n    throwThreadException();\n\n    // Read the rect\n    bufferStream.clear();\n    decoder.readRect(r, conn.getInStream(), conn.server, bufferStream);\n\n    // Then try to put it on the queue\n    entry = new QueueEntry();\n\n    entry.active = false;\n    entry.rect = r;\n    entry.encoding = encoding;\n    entry.decoder = decoder;\n    entry.server = conn.server;\n    entry.pb = pb;\n    entry.bufferStream = bufferStream;\n\n    decoder.getAffectedRegion(r, bufferStream.data(),\n                              bufferStream.length(), conn.server,\n                              entry.affectedRegion);\n\n    queueMutex.lock();\n\n    try {\n      // The workers add buffers to the end so it's safe to assume\n      // the front is still the same buffer\n      freeBuffers.removeFirst();\n\n      workQueue.addLast(entry);\n\n      // We only put a single entry on the queue so waking a single\n      // thread is sufficient\n      consumerCond.signal();\n    } finally {\n      queueMutex.unlock();\n    }\n  }\n\n  public void flush()\n  {\n    queueMutex.lock();\n\n    try {\n      while (!workQueue.isEmpty())\n        try {\n        producerCond.await();\n        } catch (InterruptedException e) { }\n    } finally {\n      queueMutex.unlock();\n    }\n\n    throwThreadException();\n  }\n\n  private void setThreadException(Exception e)\n  {\n    //os::AutoMutex a(queueMutex);\n    queueMutex.lock();\n\n    try {\n      if (threadException != null)\n        return;\n\n      threadException =\n        new Exception(\"Exception on worker thread: \"+e.getMessage());\n    } finally {\n      queueMutex.unlock();\n    }\n  }\n\n  private void throwThreadException()\n  {\n    //os::AutoMutex a(queueMutex);\n    queueMutex.lock();\n\n    try {\n      if (threadException == null)\n        return;\n\n      Exception e = new Exception(threadException.getMessage());\n\n      threadException = null;\n\n      throw e;\n    } finally {\n      queueMutex.unlock();\n    }\n  }\n\n  private class QueueEntry {\n\n    public QueueEntry() {\n      affectedRegion = new Region();\n    }\n    public boolean active;\n    public Rect rect;\n    public int encoding;\n    public Decoder decoder;\n    public ServerParams server;\n    public ModifiablePixelBuffer pb;\n    public MemOutStream bufferStream;\n    public Region affectedRegion;\n  }\n\n  private class DecodeThread implements Runnable {\n\n    public DecodeThread(DecodeManager manager)\n    {\n      this.manager = manager;\n\n      stopRequested = false;\n\n      (thread = new Thread(this, \"Decoder Thread\")).start();\n    }\n\n    public void stop()\n    {\n      //os::AutoMutex a(manager.queueMutex);\n      manager.queueMutex.lock();\n\n      try {\n        if (!thread.isAlive())\n          return;\n\n        stopRequested = true;\n\n        // We can't wake just this thread, so wake everyone\n        manager.consumerCond.signalAll();\n      } finally {\n        manager.queueMutex.unlock();\n      }\n    }\n\n    public void run()\n    {\n      manager.queueMutex.lock();\n\n      while (!stopRequested) {\n        QueueEntry entry;\n\n        // Look for an available entry in the work queue\n        entry = findEntry();\n        if (entry == null) {\n          // Wait and try again\n          try {\n            manager.consumerCond.await();\n          } catch (InterruptedException e) { }\n          continue;\n        }\n\n        // This is ours now\n        entry.active = true;\n\n        manager.queueMutex.unlock();\n\n        // Do the actual decoding\n        try {\n          entry.decoder.decodeRect(entry.rect, entry.bufferStream.data(),\n                                   entry.bufferStream.length(),\n                                   entry.server, entry.pb);\n        } catch (com.tigervnc.rdr.Exception e) {\n          manager.setThreadException(e);\n        } catch(java.lang.Exception e) {\n          assert(false);\n        }\n\n        manager.queueMutex.lock();\n\n        // Remove the entry from the queue and give back the memory buffer\n        manager.freeBuffers.addLast(entry.bufferStream);\n        manager.workQueue.remove(entry);\n        entry = null;\n\n        // Wake the main thread in case it is waiting for a memory buffer\n        manager.producerCond.signal();\n        // This rect might have been blocking multiple other rects, so\n        // wake up every worker thread\n        if (manager.workQueue.size() > 1)\n          manager.consumerCond.signalAll();\n      }\n\n      manager.queueMutex.unlock();\n    }\n\n    protected QueueEntry findEntry()\n    {\n      Iterator<QueueEntry> iter;\n      Region lockedRegion = new Region();\n\n      if (manager.workQueue.isEmpty())\n        return null;\n\n      if (!manager.workQueue.peek().active)\n        return manager.workQueue.peek();\n\n      next:for (iter = manager.workQueue.iterator(); iter.hasNext();) {\n        QueueEntry entry, entry2;\n\n        Iterator<QueueEntry> iter2;\n\n        entry = iter.next();\n\n        // Another thread working on this?\n        if (entry.active) {\n          lockedRegion.assign_union(entry.affectedRegion);\n          continue next;\n        }\n\n        // If this is an ordered decoder then make sure this is the first\n        // rectangle in the queue for that decoder\n        if ((entry.decoder.flags & DecoderOrdered) != 0) {\n          for (iter2 = manager.workQueue.iterator(); iter2.hasNext() &&\n               !(entry2 = iter2.next()).equals(entry);) {\n            if (entry.encoding == entry2.encoding) {\n              lockedRegion.assign_union(entry.affectedRegion);\n              continue next;\n            }\n          }\n        }\n\n        // For a partially ordered decoder we must ask the decoder for each\n        // pair of rectangles.\n        if ((entry.decoder.flags & DecoderPartiallyOrdered) != 0) {\n          for (iter2 = manager.workQueue.iterator(); iter2.hasNext() &&\n               !(entry2 = iter2.next()).equals(entry);) {\n            if (entry.encoding != entry2.encoding)\n              continue;\n            if (entry.decoder.doRectsConflict(entry.rect,\n                                              entry.bufferStream.data(),\n                                              entry.bufferStream.length(),\n                                              entry2.rect,\n                                              entry2.bufferStream.data(),\n                                              entry2.bufferStream.length(),\n                                              entry.server))\n              lockedRegion.assign_union(entry.affectedRegion);\n              continue next;\n          }\n        }\n\n        // Check overlap with earlier rectangles\n        if (!lockedRegion.intersect(entry.affectedRegion).is_empty()) {\n          lockedRegion.assign_union(entry.affectedRegion);\n          continue next;\n        }\n\n        return entry;\n\n      }\n\n      return null;\n    }\n\n    private DecodeManager manager;\n    private boolean stopRequested;\n\n    private Thread thread;\n\n  }\n\n  private CConnection conn;\n  private Decoder[] decoders;\n\n  private ArrayDeque<MemOutStream> freeBuffers;\n  private ArrayDeque<QueueEntry> workQueue;\n\n  private ReentrantLock queueMutex;\n  private Condition producerCond;\n  private Condition consumerCond;\n\n  private List<DecodeThread> threads;\n  private com.tigervnc.rdr.Exception threadException;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Decoder.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport com.tigervnc.rdr.*;\n\nabstract public class Decoder {\n\n  public static class DecoderFlags {\n    // A constant for decoders that don't need anything special\n    public static int DecoderPlain = 0;\n    // All rects for this decoder must be handled in order\n    public static int DecoderOrdered = 1 << 0;\n    // Only some of the rects must be handled in order,\n    // see doesRectsConflict()\n    public static int DecoderPartiallyOrdered = 1 << 1;\n  };\n\n  public Decoder(int flags)\n  {\n    this.flags = flags;\n  }\n\n  abstract public void readRect(Rect r, InStream is,\n                                ServerParams server, OutStream os);\n\n  abstract public void decodeRect(Rect r, Object buffer,\n                                  int buflen, ServerParams server,\n                                  ModifiablePixelBuffer pb);\n\n  public void getAffectedRegion(Rect rect, Object buffer,\n                                int buflen, ServerParams server,\n                                Region region)\n  {\n    region.reset(rect);\n  }\n\n  public boolean doRectsConflict(Rect rectA, Object bufferA,\n                                 int buflenA, Rect rectB,\n                                 Object bufferB, int buflenB,\n                                 ServerParams server)\n  {\n    return false;\n  }\n\n  static public boolean supported(int encoding)\n  {\n    switch(encoding) {\n    case Encodings.encodingRaw:\n    case Encodings.encodingCopyRect:\n    case Encodings.encodingRRE:\n    case Encodings.encodingHextile:\n    case Encodings.encodingZRLE:\n    case Encodings.encodingTight:\n      return true;\n    default:\n      return false;\n    }\n  }\n\n  static public Decoder createDecoder(int encoding) {\n    switch(encoding) {\n    case Encodings.encodingRaw:\n      return new RawDecoder();\n    case Encodings.encodingCopyRect:\n      return new CopyRectDecoder();\n    case Encodings.encodingRRE:\n      return new RREDecoder();\n    case Encodings.encodingHextile:\n      return new HextileDecoder();\n    case Encodings.encodingZRLE:\n      return new ZRLEDecoder();\n    case Encodings.encodingTight:\n      return new TightDecoder();\n    default:\n      return null;\n    }\n  }\n\n  public final int flags;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/DesCipher.java",
    "content": "//\n// This DES class has been extracted from package Acme.Crypto for use in VNC.\n// The bytebit[] array has been reversed so that the most significant bit\n// in each byte of the key is ignored, not the least significant.  Also the\n// unnecessary odd parity code has been removed.\n//\n// These changes are:\n//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.\n//\n// This software is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n//\n\n// DesCipher - the DES encryption method\n//\n// The meat of this code is by Dave Zimmerman <dzimm@widget.com>, and is:\n//\n// Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved.\n//\n// Permission to use, copy, modify, and distribute this software\n// and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and\n// without fee is hereby granted, provided that this copyright notice is kept\n// intact.\n//\n// WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY\n// OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\n// TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n// PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE\n// FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR\n// DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.\n//\n// THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE\n// CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE\n// PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT\n// NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE\n// SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE\n// SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE\n// PHYSICAL OR ENVIRONMENTAL DAMAGE (\"HIGH RISK ACTIVITIES\").  WIDGET WORKSHOP\n// SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR\n// HIGH RISK ACTIVITIES.\n//\n//\n// The rest is:\n//\n// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>.  All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions\n// are met:\n// 1. Redistributions of source code must retain the above copyright\n//    notice, this list of conditions and the following disclaimer.\n// 2. Redistributions in binary form must reproduce the above copyright\n//    notice, this list of conditions and the following disclaimer in the\n//    documentation and/or other materials provided with the distribution.\n//\n// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n// SUCH DAMAGE.\n//\n// Visit the ACME Labs Java page for up-to-date versions of this and other\n// fine Java utilities: http://www.acme.com/java/\n\n\n/// The DES encryption method.\n// <P>\n// This is surprisingly fast, for pure Java.  On a SPARC 20, wrapped\n// in Acme.Crypto.EncryptedOutputStream or Acme.Crypto.EncryptedInputStream,\n// it does around 7000 bytes/second.\n// <P>\n// Most of this code is by Dave Zimmerman <dzimm@widget.com>, and is\n// Copyright (c) 1996 Widget Workshop, Inc.  See the source file for details.\n// <P>\n// <A HREF=\"/resources/classes/Acme/Crypto/DesCipher.java\">Fetch the software.</A><BR>\n// <A HREF=\"/resources/classes/Acme.tar.Z\">Fetch the entire Acme package.</A>\n// <P>\n// @see Des3Cipher\n// @see EncryptedOutputStream\n// @see EncryptedInputStream\n\npackage com.tigervnc.rfb;\n\npublic class DesCipher\n    {\n\n    // Constructor, byte-array key.\n    public DesCipher( byte[] key )\n\t{\n\tsetKey( key );\n\t}\n\n    // Key routines.\n\n    private int[] encryptKeys = new int[32];\n    private int[] decryptKeys = new int[32];\n\n    /// Set the key.\n    public void setKey( byte[] key )\n\t{\n\tdeskey( key, true, encryptKeys );\n\tdeskey( key, false, decryptKeys );\n\t}\n\n    // Turn an 8-byte key into internal keys.\n    private void deskey( byte[] keyBlock, boolean encrypting, int[] KnL )\n\t{\n\tint i, j, l, m, n;\n\tint[] pc1m = new int[56];\n\tint[] pcr = new int[56];\n\tint[] kn = new int[32];\n\n\tfor ( j = 0; j < 56; ++j )\n\t    {\n\t    l = pc1[j];\n\t    m = l & 07;\n\t    pc1m[j] = ( (keyBlock[l >>> 3] & bytebit[m]) != 0 )? 1: 0;\n\t    }\n\n\tfor ( i = 0; i < 16; ++i )\n\t    {\n\t    if ( encrypting )\n\t\tm = i << 1;\n\t    else\n\t\tm = (15-i) << 1;\n\t    n = m+1;\n\t    kn[m] = kn[n] = 0;\n\t    for ( j = 0; j < 28; ++j )\n\t\t{\n\t\tl = j+totrot[i];\n\t\tif ( l < 28 )\n\t\t    pcr[j] = pc1m[l];\n\t\telse\n\t\t    pcr[j] = pc1m[l-28];\n\t\t}\n\t    for ( j=28; j < 56; ++j )\n\t\t{\n\t\tl = j+totrot[i];\n\t\tif ( l < 56 )\n\t\t    pcr[j] = pc1m[l];\n\t\telse\n\t\t    pcr[j] = pc1m[l-28];\n\t\t}\n\t    for ( j = 0; j < 24; ++j )\n\t\t{\n\t\tif ( pcr[pc2[j]] != 0 )\n\t\t    kn[m] |= bigbyte[j];\n\t\tif ( pcr[pc2[j+24]] != 0 )\n\t\t    kn[n] |= bigbyte[j];\n\t\t}\n\t    }\n\tcookey( kn, KnL );\n\t}\n\n    private void cookey( int[] raw, int KnL[] )\n\t{\n\tint raw0, raw1;\n\tint rawi, KnLi;\n\tint i;\n\n\tfor ( i = 0, rawi = 0, KnLi = 0; i < 16; ++i )\n\t    {\n\t    raw0 = raw[rawi++];\n\t    raw1 = raw[rawi++];\n\t    KnL[KnLi]  = (raw0 & 0x00fc0000) <<   6;\n\t    KnL[KnLi] |= (raw0 & 0x00000fc0) <<  10;\n\t    KnL[KnLi] |= (raw1 & 0x00fc0000) >>> 10;\n\t    KnL[KnLi] |= (raw1 & 0x00000fc0) >>>  6;\n\t    ++KnLi;\n\t    KnL[KnLi]  = (raw0 & 0x0003f000) <<  12;\n\t    KnL[KnLi] |= (raw0 & 0x0000003f) <<  16;\n\t    KnL[KnLi] |= (raw1 & 0x0003f000) >>>  4;\n\t    KnL[KnLi] |= (raw1 & 0x0000003f);\n\t    ++KnLi;\n\t    }\n\t}\n\n\n    // Block encryption routines.\n\n    private int[] tempInts = new int[2];\n\n    /// Encrypt a block of eight bytes.\n    public void encrypt( byte[] clearText, int clearOff, byte[] cipherText, int cipherOff )\n\t{\n\tsquashBytesToInts( clearText, clearOff, tempInts, 0, 2 );\n\tdes( tempInts, tempInts, encryptKeys );\n\tspreadIntsToBytes( tempInts, 0, cipherText, cipherOff, 2 );\n\t}\n\n    /// Decrypt a block of eight bytes.\n    public void decrypt( byte[] cipherText, int cipherOff, byte[] clearText, int clearOff )\n\t{\n\tsquashBytesToInts( cipherText, cipherOff, tempInts, 0, 2 );\n\tdes( tempInts, tempInts, decryptKeys );\n\tspreadIntsToBytes( tempInts, 0, clearText, clearOff, 2 );\n\t}\n\n    // The DES function.\n    private void des( int[] inInts, int[] outInts, int[] keys )\n\t{\n\tint fval, work, right, leftt;\n\tint round;\n\tint keysi = 0;\n\n\tleftt = inInts[0];\n\tright = inInts[1];\n\n\twork   = ((leftt >>>  4) ^ right) & 0x0f0f0f0f;\n\tright ^= work;\n\tleftt ^= (work << 4);\n\n\twork   = ((leftt >>> 16) ^ right) & 0x0000ffff;\n\tright ^= work;\n\tleftt ^= (work << 16);\n\n\twork   = ((right >>>  2) ^ leftt) & 0x33333333;\n\tleftt ^= work;\n\tright ^= (work << 2);\n\n\twork   = ((right >>>  8) ^ leftt) & 0x00ff00ff;\n\tleftt ^= work;\n\tright ^= (work << 8);\n\tright  = (right << 1) | ((right >>> 31) & 1);\n\n\twork   = (leftt ^ right) & 0xaaaaaaaa;\n\tleftt ^= work;\n\tright ^= work;\n\tleftt  = (leftt << 1) | ((leftt >>> 31) & 1);\n\n\tfor ( round = 0; round < 8; ++round )\n\t    {\n\t    work   = (right << 28) | (right >>> 4);\n\t    work  ^= keys[keysi++];\n\t    fval   = SP7[ work\t       & 0x0000003f ];\n\t    fval  |= SP5[(work >>>  8) & 0x0000003f ];\n\t    fval  |= SP3[(work >>> 16) & 0x0000003f ];\n\t    fval  |= SP1[(work >>> 24) & 0x0000003f ];\n\t    work   = right ^ keys[keysi++];\n\t    fval  |= SP8[ work         & 0x0000003f ];\n\t    fval  |= SP6[(work >>>  8) & 0x0000003f ];\n\t    fval  |= SP4[(work >>> 16) & 0x0000003f ];\n\t    fval  |= SP2[(work >>> 24) & 0x0000003f ];\n\t    leftt ^= fval;\n\t    work   = (leftt << 28) | (leftt >>> 4);\n\t    work  ^= keys[keysi++];\n\t    fval   = SP7[ work\t       & 0x0000003f ];\n\t    fval  |= SP5[(work >>>  8) & 0x0000003f ];\n\t    fval  |= SP3[(work >>> 16) & 0x0000003f ];\n\t    fval  |= SP1[(work >>> 24) & 0x0000003f ];\n\t    work   = leftt ^ keys[keysi++];\n\t    fval  |= SP8[ work\t       & 0x0000003f ];\n\t    fval  |= SP6[(work >>>  8) & 0x0000003f ];\n\t    fval  |= SP4[(work >>> 16) & 0x0000003f ];\n\t    fval  |= SP2[(work >>> 24) & 0x0000003f ];\n\t    right ^= fval;\n\t    }\n\n\tright  = (right << 31) | (right >>> 1);\n\twork   = (leftt ^ right) & 0xaaaaaaaa;\n\tleftt ^= work;\n\tright ^= work;\n\tleftt  = (leftt << 31) | (leftt >>> 1);\n\twork   = ((leftt >>>  8) ^ right) & 0x00ff00ff;\n\tright ^= work;\n\tleftt ^= (work << 8);\n\twork   = ((leftt >>>  2) ^ right) & 0x33333333;\n\tright ^= work;\n\tleftt ^= (work << 2);\n\twork   = ((right >>> 16) ^ leftt) & 0x0000ffff;\n\tleftt ^= work;\n\tright ^= (work << 16);\n\twork   = ((right >>>  4) ^ leftt) & 0x0f0f0f0f;\n\tleftt ^= work;\n\tright ^= (work << 4);\n\toutInts[0] = right;\n\toutInts[1] = leftt;\n\t}\n\n\n    // Tables, permutations, S-boxes, etc.\n\n    private static byte[] bytebit = {\n\t(byte)0x01, (byte)0x02, (byte)0x04, (byte)0x08,\n\t(byte)0x10, (byte)0x20, (byte)0x40, (byte)0x80\n\t};\n    private static int[] bigbyte = {\n\t0x800000, 0x400000, 0x200000, 0x100000,\n\t0x080000, 0x040000, 0x020000, 0x010000,\n\t0x008000, 0x004000, 0x002000, 0x001000,\n\t0x000800, 0x000400, 0x000200, 0x000100,\n\t0x000080, 0x000040, 0x000020, 0x000010,\n\t0x000008, 0x000004, 0x000002, 0x000001\n\t};\n    private static byte[] pc1 = {\n         (byte)56, (byte)48, (byte)40, (byte)32, (byte)24, (byte)16, (byte) 8,\n      (byte) 0, (byte)57, (byte)49, (byte)41, (byte)33, (byte)25, (byte)17,\n\t (byte) 9, (byte) 1, (byte)58, (byte)50, (byte)42, (byte)34, (byte)26,\n      (byte)18, (byte)10, (byte) 2, (byte)59, (byte)51, (byte)43, (byte)35,\n\t (byte)62, (byte)54, (byte)46, (byte)38, (byte)30, (byte)22, (byte)14,\n      (byte) 6, (byte)61, (byte)53, (byte)45, (byte)37, (byte)29, (byte)21,\n\t (byte)13, (byte) 5, (byte)60, (byte)52, (byte)44, (byte)36, (byte)28,\n      (byte)20, (byte)12, (byte) 4, (byte)27, (byte)19, (byte)11, (byte)3\n\t};\n    private static int[] totrot = {\n        1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28\n\t};\n\n    private static byte[] pc2 = {\n\t(byte)13, (byte)16, (byte)10, (byte)23, (byte) 0, (byte) 4,\n\t          (byte) 2, (byte)27, (byte)14, (byte) 5, (byte)20, (byte) 9,\n\t(byte)22, (byte)18, (byte)11, (byte)3 , (byte)25, (byte) 7,\n\t          (byte)15, (byte) 6, (byte)26, (byte)19, (byte)12, (byte) 1,\n\t(byte)40, (byte)51, (byte)30, (byte)36, (byte)46, (byte)54,\n\t          (byte)29, (byte)39, (byte)50, (byte)44, (byte)32, (byte)47,\n\t(byte)43, (byte)48, (byte)38, (byte)55, (byte)33, (byte)52,\n\t          (byte)45, (byte)41, (byte)49, (byte)35, (byte)28, (byte)31,\n\t};\n\n    private static int[] SP1 = {\n        0x01010400, 0x00000000, 0x00010000, 0x01010404,\n\t0x01010004, 0x00010404, 0x00000004, 0x00010000,\n\t0x00000400, 0x01010400, 0x01010404, 0x00000400,\n\t0x01000404, 0x01010004, 0x01000000, 0x00000004,\n\t0x00000404, 0x01000400, 0x01000400, 0x00010400,\n\t0x00010400, 0x01010000, 0x01010000, 0x01000404,\n\t0x00010004, 0x01000004, 0x01000004, 0x00010004,\n\t0x00000000, 0x00000404, 0x00010404, 0x01000000,\n\t0x00010000, 0x01010404, 0x00000004, 0x01010000,\n\t0x01010400, 0x01000000, 0x01000000, 0x00000400,\n\t0x01010004, 0x00010000, 0x00010400, 0x01000004,\n\t0x00000400, 0x00000004, 0x01000404, 0x00010404,\n\t0x01010404, 0x00010004, 0x01010000, 0x01000404,\n\t0x01000004, 0x00000404, 0x00010404, 0x01010400,\n\t0x00000404, 0x01000400, 0x01000400, 0x00000000,\n\t0x00010004, 0x00010400, 0x00000000, 0x01010004\n\t};\n    private static int[] SP2 = {\n\t0x80108020, 0x80008000, 0x00008000, 0x00108020,\n\t0x00100000, 0x00000020, 0x80100020, 0x80008020,\n\t0x80000020, 0x80108020, 0x80108000, 0x80000000,\n\t0x80008000, 0x00100000, 0x00000020, 0x80100020,\n\t0x00108000, 0x00100020, 0x80008020, 0x00000000,\n\t0x80000000, 0x00008000, 0x00108020, 0x80100000,\n\t0x00100020, 0x80000020, 0x00000000, 0x00108000,\n\t0x00008020, 0x80108000, 0x80100000, 0x00008020,\n\t0x00000000, 0x00108020, 0x80100020, 0x00100000,\n\t0x80008020, 0x80100000, 0x80108000, 0x00008000,\n\t0x80100000, 0x80008000, 0x00000020, 0x80108020,\n\t0x00108020, 0x00000020, 0x00008000, 0x80000000,\n\t0x00008020, 0x80108000, 0x00100000, 0x80000020,\n\t0x00100020, 0x80008020, 0x80000020, 0x00100020,\n\t0x00108000, 0x00000000, 0x80008000, 0x00008020,\n\t0x80000000, 0x80100020, 0x80108020, 0x00108000\n\t};\n    private static int[] SP3 = {\n\t0x00000208, 0x08020200, 0x00000000, 0x08020008,\n\t0x08000200, 0x00000000, 0x00020208, 0x08000200,\n\t0x00020008, 0x08000008, 0x08000008, 0x00020000,\n\t0x08020208, 0x00020008, 0x08020000, 0x00000208,\n\t0x08000000, 0x00000008, 0x08020200, 0x00000200,\n\t0x00020200, 0x08020000, 0x08020008, 0x00020208,\n\t0x08000208, 0x00020200, 0x00020000, 0x08000208,\n\t0x00000008, 0x08020208, 0x00000200, 0x08000000,\n\t0x08020200, 0x08000000, 0x00020008, 0x00000208,\n\t0x00020000, 0x08020200, 0x08000200, 0x00000000,\n\t0x00000200, 0x00020008, 0x08020208, 0x08000200,\n\t0x08000008, 0x00000200, 0x00000000, 0x08020008,\n\t0x08000208, 0x00020000, 0x08000000, 0x08020208,\n\t0x00000008, 0x00020208, 0x00020200, 0x08000008,\n\t0x08020000, 0x08000208, 0x00000208, 0x08020000,\n\t0x00020208, 0x00000008, 0x08020008, 0x00020200\n\t};\n    private static int[] SP4 = {\n\t0x00802001, 0x00002081, 0x00002081, 0x00000080,\n\t0x00802080, 0x00800081, 0x00800001, 0x00002001,\n\t0x00000000, 0x00802000, 0x00802000, 0x00802081,\n\t0x00000081, 0x00000000, 0x00800080, 0x00800001,\n\t0x00000001, 0x00002000, 0x00800000, 0x00802001,\n\t0x00000080, 0x00800000, 0x00002001, 0x00002080,\n\t0x00800081, 0x00000001, 0x00002080, 0x00800080,\n\t0x00002000, 0x00802080, 0x00802081, 0x00000081,\n\t0x00800080, 0x00800001, 0x00802000, 0x00802081,\n\t0x00000081, 0x00000000, 0x00000000, 0x00802000,\n\t0x00002080, 0x00800080, 0x00800081, 0x00000001,\n\t0x00802001, 0x00002081, 0x00002081, 0x00000080,\n\t0x00802081, 0x00000081, 0x00000001, 0x00002000,\n\t0x00800001, 0x00002001, 0x00802080, 0x00800081,\n\t0x00002001, 0x00002080, 0x00800000, 0x00802001,\n\t0x00000080, 0x00800000, 0x00002000, 0x00802080\n\t};\n    private static int[] SP5 = {\n\t0x00000100, 0x02080100, 0x02080000, 0x42000100,\n\t0x00080000, 0x00000100, 0x40000000, 0x02080000,\n\t0x40080100, 0x00080000, 0x02000100, 0x40080100,\n\t0x42000100, 0x42080000, 0x00080100, 0x40000000,\n\t0x02000000, 0x40080000, 0x40080000, 0x00000000,\n\t0x40000100, 0x42080100, 0x42080100, 0x02000100,\n\t0x42080000, 0x40000100, 0x00000000, 0x42000000,\n\t0x02080100, 0x02000000, 0x42000000, 0x00080100,\n\t0x00080000, 0x42000100, 0x00000100, 0x02000000,\n\t0x40000000, 0x02080000, 0x42000100, 0x40080100,\n\t0x02000100, 0x40000000, 0x42080000, 0x02080100,\n\t0x40080100, 0x00000100, 0x02000000, 0x42080000,\n\t0x42080100, 0x00080100, 0x42000000, 0x42080100,\n\t0x02080000, 0x00000000, 0x40080000, 0x42000000,\n\t0x00080100, 0x02000100, 0x40000100, 0x00080000,\n\t0x00000000, 0x40080000, 0x02080100, 0x40000100\n\t};\n    private static int[] SP6 = {\n\t0x20000010, 0x20400000, 0x00004000, 0x20404010,\n\t0x20400000, 0x00000010, 0x20404010, 0x00400000,\n\t0x20004000, 0x00404010, 0x00400000, 0x20000010,\n\t0x00400010, 0x20004000, 0x20000000, 0x00004010,\n\t0x00000000, 0x00400010, 0x20004010, 0x00004000,\n\t0x00404000, 0x20004010, 0x00000010, 0x20400010,\n\t0x20400010, 0x00000000, 0x00404010, 0x20404000,\n\t0x00004010, 0x00404000, 0x20404000, 0x20000000,\n\t0x20004000, 0x00000010, 0x20400010, 0x00404000,\n\t0x20404010, 0x00400000, 0x00004010, 0x20000010,\n\t0x00400000, 0x20004000, 0x20000000, 0x00004010,\n\t0x20000010, 0x20404010, 0x00404000, 0x20400000,\n\t0x00404010, 0x20404000, 0x00000000, 0x20400010,\n\t0x00000010, 0x00004000, 0x20400000, 0x00404010,\n\t0x00004000, 0x00400010, 0x20004010, 0x00000000,\n\t0x20404000, 0x20000000, 0x00400010, 0x20004010\n\t};\n    private static int[] SP7 = {\n\t0x00200000, 0x04200002, 0x04000802, 0x00000000,\n\t0x00000800, 0x04000802, 0x00200802, 0x04200800,\n\t0x04200802, 0x00200000, 0x00000000, 0x04000002,\n\t0x00000002, 0x04000000, 0x04200002, 0x00000802,\n\t0x04000800, 0x00200802, 0x00200002, 0x04000800,\n\t0x04000002, 0x04200000, 0x04200800, 0x00200002,\n\t0x04200000, 0x00000800, 0x00000802, 0x04200802,\n\t0x00200800, 0x00000002, 0x04000000, 0x00200800,\n\t0x04000000, 0x00200800, 0x00200000, 0x04000802,\n\t0x04000802, 0x04200002, 0x04200002, 0x00000002,\n\t0x00200002, 0x04000000, 0x04000800, 0x00200000,\n\t0x04200800, 0x00000802, 0x00200802, 0x04200800,\n\t0x00000802, 0x04000002, 0x04200802, 0x04200000,\n\t0x00200800, 0x00000000, 0x00000002, 0x04200802,\n\t0x00000000, 0x00200802, 0x04200000, 0x00000800,\n\t0x04000002, 0x04000800, 0x00000800, 0x00200002\n\t};\n    private static int[] SP8 = {\n\t0x10001040, 0x00001000, 0x00040000, 0x10041040,\n\t0x10000000, 0x10001040, 0x00000040, 0x10000000,\n\t0x00040040, 0x10040000, 0x10041040, 0x00041000,\n\t0x10041000, 0x00041040, 0x00001000, 0x00000040,\n\t0x10040000, 0x10000040, 0x10001000, 0x00001040,\n\t0x00041000, 0x00040040, 0x10040040, 0x10041000,\n\t0x00001040, 0x00000000, 0x00000000, 0x10040040,\n\t0x10000040, 0x10001000, 0x00041040, 0x00040000,\n\t0x00041040, 0x00040000, 0x10041000, 0x00001000,\n\t0x00000040, 0x10040040, 0x00001000, 0x00041040,\n\t0x10001000, 0x00000040, 0x10000040, 0x10040000,\n\t0x10040040, 0x10000000, 0x00040000, 0x10001040,\n\t0x00000000, 0x10041040, 0x00040040, 0x10000040,\n\t0x10040000, 0x10001000, 0x10001040, 0x00000000,\n\t0x10041040, 0x00041000, 0x00041000, 0x00001040,\n\t0x00001040, 0x00040040, 0x10000000, 0x10041000\n\t};\n\n    // Routines taken from other parts of the Acme utilities.\n\n    /// Squash bytes down to ints.\n    public static void squashBytesToInts( byte[] inBytes, int inOff, int[] outInts, int outOff, int intLen )\n        {\n\tfor ( int i = 0; i < intLen; ++i )\n\t    outInts[outOff + i] =\n\t\t( ( inBytes[inOff + i * 4    ] & 0xff ) << 24 ) |\n\t\t( ( inBytes[inOff + i * 4 + 1] & 0xff ) << 16 ) |\n\t\t( ( inBytes[inOff + i * 4 + 2] & 0xff ) <<  8 ) |\n\t\t  ( inBytes[inOff + i * 4 + 3] & 0xff );\n        }\n\n    /// Spread ints into bytes.\n    public static void spreadIntsToBytes( int[] inInts, int inOff, byte[] outBytes, int outOff, int intLen )\n        {\n\tfor ( int i = 0; i < intLen; ++i )\n\t    {\n\t    outBytes[outOff + i * 4    ] = (byte) ( inInts[inOff + i] >>> 24 );\n\t    outBytes[outOff + i * 4 + 1] = (byte) ( inInts[inOff + i] >>> 16 );\n\t    outBytes[outOff + i * 4 + 2] = (byte) ( inInts[inOff + i] >>>  8 );\n\t    outBytes[outOff + i * 4 + 3] = (byte)   inInts[inOff + i];\n\t    }\n        }\n    }\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Encoder.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class Encoder {\n  static public boolean supported(int encoding) {\n    return false;\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Encodings.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class Encodings {\n\n  public static final int encodingRaw = 0;\n  public static final int encodingCopyRect = 1;\n  public static final int encodingRRE = 2;\n  public static final int encodingCoRRE = 4;\n  public static final int encodingHextile = 5;\n  public static final int encodingTight = 7;\n  public static final int encodingZRLE = 16;\n\n  public static final int encodingMax = 255;\n\n  public static final int pseudoEncodingXCursor = -240;\n  public static final int pseudoEncodingCursor = -239;\n  public static final int pseudoEncodingDesktopSize = -223;\n  public static final int pseudoEncodingExtendedDesktopSize = -308;\n  public static final int pseudoEncodingDesktopName = -307;\n  public static final int pseudoEncodingClientRedirect = -311;\n  public static final int pseudoEncodingFence = -312;\n  public static final int pseudoEncodingContinuousUpdates = -313;\n  public static final int pseudoEncodingCursorWithAlpha = -314;\n\n  // TightVNC-specific\n  public static final int pseudoEncodingLastRect = -224;\n  public static final int pseudoEncodingQualityLevel0 = -32;\n  public static final int pseudoEncodingQualityLevel9 = -23;\n  public static final int pseudoEncodingCompressLevel0 = -256;\n  public static final int pseudoEncodingCompressLevel9 = -247;\n\n  // TurboVNC-specific\n  public static final int pseudoEncodingFineQualityLevel0 = -512;\n  public static final int pseudoEncodingFineQualityLevel100 = -412;\n  public static final int pseudoEncodingSubsamp1X = -768;\n  public static final int pseudoEncodingSubsamp4X = -767;\n  public static final int pseudoEncodingSubsamp2X = -766;\n  public static final int pseudoEncodingSubsampGray = -765;\n  public static final int pseudoEncodingSubsamp8X = -764;\n  public static final int pseudoEncodingSubsamp16X = -763;\n\n  // VMware-specific\n  public static final int pseudoEncodingVMwareCursor = 0x574d5664;\n\n  public static int encodingNum(String name) {\n    if (name.equalsIgnoreCase(\"raw\"))      return encodingRaw;\n    if (name.equalsIgnoreCase(\"copyRect\")) return encodingCopyRect;\n    if (name.equalsIgnoreCase(\"RRE\"))      return encodingRRE;\n    if (name.equalsIgnoreCase(\"coRRE\"))    return encodingCoRRE;\n    if (name.equalsIgnoreCase(\"hextile\"))  return encodingHextile;\n    if (name.equalsIgnoreCase(\"Tight\"))    return encodingTight;\n    if (name.equalsIgnoreCase(\"ZRLE\"))     return encodingZRLE;\n    return -1;\n  }\n\n  public static String encodingName(int num) {\n    switch (num) {\n    case encodingRaw:           return \"raw\";\n    case encodingCopyRect:      return \"copyRect\";\n    case encodingRRE:           return \"RRE\";\n    case encodingCoRRE:         return \"CoRRE\";\n    case encodingHextile:       return \"hextile\";\n    case encodingTight:         return \"Tight\";\n    case encodingZRLE:          return \"ZRLE\";\n    default:                    return \"[unknown encoding]\";\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Exception.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class Exception extends com.tigervnc.rdr.Exception {\n  public Exception(String s) { super(s); }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/FullFramePixelBuffer.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.awt.image.*;\n\npublic class FullFramePixelBuffer extends ModifiablePixelBuffer {\n\n  public FullFramePixelBuffer(PixelFormat pf, int w, int h,\n                              WritableRaster data_) {\n    super(pf, w, h);\n    data = data_;\n  }\n\n  protected FullFramePixelBuffer() {}\n\n  public WritableRaster getBufferRW(Rect r)\n  {\n    synchronized(image) {\n      return data.createWritableChild(r.tl.x, r.tl.y,\n                                      r.width(), r.height(),\n                                      0, 0, null);\n    }\n  }\n\n  public void commitBufferRW(Rect r)\n  {\n  }\n\n  public Raster getBuffer(Rect r)\n  {\n    synchronized(image) {\n      Raster src =\n        data.createChild(r.tl.x, r.tl.y, r.width(), r.height(), 0, 0, null);\n      WritableRaster dst =\n        data.createCompatibleWritableRaster(r.width(), r.height());\n      dst.setDataElements(0, 0, src);\n      return dst;\n    }\n  }\n\n  protected WritableRaster data;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Hextile.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class Hextile {\n  public static final int raw = (1 << 0);\n  public static final int bgSpecified = (1 << 1);\n  public static final int fgSpecified = (1 << 2);\n  public static final int anySubrects = (1 << 3);\n  public static final int subrectsColoured = (1 << 4);\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/HextileDecoder.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.awt.image.*;\nimport java.nio.*;\nimport java.util.Arrays;\n\nimport com.tigervnc.rdr.*;\n\npublic class HextileDecoder extends Decoder {\n\n  public static final int hextileRaw = (1 << 0);\n  public static final int hextileBgSpecified = (1 << 1);\n  public static final int hextileFgSpecified = (1 << 2);\n  public static final int hextileAnySubrects = (1 << 3);\n  public static final int hextileSubrectsColoured = (1 << 4);\n\n  public HextileDecoder() { super(DecoderFlags.DecoderPlain); }\n\n  public void readRect(Rect r, InStream is,\n                       ServerParams server, OutStream os)\n  {\n    Rect t = new Rect();\n    int bytesPerPixel;\n\n    bytesPerPixel = server.pf().bpp/8;\n\n    for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {\n\n      t.br.y = Math.min(r.br.y, t.tl.y + 16);\n\n      for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {\n        int tileType;\n\n        t.br.x = Math.min(r.br.x, t.tl.x + 16);\n\n        tileType = is.readU8();\n        os.writeU8(tileType);\n\n        if ((tileType & hextileRaw) != 0) {\n          os.copyBytes(is, t.area() * bytesPerPixel);\n          continue;\n        }\n\n        if ((tileType & hextileBgSpecified) != 0)\n          os.copyBytes(is, bytesPerPixel);\n\n        if ((tileType & hextileFgSpecified) != 0)\n          os.copyBytes(is, bytesPerPixel);\n\n        if ((tileType & hextileAnySubrects) != 0) {\n          int nSubrects;\n\n          nSubrects = is.readU8();\n          os.writeU8(nSubrects);\n\n          if ((tileType & hextileSubrectsColoured) != 0)\n            os.copyBytes(is, nSubrects * (bytesPerPixel + 2));\n          else\n            os.copyBytes(is, nSubrects * 2);\n        }\n      }\n    }\n  }\n\n  public void decodeRect(Rect r, Object buffer,\n                         int buflen, ServerParams server,\n                         ModifiablePixelBuffer pb)\n  {\n    MemInStream is = new MemInStream((byte[])buffer, 0, buflen);\n    PixelFormat pf = server.pf();\n    switch (pf.bpp) {\n    case 8:  hextileDecode8(r, is, pf, pb); break;\n    case 16: hextileDecode16(r, is, pf, pb); break;\n    case 32: hextileDecode32(r, is, pf, pb); break;\n    }\n  }\n\n  private void hextileDecode8(Rect r, InStream is,\n                              PixelFormat pf,\n                              ModifiablePixelBuffer pb)\n  {\n    HEXTILE_DECODE(r, is, pf, pb);\n  }\n\n  private void hextileDecode16(Rect r, InStream is,\n                               PixelFormat pf,\n                               ModifiablePixelBuffer pb)\n  {\n    HEXTILE_DECODE(r, is, pf, pb);\n  }\n\n  private void hextileDecode32(Rect r, InStream is,\n                               PixelFormat pf,\n                               ModifiablePixelBuffer pb)\n  {\n    HEXTILE_DECODE(r, is, pf, pb);\n  }\n\n  private static ByteBuffer READ_PIXEL(InStream is, PixelFormat pf) {\n    switch (pf.bpp) {\n    case 8:\n      return ByteBuffer.allocate(1).put(0, (byte)is.readOpaque8());\n    case 16:\n      return ByteBuffer.allocate(2).putShort(0, (short)is.readOpaque16());\n    default:\n      return ByteBuffer.allocate(4).putInt(0, is.readOpaque32());\n    }\n  }\n\n  private void HEXTILE_DECODE(Rect r, InStream is,\n                              PixelFormat pf,\n                              ModifiablePixelBuffer pb)\n  {\n    Rect t = new Rect();\n    ByteBuffer bg = ByteBuffer.allocate(pf.bpp/8);\n    ByteBuffer fg = ByteBuffer.allocate(pf.bpp/8);\n    ByteBuffer buf = ByteBuffer.allocate(16 * 16 * pf.bpp/8);\n\n    for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {\n\n      t.br.y = Math.min(r.br.y, t.tl.y + 16);\n\n      for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {\n\n        t.br.x = Math.min(r.br.x, t.tl.x + 16);\n\n        int tileType = is.readU8();\n\n        if ((tileType & hextileRaw) != 0) {\n          is.readBytes(buf.duplicate(), t.area() * (pf.bpp/8));\n          pb.imageRect(pf, t, buf.array());\n          continue;\n        }\n\n        if ((tileType & hextileBgSpecified) != 0)\n          bg = READ_PIXEL(is, pf);\n\n        int len = t.area();\n        ByteBuffer ptr = buf.duplicate();\n        while (len-- > 0) ptr.put(bg.array());\n\n        if ((tileType & hextileFgSpecified) != 0)\n          fg = READ_PIXEL(is, pf);\n\n        if ((tileType & hextileAnySubrects) != 0) {\n          int nSubrects = is.readU8();\n\n          for (int i = 0; i < nSubrects; i++) {\n\n            if ((tileType & hextileSubrectsColoured) != 0)\n              fg = READ_PIXEL(is, pf);\n\n            int xy = is.readU8();\n            int wh = is.readU8();\n\n            int x = ((xy >> 4) & 15);\n            int y = (xy & 15);\n            int w = ((wh >> 4) & 15) + 1;\n            int h = (wh & 15) + 1;\n            if (x + w > 16 || y + h > 16) {\n              throw new Exception(\"HEXTILE_DECODE: Hextile out of bounds\");\n            }\n            ptr = buf.duplicate();\n            ptr.position((y * t.width() + x)*pf.bpp/8);\n            int rowAdd = (t.width() - w)*pf.bpp/8;\n            while (h-- > 0) {\n              len = w;\n              while (len-- > 0) ptr.put(fg.array());\n              if (h > 0) ptr.position(ptr.position()+rowAdd);\n            }\n          }\n        }\n        pb.imageRect(pf, t, buf.array());\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Hostname.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class Hostname {\n\n  public static String getHost(String vncServerName) {\n    int colonPos = vncServerName.indexOf(':');\n    if (colonPos == 0)\n      return \"localhost\";\n    if (colonPos == -1)\n      colonPos = vncServerName.length();\n    return vncServerName.substring(0, colonPos);\n  }\n\n  public static int getPort(String vncServerName) {\n    int colonPos = vncServerName.indexOf(':');\n    if (colonPos == -1 || colonPos == vncServerName.length()-1)\n      return 5900;\n    if (vncServerName.charAt(colonPos+1) == ':') {\n      return Integer.parseInt(vncServerName.substring(colonPos+2));\n    }\n    int port = Integer.parseInt(vncServerName.substring(colonPos+1));\n    if (port < 100)\n      port += 5900;\n    return port;\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/IntParameter.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2004-2005 Cendio AB.\n * Copyright 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class IntParameter extends VoidParameter {\n  public IntParameter(String name_, String desc_, int v,\n                      int minValue_, int maxValue_,\n                      Configuration.ConfigurationObject co)\n  {\n    super(name_, desc_, co);\n    value = v;\n    defValue = v;\n    minValue = minValue_;\n    maxValue = maxValue_;\n  }\n\n  public IntParameter(String name_, String desc_, int v)\n  {\n    this(name_, desc_, v, Integer.MIN_VALUE, Integer.MAX_VALUE,\n         Configuration.ConfigurationObject.ConfGlobal);\n  }\n\n  public boolean setParam(String v) {\n    if (immutable) return true;\n    vlog.debug(\"Set \"+getName()+\"(Int) to \"+v);\n    try {\n      int i;\n      i = Integer.parseInt(v);\n      if (i < minValue || i > maxValue)\n        return false;\n      value = i;\n      return true;\n    } catch (NumberFormatException e) {\n      throw new Exception(e.toString());\n    }\n  }\n\n  public boolean setParam(int v) {\n    if (immutable) return true;\n    vlog.debug(\"Set \"+getName()+\"(Int) to \"+v);\n    if (v < minValue || v > maxValue)\n      return false;\n    value = v;\n    return true;\n  }\n\n  public String getDefaultStr() { return Integer.toString(defValue); }\n  public String getValueStr() { return Integer.toString(value); }\n\n  //public int int() { return value; }\n  public int getValue() { return value; }\n\n  protected int value;\n  protected int defValue;\n  protected int minValue;\n  protected int maxValue;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/JpegCompressor.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\npackage com.tigervnc.rfb;\n\npublic class JpegCompressor {\n\n  public static final int SUBSAMP_UNDEFINED = -1;\n  public static final int SUBSAMP_NONE = 0;\n  public static final int SUBSAMP_420 = 1;\n  public static final int SUBSAMP_422 = 2;\n  public static final int SUBSAMP_GRAY = 3;\n\n  public static int subsamplingNum(String name) {\n    if (name.equalsIgnoreCase(\"SUBSAMP_UNDEFINED\")) return SUBSAMP_UNDEFINED;\n    if (name.equalsIgnoreCase(\"SUBSAMP_NONE\"))      return SUBSAMP_NONE;\n    if (name.equalsIgnoreCase(\"SUBSAMP_420\"))       return SUBSAMP_420;\n    if (name.equalsIgnoreCase(\"SUBSAMP_422\"))       return SUBSAMP_422;\n    if (name.equalsIgnoreCase(\"SUBSAMP_GRAY\"))      return SUBSAMP_GRAY;\n    return SUBSAMP_UNDEFINED;\n  }\n\n  public static String subsamplingName(int num) {\n    switch (num) {\n    case SUBSAMP_UNDEFINED: return \"SUBSAMP_UNDEFINED\";\n    case SUBSAMP_NONE:      return \"SUBSAMP_NONE\";\n    case SUBSAMP_420:       return \"SUBSAMP_420\";\n    case SUBSAMP_422:       return \"SUBSAMP_422\";\n    case SUBSAMP_GRAY:      return \"SUBSAMP_GRAY\";\n    default:                return \"SUBSAMP_UNDEFINED\";\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/JpegDecompressor.java",
    "content": "/* Copyright (C) 2016 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\npackage com.tigervnc.rfb;\n\nimport java.awt.*;\nimport java.awt.image.*;\nimport java.io.*;\nimport java.nio.ByteBuffer;\nimport javax.imageio.*;\nimport javax.imageio.stream.*;\n\npublic class JpegDecompressor {\n\n  public JpegDecompressor() {}\n\n  public void decompress(ByteBuffer jpegBuf, int jpegBufLen,\n    PixelBuffer pb, Rect r, PixelFormat pf)\n  {\n\n    byte[] src = new byte[jpegBufLen];\n\n    jpegBuf.get(src);\n    try {\n      ImageIO.setUseCache(false);\n      BufferedImage jpeg =\n        ImageIO.read(new MemoryCacheImageInputStream(new ByteArrayInputStream(src)));\n      jpeg.setAccelerationPriority(1);\n      synchronized(pb.getImage()) {\n        Graphics2D g2 = (Graphics2D)pb.getImage().getGraphics();\n        g2.drawImage(jpeg, r.tl.x, r.tl.y, r.width(), r.height(), null);\n        g2.dispose();\n      }\n      jpeg.flush();\n    } catch (IOException e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Keysym2ucs.java",
    "content": "/* Copyright (C) 2017 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n *\n * This module converts keysym values into the corresponding ISO 10646\n * (UCS, Unicode) values.\n *\n * The array keysymtab[] contains pairs of X11 keysym values for graphical\n * characters and the corresponding Unicode value. The function\n * keysym2ucs() maps a keysym onto a Unicode value using a binary search,\n * therefore keysymtab[] must remain SORTED by keysym value.\n *\n * The keysym -> UTF-8 conversion will hopefully one day be provided\n * by Xlib via XmbLookupString() and should ideally not have to be\n * done in X applications. But we are not there yet.\n *\n * We allow to represent any UCS character in the range U-00000000 to\n * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.\n * This admittedly does not cover the entire 31-bit space of UCS, but\n * it does cover all of the characters up to U-10FFFF, which can be\n * represented by UTF-16, and more, and it is very unlikely that higher\n * UCS codes will ever be assigned by ISO. So to get Unicode character\n * U+ABCD you can directly use keysym 0x0100abcd.\n *\n * NOTE: The comments in the table below contain the actual character\n * encoded in UTF-8, so for viewing and editing best use an editor in\n * UTF-8 mode.\n *\n * Derived from keysym2ucs.c, originally authored by Markus G, Kuhn\n *\n */\n\npackage com.tigervnc.rfb;\n\npublic class Keysym2ucs {\n\n  private static class codepair {\n    public codepair(int keysym_, int ucs_) {\n      keysym = keysym_;\n      ucs = ucs_;\n    }\n    int keysym;\n    int ucs;\n  }\n\n  private static class combiningpair {\n    public combiningpair(int spacing_, int combining_) {\n      spacing = spacing_;\n      combining = combining_;\n    }\n    int spacing;\n    int combining;\n  }\n\n  public static codepair[] keysymtab = {\n    new codepair(0x01a1, 0x0104), /*                     Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */\n    new codepair(0x01a2, 0x02d8), /*                       breve ˘ BREVE */\n    new codepair(0x01a3, 0x0141), /*                     Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */\n    new codepair(0x01a5, 0x013d), /*                      Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */\n    new codepair(0x01a6, 0x015a), /*                      Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */\n    new codepair(0x01a9, 0x0160), /*                      Scaron Š LATIN CAPITAL LETTER S WITH CARON */\n    new codepair(0x01aa, 0x015e), /*                    Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */\n    new codepair(0x01ab, 0x0164), /*                      Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */\n    new codepair(0x01ac, 0x0179), /*                      Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */\n    new codepair(0x01ae, 0x017d), /*                      Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */\n    new codepair(0x01af, 0x017b), /*                   Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */\n    new codepair(0x01b1, 0x0105), /*                     aogonek ą LATIN SMALL LETTER A WITH OGONEK */\n    new codepair(0x01b2, 0x02db), /*                      ogonek ˛ OGONEK */\n    new codepair(0x01b3, 0x0142), /*                     lstroke ł LATIN SMALL LETTER L WITH STROKE */\n    new codepair(0x01b5, 0x013e), /*                      lcaron ľ LATIN SMALL LETTER L WITH CARON */\n    new codepair(0x01b6, 0x015b), /*                      sacute ś LATIN SMALL LETTER S WITH ACUTE */\n    new codepair(0x01b7, 0x02c7), /*                       caron ˇ CARON */\n    new codepair(0x01b9, 0x0161), /*                      scaron š LATIN SMALL LETTER S WITH CARON */\n    new codepair(0x01ba, 0x015f), /*                    scedilla ş LATIN SMALL LETTER S WITH CEDILLA */\n    new codepair(0x01bb, 0x0165), /*                      tcaron ť LATIN SMALL LETTER T WITH CARON */\n    new codepair(0x01bc, 0x017a), /*                      zacute ź LATIN SMALL LETTER Z WITH ACUTE */\n    new codepair(0x01bd, 0x02dd), /*                 doubleacute ˝ DOUBLE ACUTE ACCENT */\n    new codepair(0x01be, 0x017e), /*                      zcaron ž LATIN SMALL LETTER Z WITH CARON */\n    new codepair(0x01bf, 0x017c), /*                   zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */\n    new codepair(0x01c0, 0x0154), /*                      Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */\n    new codepair(0x01c3, 0x0102), /*                      Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */\n    new codepair(0x01c5, 0x0139), /*                      Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */\n    new codepair(0x01c6, 0x0106), /*                      Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */\n    new codepair(0x01c8, 0x010c), /*                      Ccaron Č LATIN CAPITAL LETTER C WITH CARON */\n    new codepair(0x01ca, 0x0118), /*                     Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */\n    new codepair(0x01cc, 0x011a), /*                      Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */\n    new codepair(0x01cf, 0x010e), /*                      Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */\n    new codepair(0x01d0, 0x0110), /*                     Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */\n    new codepair(0x01d1, 0x0143), /*                      Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */\n    new codepair(0x01d2, 0x0147), /*                      Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */\n    new codepair(0x01d5, 0x0150), /*                Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */\n    new codepair(0x01d8, 0x0158), /*                      Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */\n    new codepair(0x01d9, 0x016e), /*                       Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */\n    new codepair(0x01db, 0x0170), /*                Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */\n    new codepair(0x01de, 0x0162), /*                    Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */\n    new codepair(0x01e0, 0x0155), /*                      racute ŕ LATIN SMALL LETTER R WITH ACUTE */\n    new codepair(0x01e3, 0x0103), /*                      abreve ă LATIN SMALL LETTER A WITH BREVE */\n    new codepair(0x01e5, 0x013a), /*                      lacute ĺ LATIN SMALL LETTER L WITH ACUTE */\n    new codepair(0x01e6, 0x0107), /*                      cacute ć LATIN SMALL LETTER C WITH ACUTE */\n    new codepair(0x01e8, 0x010d), /*                      ccaron č LATIN SMALL LETTER C WITH CARON */\n    new codepair(0x01ea, 0x0119), /*                     eogonek ę LATIN SMALL LETTER E WITH OGONEK */\n    new codepair(0x01ec, 0x011b), /*                      ecaron ě LATIN SMALL LETTER E WITH CARON */\n    new codepair(0x01ef, 0x010f), /*                      dcaron ď LATIN SMALL LETTER D WITH CARON */\n    new codepair(0x01f0, 0x0111), /*                     dstroke đ LATIN SMALL LETTER D WITH STROKE */\n    new codepair(0x01f1, 0x0144), /*                      nacute ń LATIN SMALL LETTER N WITH ACUTE */\n    new codepair(0x01f2, 0x0148), /*                      ncaron ň LATIN SMALL LETTER N WITH CARON */\n    new codepair(0x01f5, 0x0151), /*                odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */\n    new codepair(0x01f8, 0x0159), /*                      rcaron ř LATIN SMALL LETTER R WITH CARON */\n    new codepair(0x01f9, 0x016f), /*                       uring ů LATIN SMALL LETTER U WITH RING ABOVE */\n    new codepair(0x01fb, 0x0171), /*                udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */\n    new codepair(0x01fe, 0x0163), /*                    tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */\n    new codepair(0x01ff, 0x02d9), /*                    abovedot ˙ DOT ABOVE */\n    new codepair(0x02a1, 0x0126), /*                     Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */\n    new codepair(0x02a6, 0x0124), /*                 Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */\n    new codepair(0x02a9, 0x0130), /*                   Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */\n    new codepair(0x02ab, 0x011e), /*                      Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */\n    new codepair(0x02ac, 0x0134), /*                 Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */\n    new codepair(0x02b1, 0x0127), /*                     hstroke ħ LATIN SMALL LETTER H WITH STROKE */\n    new codepair(0x02b6, 0x0125), /*                 hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */\n    new codepair(0x02b9, 0x0131), /*                    idotless ı LATIN SMALL LETTER DOTLESS I */\n    new codepair(0x02bb, 0x011f), /*                      gbreve ğ LATIN SMALL LETTER G WITH BREVE */\n    new codepair(0x02bc, 0x0135), /*                 jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */\n    new codepair(0x02c5, 0x010a), /*                   Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */\n    new codepair(0x02c6, 0x0108), /*                 Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */\n    new codepair(0x02d5, 0x0120), /*                   Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */\n    new codepair(0x02d8, 0x011c), /*                 Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */\n    new codepair(0x02dd, 0x016c), /*                      Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */\n    new codepair(0x02de, 0x015c), /*                 Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */\n    new codepair(0x02e5, 0x010b), /*                   cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */\n    new codepair(0x02e6, 0x0109), /*                 ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */\n    new codepair(0x02f5, 0x0121), /*                   gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */\n    new codepair(0x02f8, 0x011d), /*                 gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */\n    new codepair(0x02fd, 0x016d), /*                      ubreve ŭ LATIN SMALL LETTER U WITH BREVE */\n    new codepair(0x02fe, 0x015d), /*                 scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */\n    new codepair(0x03a2, 0x0138), /*                         kra ĸ LATIN SMALL LETTER KRA */\n    new codepair(0x03a3, 0x0156), /*                    Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */\n    new codepair(0x03a5, 0x0128), /*                      Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */\n    new codepair(0x03a6, 0x013b), /*                    Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */\n    new codepair(0x03aa, 0x0112), /*                     Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */\n    new codepair(0x03ab, 0x0122), /*                    Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */\n    new codepair(0x03ac, 0x0166), /*                      Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */\n    new codepair(0x03b3, 0x0157), /*                    rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */\n    new codepair(0x03b5, 0x0129), /*                      itilde ĩ LATIN SMALL LETTER I WITH TILDE */\n    new codepair(0x03b6, 0x013c), /*                    lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */\n    new codepair(0x03ba, 0x0113), /*                     emacron ē LATIN SMALL LETTER E WITH MACRON */\n    new codepair(0x03bb, 0x0123), /*                    gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */\n    new codepair(0x03bc, 0x0167), /*                      tslash ŧ LATIN SMALL LETTER T WITH STROKE */\n    new codepair(0x03bd, 0x014a), /*                         ENG Ŋ LATIN CAPITAL LETTER ENG */\n    new codepair(0x03bf, 0x014b), /*                         eng ŋ LATIN SMALL LETTER ENG */\n    new codepair(0x03c0, 0x0100), /*                     Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */\n    new codepair(0x03c7, 0x012e), /*                     Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */\n    new codepair(0x03cc, 0x0116), /*                   Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */\n    new codepair(0x03cf, 0x012a), /*                     Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */\n    new codepair(0x03d1, 0x0145), /*                    Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */\n    new codepair(0x03d2, 0x014c), /*                     Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */\n    new codepair(0x03d3, 0x0136), /*                    Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */\n    new codepair(0x03d9, 0x0172), /*                     Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */\n    new codepair(0x03dd, 0x0168), /*                      Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */\n    new codepair(0x03de, 0x016a), /*                     Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */\n    new codepair(0x03e0, 0x0101), /*                     amacron ā LATIN SMALL LETTER A WITH MACRON */\n    new codepair(0x03e7, 0x012f), /*                     iogonek į LATIN SMALL LETTER I WITH OGONEK */\n    new codepair(0x03ec, 0x0117), /*                   eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */\n    new codepair(0x03ef, 0x012b), /*                     imacron ī LATIN SMALL LETTER I WITH MACRON */\n    new codepair(0x03f1, 0x0146), /*                    ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */\n    new codepair(0x03f2, 0x014d), /*                     omacron ō LATIN SMALL LETTER O WITH MACRON */\n    new codepair(0x03f3, 0x0137), /*                    kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */\n    new codepair(0x03f9, 0x0173), /*                     uogonek ų LATIN SMALL LETTER U WITH OGONEK */\n    new codepair(0x03fd, 0x0169), /*                      utilde ũ LATIN SMALL LETTER U WITH TILDE */\n    new codepair(0x03fe, 0x016b), /*                     umacron ū LATIN SMALL LETTER U WITH MACRON */\n    new codepair(0x047e, 0x203e), /*                    overline ‾ OVERLINE */\n    new codepair(0x04a1, 0x3002), /*               kana_fullstop 。 IDEOGRAPHIC FULL STOP */\n    new codepair(0x04a2, 0x300c), /*         kana_openingbracket 「 LEFT CORNER BRACKET */\n    new codepair(0x04a3, 0x300d), /*         kana_closingbracket 」 RIGHT CORNER BRACKET */\n    new codepair(0x04a4, 0x3001), /*                  kana_comma 、 IDEOGRAPHIC COMMA */\n    new codepair(0x04a5, 0x30fb), /*            kana_conjunctive ・ KATAKANA MIDDLE DOT */\n    new codepair(0x04a6, 0x30f2), /*                     kana_WO ヲ KATAKANA LETTER WO */\n    new codepair(0x04a7, 0x30a1), /*                      kana_a ァ KATAKANA LETTER SMALL A */\n    new codepair(0x04a8, 0x30a3), /*                      kana_i ィ KATAKANA LETTER SMALL I */\n    new codepair(0x04a9, 0x30a5), /*                      kana_u ゥ KATAKANA LETTER SMALL U */\n    new codepair(0x04aa, 0x30a7), /*                      kana_e ェ KATAKANA LETTER SMALL E */\n    new codepair(0x04ab, 0x30a9), /*                      kana_o ォ KATAKANA LETTER SMALL O */\n    new codepair(0x04ac, 0x30e3), /*                     kana_ya ャ KATAKANA LETTER SMALL YA */\n    new codepair(0x04ad, 0x30e5), /*                     kana_yu ュ KATAKANA LETTER SMALL YU */\n    new codepair(0x04ae, 0x30e7), /*                     kana_yo ョ KATAKANA LETTER SMALL YO */\n    new codepair(0x04af, 0x30c3), /*                    kana_tsu ッ KATAKANA LETTER SMALL TU */\n    new codepair(0x04b0, 0x30fc), /*              prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */\n    new codepair(0x04b1, 0x30a2), /*                      kana_A ア KATAKANA LETTER A */\n    new codepair(0x04b2, 0x30a4), /*                      kana_I イ KATAKANA LETTER I */\n    new codepair(0x04b3, 0x30a6), /*                      kana_U ウ KATAKANA LETTER U */\n    new codepair(0x04b4, 0x30a8), /*                      kana_E エ KATAKANA LETTER E */\n    new codepair(0x04b5, 0x30aa), /*                      kana_O オ KATAKANA LETTER O */\n    new codepair(0x04b6, 0x30ab), /*                     kana_KA カ KATAKANA LETTER KA */\n    new codepair(0x04b7, 0x30ad), /*                     kana_KI キ KATAKANA LETTER KI */\n    new codepair(0x04b8, 0x30af), /*                     kana_KU ク KATAKANA LETTER KU */\n    new codepair(0x04b9, 0x30b1), /*                     kana_KE ケ KATAKANA LETTER KE */\n    new codepair(0x04ba, 0x30b3), /*                     kana_KO コ KATAKANA LETTER KO */\n    new codepair(0x04bb, 0x30b5), /*                     kana_SA サ KATAKANA LETTER SA */\n    new codepair(0x04bc, 0x30b7), /*                    kana_SHI シ KATAKANA LETTER SI */\n    new codepair(0x04bd, 0x30b9), /*                     kana_SU ス KATAKANA LETTER SU */\n    new codepair(0x04be, 0x30bb), /*                     kana_SE セ KATAKANA LETTER SE */\n    new codepair(0x04bf, 0x30bd), /*                     kana_SO ソ KATAKANA LETTER SO */\n    new codepair(0x04c0, 0x30bf), /*                     kana_TA タ KATAKANA LETTER TA */\n    new codepair(0x04c1, 0x30c1), /*                    kana_CHI チ KATAKANA LETTER TI */\n    new codepair(0x04c2, 0x30c4), /*                    kana_TSU ツ KATAKANA LETTER TU */\n    new codepair(0x04c3, 0x30c6), /*                     kana_TE テ KATAKANA LETTER TE */\n    new codepair(0x04c4, 0x30c8), /*                     kana_TO ト KATAKANA LETTER TO */\n    new codepair(0x04c5, 0x30ca), /*                     kana_NA ナ KATAKANA LETTER NA */\n    new codepair(0x04c6, 0x30cb), /*                     kana_NI ニ KATAKANA LETTER NI */\n    new codepair(0x04c7, 0x30cc), /*                     kana_NU ヌ KATAKANA LETTER NU */\n    new codepair(0x04c8, 0x30cd), /*                     kana_NE ネ KATAKANA LETTER NE */\n    new codepair(0x04c9, 0x30ce), /*                     kana_NO ノ KATAKANA LETTER NO */\n    new codepair(0x04ca, 0x30cf), /*                     kana_HA ハ KATAKANA LETTER HA */\n    new codepair(0x04cb, 0x30d2), /*                     kana_HI ヒ KATAKANA LETTER HI */\n    new codepair(0x04cc, 0x30d5), /*                     kana_FU フ KATAKANA LETTER HU */\n    new codepair(0x04cd, 0x30d8), /*                     kana_HE ヘ KATAKANA LETTER HE */\n    new codepair(0x04ce, 0x30db), /*                     kana_HO ホ KATAKANA LETTER HO */\n    new codepair(0x04cf, 0x30de), /*                     kana_MA マ KATAKANA LETTER MA */\n    new codepair(0x04d0, 0x30df), /*                     kana_MI ミ KATAKANA LETTER MI */\n    new codepair(0x04d1, 0x30e0), /*                     kana_MU ム KATAKANA LETTER MU */\n    new codepair(0x04d2, 0x30e1), /*                     kana_ME メ KATAKANA LETTER ME */\n    new codepair(0x04d3, 0x30e2), /*                     kana_MO モ KATAKANA LETTER MO */\n    new codepair(0x04d4, 0x30e4), /*                     kana_YA ヤ KATAKANA LETTER YA */\n    new codepair(0x04d5, 0x30e6), /*                     kana_YU ユ KATAKANA LETTER YU */\n    new codepair(0x04d6, 0x30e8), /*                     kana_YO ヨ KATAKANA LETTER YO */\n    new codepair(0x04d7, 0x30e9), /*                     kana_RA ラ KATAKANA LETTER RA */\n    new codepair(0x04d8, 0x30ea), /*                     kana_RI リ KATAKANA LETTER RI */\n    new codepair(0x04d9, 0x30eb), /*                     kana_RU ル KATAKANA LETTER RU */\n    new codepair(0x04da, 0x30ec), /*                     kana_RE レ KATAKANA LETTER RE */\n    new codepair(0x04db, 0x30ed), /*                     kana_RO ロ KATAKANA LETTER RO */\n    new codepair(0x04dc, 0x30ef), /*                     kana_WA ワ KATAKANA LETTER WA */\n    new codepair(0x04dd, 0x30f3), /*                      kana_N ン KATAKANA LETTER N */\n    new codepair(0x04de, 0x309b), /*                 voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */\n    new codepair(0x04df, 0x309c), /*             semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */\n    new codepair(0x05ac, 0x060c), /*                Arabic_comma ، ARABIC COMMA */\n    new codepair(0x05bb, 0x061b), /*            Arabic_semicolon ؛ ARABIC SEMICOLON */\n    new codepair(0x05bf, 0x061f), /*        Arabic_question_mark ؟ ARABIC QUESTION MARK */\n    new codepair(0x05c1, 0x0621), /*                Arabic_hamza ء ARABIC LETTER HAMZA */\n    new codepair(0x05c2, 0x0622), /*          Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */\n    new codepair(0x05c3, 0x0623), /*          Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */\n    new codepair(0x05c4, 0x0624), /*           Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */\n    new codepair(0x05c5, 0x0625), /*       Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */\n    new codepair(0x05c6, 0x0626), /*           Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */\n    new codepair(0x05c7, 0x0627), /*                 Arabic_alef ا ARABIC LETTER ALEF */\n    new codepair(0x05c8, 0x0628), /*                  Arabic_beh ب ARABIC LETTER BEH */\n    new codepair(0x05c9, 0x0629), /*           Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */\n    new codepair(0x05ca, 0x062a), /*                  Arabic_teh ت ARABIC LETTER TEH */\n    new codepair(0x05cb, 0x062b), /*                 Arabic_theh ث ARABIC LETTER THEH */\n    new codepair(0x05cc, 0x062c), /*                 Arabic_jeem ج ARABIC LETTER JEEM */\n    new codepair(0x05cd, 0x062d), /*                  Arabic_hah ح ARABIC LETTER HAH */\n    new codepair(0x05ce, 0x062e), /*                 Arabic_khah خ ARABIC LETTER KHAH */\n    new codepair(0x05cf, 0x062f), /*                  Arabic_dal د ARABIC LETTER DAL */\n    new codepair(0x05d0, 0x0630), /*                 Arabic_thal ذ ARABIC LETTER THAL */\n    new codepair(0x05d1, 0x0631), /*                   Arabic_ra ر ARABIC LETTER REH */\n    new codepair(0x05d2, 0x0632), /*                 Arabic_zain ز ARABIC LETTER ZAIN */\n    new codepair(0x05d3, 0x0633), /*                 Arabic_seen س ARABIC LETTER SEEN */\n    new codepair(0x05d4, 0x0634), /*                Arabic_sheen ش ARABIC LETTER SHEEN */\n    new codepair(0x05d5, 0x0635), /*                  Arabic_sad ص ARABIC LETTER SAD */\n    new codepair(0x05d6, 0x0636), /*                  Arabic_dad ض ARABIC LETTER DAD */\n    new codepair(0x05d7, 0x0637), /*                  Arabic_tah ط ARABIC LETTER TAH */\n    new codepair(0x05d8, 0x0638), /*                  Arabic_zah ظ ARABIC LETTER ZAH */\n    new codepair(0x05d9, 0x0639), /*                  Arabic_ain ع ARABIC LETTER AIN */\n    new codepair(0x05da, 0x063a), /*                Arabic_ghain غ ARABIC LETTER GHAIN */\n    new codepair(0x05e0, 0x0640), /*              Arabic_tatweel ـ ARABIC TATWEEL */\n    new codepair(0x05e1, 0x0641), /*                  Arabic_feh ف ARABIC LETTER FEH */\n    new codepair(0x05e2, 0x0642), /*                  Arabic_qaf ق ARABIC LETTER QAF */\n    new codepair(0x05e3, 0x0643), /*                  Arabic_kaf ك ARABIC LETTER KAF */\n    new codepair(0x05e4, 0x0644), /*                  Arabic_lam ل ARABIC LETTER LAM */\n    new codepair(0x05e5, 0x0645), /*                 Arabic_meem م ARABIC LETTER MEEM */\n    new codepair(0x05e6, 0x0646), /*                 Arabic_noon ن ARABIC LETTER NOON */\n    new codepair(0x05e7, 0x0647), /*                   Arabic_ha ه ARABIC LETTER HEH */\n    new codepair(0x05e8, 0x0648), /*                  Arabic_waw و ARABIC LETTER WAW */\n    new codepair(0x05e9, 0x0649), /*          Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */\n    new codepair(0x05ea, 0x064a), /*                  Arabic_yeh ي ARABIC LETTER YEH */\n    new codepair(0x05eb, 0x064b), /*             Arabic_fathatan ً ARABIC FATHATAN */\n    new codepair(0x05ec, 0x064c), /*             Arabic_dammatan ٌ ARABIC DAMMATAN */\n    new codepair(0x05ed, 0x064d), /*             Arabic_kasratan ٍ ARABIC KASRATAN */\n    new codepair(0x05ee, 0x064e), /*                Arabic_fatha َ ARABIC FATHA */\n    new codepair(0x05ef, 0x064f), /*                Arabic_damma ُ ARABIC DAMMA */\n    new codepair(0x05f0, 0x0650), /*                Arabic_kasra ِ ARABIC KASRA */\n    new codepair(0x05f1, 0x0651), /*               Arabic_shadda ّ ARABIC SHADDA */\n    new codepair(0x05f2, 0x0652), /*                Arabic_sukun ْ ARABIC SUKUN */\n    new codepair(0x06a1, 0x0452), /*                 Serbian_dje ђ CYRILLIC SMALL LETTER DJE */\n    new codepair(0x06a2, 0x0453), /*               Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */\n    new codepair(0x06a3, 0x0451), /*                 Cyrillic_io ё CYRILLIC SMALL LETTER IO */\n    new codepair(0x06a4, 0x0454), /*                Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */\n    new codepair(0x06a5, 0x0455), /*               Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */\n    new codepair(0x06a6, 0x0456), /*                 Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */\n    new codepair(0x06a7, 0x0457), /*                Ukrainian_yi ї CYRILLIC SMALL LETTER YI */\n    new codepair(0x06a8, 0x0458), /*                 Cyrillic_je ј CYRILLIC SMALL LETTER JE */\n    new codepair(0x06a9, 0x0459), /*                Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */\n    new codepair(0x06aa, 0x045a), /*                Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */\n    new codepair(0x06ab, 0x045b), /*                Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */\n    new codepair(0x06ac, 0x045c), /*               Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */\n    new codepair(0x06ae, 0x045e), /*         Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */\n    new codepair(0x06af, 0x045f), /*               Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */\n    new codepair(0x06b0, 0x2116), /*                  numerosign № NUMERO SIGN */\n    new codepair(0x06b1, 0x0402), /*                 Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */\n    new codepair(0x06b2, 0x0403), /*               Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */\n    new codepair(0x06b3, 0x0401), /*                 Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */\n    new codepair(0x06b4, 0x0404), /*                Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */\n    new codepair(0x06b5, 0x0405), /*               Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */\n    new codepair(0x06b6, 0x0406), /*                 Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */\n    new codepair(0x06b7, 0x0407), /*                Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */\n    new codepair(0x06b8, 0x0408), /*                 Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */\n    new codepair(0x06b9, 0x0409), /*                Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */\n    new codepair(0x06ba, 0x040a), /*                Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */\n    new codepair(0x06bb, 0x040b), /*                Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */\n    new codepair(0x06bc, 0x040c), /*               Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */\n    new codepair(0x06be, 0x040e), /*         Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */\n    new codepair(0x06bf, 0x040f), /*               Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */\n    new codepair(0x06c0, 0x044e), /*                 Cyrillic_yu ю CYRILLIC SMALL LETTER YU */\n    new codepair(0x06c1, 0x0430), /*                  Cyrillic_a а CYRILLIC SMALL LETTER A */\n    new codepair(0x06c2, 0x0431), /*                 Cyrillic_be б CYRILLIC SMALL LETTER BE */\n    new codepair(0x06c3, 0x0446), /*                Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */\n    new codepair(0x06c4, 0x0434), /*                 Cyrillic_de д CYRILLIC SMALL LETTER DE */\n    new codepair(0x06c5, 0x0435), /*                 Cyrillic_ie е CYRILLIC SMALL LETTER IE */\n    new codepair(0x06c6, 0x0444), /*                 Cyrillic_ef ф CYRILLIC SMALL LETTER EF */\n    new codepair(0x06c7, 0x0433), /*                Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */\n    new codepair(0x06c8, 0x0445), /*                 Cyrillic_ha х CYRILLIC SMALL LETTER HA */\n    new codepair(0x06c9, 0x0438), /*                  Cyrillic_i и CYRILLIC SMALL LETTER I */\n    new codepair(0x06ca, 0x0439), /*             Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */\n    new codepair(0x06cb, 0x043a), /*                 Cyrillic_ka к CYRILLIC SMALL LETTER KA */\n    new codepair(0x06cc, 0x043b), /*                 Cyrillic_el л CYRILLIC SMALL LETTER EL */\n    new codepair(0x06cd, 0x043c), /*                 Cyrillic_em м CYRILLIC SMALL LETTER EM */\n    new codepair(0x06ce, 0x043d), /*                 Cyrillic_en н CYRILLIC SMALL LETTER EN */\n    new codepair(0x06cf, 0x043e), /*                  Cyrillic_o о CYRILLIC SMALL LETTER O */\n    new codepair(0x06d0, 0x043f), /*                 Cyrillic_pe п CYRILLIC SMALL LETTER PE */\n    new codepair(0x06d1, 0x044f), /*                 Cyrillic_ya я CYRILLIC SMALL LETTER YA */\n    new codepair(0x06d2, 0x0440), /*                 Cyrillic_er р CYRILLIC SMALL LETTER ER */\n    new codepair(0x06d3, 0x0441), /*                 Cyrillic_es с CYRILLIC SMALL LETTER ES */\n    new codepair(0x06d4, 0x0442), /*                 Cyrillic_te т CYRILLIC SMALL LETTER TE */\n    new codepair(0x06d5, 0x0443), /*                  Cyrillic_u у CYRILLIC SMALL LETTER U */\n    new codepair(0x06d6, 0x0436), /*                Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */\n    new codepair(0x06d7, 0x0432), /*                 Cyrillic_ve в CYRILLIC SMALL LETTER VE */\n    new codepair(0x06d8, 0x044c), /*           Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */\n    new codepair(0x06d9, 0x044b), /*               Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */\n    new codepair(0x06da, 0x0437), /*                 Cyrillic_ze з CYRILLIC SMALL LETTER ZE */\n    new codepair(0x06db, 0x0448), /*                Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */\n    new codepair(0x06dc, 0x044d), /*                  Cyrillic_e э CYRILLIC SMALL LETTER E */\n    new codepair(0x06dd, 0x0449), /*              Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */\n    new codepair(0x06de, 0x0447), /*                Cyrillic_che ч CYRILLIC SMALL LETTER CHE */\n    new codepair(0x06df, 0x044a), /*           Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */\n    new codepair(0x06e0, 0x042e), /*                 Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */\n    new codepair(0x06e1, 0x0410), /*                  Cyrillic_A А CYRILLIC CAPITAL LETTER A */\n    new codepair(0x06e2, 0x0411), /*                 Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */\n    new codepair(0x06e3, 0x0426), /*                Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */\n    new codepair(0x06e4, 0x0414), /*                 Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */\n    new codepair(0x06e5, 0x0415), /*                 Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */\n    new codepair(0x06e6, 0x0424), /*                 Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */\n    new codepair(0x06e7, 0x0413), /*                Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */\n    new codepair(0x06e8, 0x0425), /*                 Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */\n    new codepair(0x06e9, 0x0418), /*                  Cyrillic_I И CYRILLIC CAPITAL LETTER I */\n    new codepair(0x06ea, 0x0419), /*             Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */\n    new codepair(0x06eb, 0x041a), /*                 Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */\n    new codepair(0x06ec, 0x041b), /*                 Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */\n    new codepair(0x06ed, 0x041c), /*                 Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */\n    new codepair(0x06ee, 0x041d), /*                 Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */\n    new codepair(0x06ef, 0x041e), /*                  Cyrillic_O О CYRILLIC CAPITAL LETTER O */\n    new codepair(0x06f0, 0x041f), /*                 Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */\n    new codepair(0x06f1, 0x042f), /*                 Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */\n    new codepair(0x06f2, 0x0420), /*                 Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */\n    new codepair(0x06f3, 0x0421), /*                 Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */\n    new codepair(0x06f4, 0x0422), /*                 Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */\n    new codepair(0x06f5, 0x0423), /*                  Cyrillic_U У CYRILLIC CAPITAL LETTER U */\n    new codepair(0x06f6, 0x0416), /*                Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */\n    new codepair(0x06f7, 0x0412), /*                 Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */\n    new codepair(0x06f8, 0x042c), /*           Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */\n    new codepair(0x06f9, 0x042b), /*               Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */\n    new codepair(0x06fa, 0x0417), /*                 Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */\n    new codepair(0x06fb, 0x0428), /*                Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */\n    new codepair(0x06fc, 0x042d), /*                  Cyrillic_E Э CYRILLIC CAPITAL LETTER E */\n    new codepair(0x06fd, 0x0429), /*              Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */\n    new codepair(0x06fe, 0x0427), /*                Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */\n    new codepair(0x06ff, 0x042a), /*           Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */\n    new codepair(0x07a1, 0x0386), /*           Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */\n    new codepair(0x07a2, 0x0388), /*         Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */\n    new codepair(0x07a3, 0x0389), /*             Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */\n    new codepair(0x07a4, 0x038a), /*            Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */\n    new codepair(0x07a5, 0x03aa), /*         Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */\n    new codepair(0x07a7, 0x038c), /*         Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */\n    new codepair(0x07a8, 0x038e), /*         Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */\n    new codepair(0x07a9, 0x03ab), /*       Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */\n    new codepair(0x07ab, 0x038f), /*           Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */\n    new codepair(0x07ae, 0x0385), /*        Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */\n    new codepair(0x07af, 0x2015), /*              Greek_horizbar ― HORIZONTAL BAR */\n    new codepair(0x07b1, 0x03ac), /*           Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */\n    new codepair(0x07b2, 0x03ad), /*         Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */\n    new codepair(0x07b3, 0x03ae), /*             Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */\n    new codepair(0x07b4, 0x03af), /*            Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */\n    new codepair(0x07b5, 0x03ca), /*          Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */\n    new codepair(0x07b6, 0x0390), /*    Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */\n    new codepair(0x07b7, 0x03cc), /*         Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */\n    new codepair(0x07b8, 0x03cd), /*         Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */\n    new codepair(0x07b9, 0x03cb), /*       Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */\n    new codepair(0x07ba, 0x03b0), /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */\n    new codepair(0x07bb, 0x03ce), /*           Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */\n    new codepair(0x07c1, 0x0391), /*                 Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */\n    new codepair(0x07c2, 0x0392), /*                  Greek_BETA Β GREEK CAPITAL LETTER BETA */\n    new codepair(0x07c3, 0x0393), /*                 Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */\n    new codepair(0x07c4, 0x0394), /*                 Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */\n    new codepair(0x07c5, 0x0395), /*               Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */\n    new codepair(0x07c6, 0x0396), /*                  Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */\n    new codepair(0x07c7, 0x0397), /*                   Greek_ETA Η GREEK CAPITAL LETTER ETA */\n    new codepair(0x07c8, 0x0398), /*                 Greek_THETA Θ GREEK CAPITAL LETTER THETA */\n    new codepair(0x07c9, 0x0399), /*                  Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */\n    new codepair(0x07ca, 0x039a), /*                 Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */\n    new codepair(0x07cb, 0x039b), /*                Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */\n    new codepair(0x07cc, 0x039c), /*                    Greek_MU Μ GREEK CAPITAL LETTER MU */\n    new codepair(0x07cd, 0x039d), /*                    Greek_NU Ν GREEK CAPITAL LETTER NU */\n    new codepair(0x07ce, 0x039e), /*                    Greek_XI Ξ GREEK CAPITAL LETTER XI */\n    new codepair(0x07cf, 0x039f), /*               Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */\n    new codepair(0x07d0, 0x03a0), /*                    Greek_PI Π GREEK CAPITAL LETTER PI */\n    new codepair(0x07d1, 0x03a1), /*                   Greek_RHO Ρ GREEK CAPITAL LETTER RHO */\n    new codepair(0x07d2, 0x03a3), /*                 Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */\n    new codepair(0x07d4, 0x03a4), /*                   Greek_TAU Τ GREEK CAPITAL LETTER TAU */\n    new codepair(0x07d5, 0x03a5), /*               Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */\n    new codepair(0x07d6, 0x03a6), /*                   Greek_PHI Φ GREEK CAPITAL LETTER PHI */\n    new codepair(0x07d7, 0x03a7), /*                   Greek_CHI Χ GREEK CAPITAL LETTER CHI */\n    new codepair(0x07d8, 0x03a8), /*                   Greek_PSI Ψ GREEK CAPITAL LETTER PSI */\n    new codepair(0x07d9, 0x03a9), /*                 Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */\n    new codepair(0x07e1, 0x03b1), /*                 Greek_alpha α GREEK SMALL LETTER ALPHA */\n    new codepair(0x07e2, 0x03b2), /*                  Greek_beta β GREEK SMALL LETTER BETA */\n    new codepair(0x07e3, 0x03b3), /*                 Greek_gamma γ GREEK SMALL LETTER GAMMA */\n    new codepair(0x07e4, 0x03b4), /*                 Greek_delta δ GREEK SMALL LETTER DELTA */\n    new codepair(0x07e5, 0x03b5), /*               Greek_epsilon ε GREEK SMALL LETTER EPSILON */\n    new codepair(0x07e6, 0x03b6), /*                  Greek_zeta ζ GREEK SMALL LETTER ZETA */\n    new codepair(0x07e7, 0x03b7), /*                   Greek_eta η GREEK SMALL LETTER ETA */\n    new codepair(0x07e8, 0x03b8), /*                 Greek_theta θ GREEK SMALL LETTER THETA */\n    new codepair(0x07e9, 0x03b9), /*                  Greek_iota ι GREEK SMALL LETTER IOTA */\n    new codepair(0x07ea, 0x03ba), /*                 Greek_kappa κ GREEK SMALL LETTER KAPPA */\n    new codepair(0x07eb, 0x03bb), /*                Greek_lambda λ GREEK SMALL LETTER LAMDA */\n    new codepair(0x07ec, 0x03bc), /*                    Greek_mu μ GREEK SMALL LETTER MU */\n    new codepair(0x07ed, 0x03bd), /*                    Greek_nu ν GREEK SMALL LETTER NU */\n    new codepair(0x07ee, 0x03be), /*                    Greek_xi ξ GREEK SMALL LETTER XI */\n    new codepair(0x07ef, 0x03bf), /*               Greek_omicron ο GREEK SMALL LETTER OMICRON */\n    new codepair(0x07f0, 0x03c0), /*                    Greek_pi π GREEK SMALL LETTER PI */\n    new codepair(0x07f1, 0x03c1), /*                   Greek_rho ρ GREEK SMALL LETTER RHO */\n    new codepair(0x07f2, 0x03c3), /*                 Greek_sigma σ GREEK SMALL LETTER SIGMA */\n    new codepair(0x07f3, 0x03c2), /*       Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */\n    new codepair(0x07f4, 0x03c4), /*                   Greek_tau τ GREEK SMALL LETTER TAU */\n    new codepair(0x07f5, 0x03c5), /*               Greek_upsilon υ GREEK SMALL LETTER UPSILON */\n    new codepair(0x07f6, 0x03c6), /*                   Greek_phi φ GREEK SMALL LETTER PHI */\n    new codepair(0x07f7, 0x03c7), /*                   Greek_chi χ GREEK SMALL LETTER CHI */\n    new codepair(0x07f8, 0x03c8), /*                   Greek_psi ψ GREEK SMALL LETTER PSI */\n    new codepair(0x07f9, 0x03c9), /*                 Greek_omega ω GREEK SMALL LETTER OMEGA */\n    new codepair(0x08a1, 0x23b7), /*                 leftradical ⎷ ??? */\n    new codepair(0x08a2, 0x250c), /*              topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */\n    new codepair(0x08a3, 0x2500), /*              horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */\n    new codepair(0x08a4, 0x2320), /*                 topintegral ⌠ TOP HALF INTEGRAL */\n    new codepair(0x08a5, 0x2321), /*                 botintegral ⌡ BOTTOM HALF INTEGRAL */\n    new codepair(0x08a6, 0x2502), /*               vertconnector │ BOX DRAWINGS LIGHT VERTICAL */\n    new codepair(0x08a7, 0x23a1), /*            topleftsqbracket ⎡ ??? */\n    new codepair(0x08a8, 0x23a3), /*            botleftsqbracket ⎣ ??? */\n    new codepair(0x08a9, 0x23a4), /*           toprightsqbracket ⎤ ??? */\n    new codepair(0x08aa, 0x23a6), /*           botrightsqbracket ⎦ ??? */\n    new codepair(0x08ab, 0x239b), /*               topleftparens ⎛ ??? */\n    new codepair(0x08ac, 0x239d), /*               botleftparens ⎝ ??? */\n    new codepair(0x08ad, 0x239e), /*              toprightparens ⎞ ??? */\n    new codepair(0x08ae, 0x23a0), /*              botrightparens ⎠ ??? */\n    new codepair(0x08af, 0x23a8), /*        leftmiddlecurlybrace ⎨ ??? */\n    new codepair(0x08b0, 0x23ac), /*       rightmiddlecurlybrace ⎬ ??? */\n  /*  0x08b1                          topleftsummation ? ??? */\n  /*  0x08b2                          botleftsummation ? ??? */\n  /*  0x08b3                 topvertsummationconnector ? ??? */\n  /*  0x08b4                 botvertsummationconnector ? ??? */\n  /*  0x08b5                         toprightsummation ? ??? */\n  /*  0x08b6                         botrightsummation ? ??? */\n  /*  0x08b7                      rightmiddlesummation ? ??? */\n    new codepair(0x08bc, 0x2264), /*               lessthanequal ≤ LESS-THAN OR EQUAL TO */\n    new codepair(0x08bd, 0x2260), /*                    notequal ≠ NOT EQUAL TO */\n    new codepair(0x08be, 0x2265), /*            greaterthanequal ≥ GREATER-THAN OR EQUAL TO */\n    new codepair(0x08bf, 0x222b), /*                    integral ∫ INTEGRAL */\n    new codepair(0x08c0, 0x2234), /*                   therefore ∴ THEREFORE */\n    new codepair(0x08c1, 0x221d), /*                   variation ∝ PROPORTIONAL TO */\n    new codepair(0x08c2, 0x221e), /*                    infinity ∞ INFINITY */\n    new codepair(0x08c5, 0x2207), /*                       nabla ∇ NABLA */\n    new codepair(0x08c8, 0x223c), /*                 approximate ∼ TILDE OPERATOR */\n    new codepair(0x08c9, 0x2243), /*                similarequal ≃ ASYMPTOTICALLY EQUAL TO */\n    new codepair(0x08cd, 0x21d4), /*                    ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */\n    new codepair(0x08ce, 0x21d2), /*                     implies ⇒ RIGHTWARDS DOUBLE ARROW */\n    new codepair(0x08cf, 0x2261), /*                   identical ≡ IDENTICAL TO */\n    new codepair(0x08d6, 0x221a), /*                     radical √ SQUARE ROOT */\n    new codepair(0x08da, 0x2282), /*                  includedin ⊂ SUBSET OF */\n    new codepair(0x08db, 0x2283), /*                    includes ⊃ SUPERSET OF */\n    new codepair(0x08dc, 0x2229), /*                intersection ∩ INTERSECTION */\n    new codepair(0x08dd, 0x222a), /*                       union ∪ UNION */\n    new codepair(0x08de, 0x2227), /*                  logicaland ∧ LOGICAL AND */\n    new codepair(0x08df, 0x2228), /*                   logicalor ∨ LOGICAL OR */\n    new codepair(0x08ef, 0x2202), /*           partialderivative ∂ PARTIAL DIFFERENTIAL */\n    new codepair(0x08f6, 0x0192), /*                    function ƒ LATIN SMALL LETTER F WITH HOOK */\n    new codepair(0x08fb, 0x2190), /*                   leftarrow ← LEFTWARDS ARROW */\n    new codepair(0x08fc, 0x2191), /*                     uparrow ↑ UPWARDS ARROW */\n    new codepair(0x08fd, 0x2192), /*                  rightarrow → RIGHTWARDS ARROW */\n    new codepair(0x08fe, 0x2193), /*                   downarrow ↓ DOWNWARDS ARROW */\n  /*  0x09df                                     blank ? ??? */\n    new codepair(0x09e0, 0x25c6), /*                soliddiamond ◆ BLACK DIAMOND */\n    new codepair(0x09e1, 0x2592), /*                checkerboard ▒ MEDIUM SHADE */\n    new codepair(0x09e2, 0x2409), /*                          ht ␉ SYMBOL FOR HORIZONTAL TABULATION */\n    new codepair(0x09e3, 0x240c), /*                          ff ␌ SYMBOL FOR FORM FEED */\n    new codepair(0x09e4, 0x240d), /*                          cr ␍ SYMBOL FOR CARRIAGE RETURN */\n    new codepair(0x09e5, 0x240a), /*                          lf ␊ SYMBOL FOR LINE FEED */\n    new codepair(0x09e8, 0x2424), /*                          nl ␤ SYMBOL FOR NEWLINE */\n    new codepair(0x09e9, 0x240b), /*                          vt ␋ SYMBOL FOR VERTICAL TABULATION */\n    new codepair(0x09ea, 0x2518), /*              lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */\n    new codepair(0x09eb, 0x2510), /*               uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */\n    new codepair(0x09ec, 0x250c), /*                upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */\n    new codepair(0x09ed, 0x2514), /*               lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */\n    new codepair(0x09ee, 0x253c), /*               crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */\n    new codepair(0x09ef, 0x23ba), /*              horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */\n    new codepair(0x09f0, 0x23bb), /*              horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */\n    new codepair(0x09f1, 0x2500), /*              horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */\n    new codepair(0x09f2, 0x23bc), /*              horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */\n    new codepair(0x09f3, 0x23bd), /*              horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */\n    new codepair(0x09f4, 0x251c), /*                       leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */\n    new codepair(0x09f5, 0x2524), /*                      rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */\n    new codepair(0x09f6, 0x2534), /*                        bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */\n    new codepair(0x09f7, 0x252c), /*                        topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */\n    new codepair(0x09f8, 0x2502), /*                     vertbar │ BOX DRAWINGS LIGHT VERTICAL */\n    new codepair(0x0aa1, 0x2003), /*                     emspace   EM SPACE */\n    new codepair(0x0aa2, 0x2002), /*                     enspace   EN SPACE */\n    new codepair(0x0aa3, 0x2004), /*                    em3space   THREE-PER-EM SPACE */\n    new codepair(0x0aa4, 0x2005), /*                    em4space   FOUR-PER-EM SPACE */\n    new codepair(0x0aa5, 0x2007), /*                  digitspace   FIGURE SPACE */\n    new codepair(0x0aa6, 0x2008), /*                  punctspace   PUNCTUATION SPACE */\n    new codepair(0x0aa7, 0x2009), /*                   thinspace   THIN SPACE */\n    new codepair(0x0aa8, 0x200a), /*                   hairspace   HAIR SPACE */\n    new codepair(0x0aa9, 0x2014), /*                      emdash — EM DASH */\n    new codepair(0x0aaa, 0x2013), /*                      endash – EN DASH */\n  /*  0x0aac                               signifblank ? ??? */\n    new codepair(0x0aae, 0x2026), /*                    ellipsis … HORIZONTAL ELLIPSIS */\n    new codepair(0x0aaf, 0x2025), /*             doubbaselinedot ‥ TWO DOT LEADER */\n    new codepair(0x0ab0, 0x2153), /*                    onethird ⅓ VULGAR FRACTION ONE THIRD */\n    new codepair(0x0ab1, 0x2154), /*                   twothirds ⅔ VULGAR FRACTION TWO THIRDS */\n    new codepair(0x0ab2, 0x2155), /*                    onefifth ⅕ VULGAR FRACTION ONE FIFTH */\n    new codepair(0x0ab3, 0x2156), /*                   twofifths ⅖ VULGAR FRACTION TWO FIFTHS */\n    new codepair(0x0ab4, 0x2157), /*                 threefifths ⅗ VULGAR FRACTION THREE FIFTHS */\n    new codepair(0x0ab5, 0x2158), /*                  fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */\n    new codepair(0x0ab6, 0x2159), /*                    onesixth ⅙ VULGAR FRACTION ONE SIXTH */\n    new codepair(0x0ab7, 0x215a), /*                  fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */\n    new codepair(0x0ab8, 0x2105), /*                      careof ℅ CARE OF */\n    new codepair(0x0abb, 0x2012), /*                     figdash ‒ FIGURE DASH */\n    new codepair(0x0abc, 0x2329), /*            leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */\n  /*  0x0abd                              decimalpoint ? ??? */\n    new codepair(0x0abe, 0x232a), /*           rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */\n  /*  0x0abf                                    marker ? ??? */\n    new codepair(0x0ac3, 0x215b), /*                   oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */\n    new codepair(0x0ac4, 0x215c), /*                threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */\n    new codepair(0x0ac5, 0x215d), /*                 fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */\n    new codepair(0x0ac6, 0x215e), /*                seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */\n    new codepair(0x0ac9, 0x2122), /*                   trademark ™ TRADE MARK SIGN */\n    new codepair(0x0aca, 0x2613), /*               signaturemark ☓ SALTIRE */\n  /*  0x0acb                         trademarkincircle ? ??? */\n    new codepair(0x0acc, 0x25c1), /*            leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */\n    new codepair(0x0acd, 0x25b7), /*           rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */\n    new codepair(0x0ace, 0x25cb), /*                emopencircle ○ WHITE CIRCLE */\n    new codepair(0x0acf, 0x25af), /*             emopenrectangle ▯ WHITE VERTICAL RECTANGLE */\n    new codepair(0x0ad0, 0x2018), /*         leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */\n    new codepair(0x0ad1, 0x2019), /*        rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */\n    new codepair(0x0ad2, 0x201c), /*         leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */\n    new codepair(0x0ad3, 0x201d), /*        rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */\n    new codepair(0x0ad4, 0x211e), /*                prescription ℞ PRESCRIPTION TAKE */\n    new codepair(0x0ad6, 0x2032), /*                     minutes ′ PRIME */\n    new codepair(0x0ad7, 0x2033), /*                     seconds ″ DOUBLE PRIME */\n    new codepair(0x0ad9, 0x271d), /*                  latincross ✝ LATIN CROSS */\n  /*  0x0ada                                  hexagram ? ??? */\n    new codepair(0x0adb, 0x25ac), /*            filledrectbullet ▬ BLACK RECTANGLE */\n    new codepair(0x0adc, 0x25c0), /*         filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */\n    new codepair(0x0add, 0x25b6), /*        filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */\n    new codepair(0x0ade, 0x25cf), /*              emfilledcircle ● BLACK CIRCLE */\n    new codepair(0x0adf, 0x25ae), /*                emfilledrect ▮ BLACK VERTICAL RECTANGLE */\n    new codepair(0x0ae0, 0x25e6), /*            enopencircbullet ◦ WHITE BULLET */\n    new codepair(0x0ae1, 0x25ab), /*          enopensquarebullet ▫ WHITE SMALL SQUARE */\n    new codepair(0x0ae2, 0x25ad), /*              openrectbullet ▭ WHITE RECTANGLE */\n    new codepair(0x0ae3, 0x25b3), /*             opentribulletup △ WHITE UP-POINTING TRIANGLE */\n    new codepair(0x0ae4, 0x25bd), /*           opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */\n    new codepair(0x0ae5, 0x2606), /*                    openstar ☆ WHITE STAR */\n    new codepair(0x0ae6, 0x2022), /*          enfilledcircbullet • BULLET */\n    new codepair(0x0ae7, 0x25aa), /*            enfilledsqbullet ▪ BLACK SMALL SQUARE */\n    new codepair(0x0ae8, 0x25b2), /*           filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */\n    new codepair(0x0ae9, 0x25bc), /*         filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */\n    new codepair(0x0aea, 0x261c), /*                 leftpointer ☜ WHITE LEFT POINTING INDEX */\n    new codepair(0x0aeb, 0x261e), /*                rightpointer ☞ WHITE RIGHT POINTING INDEX */\n    new codepair(0x0aec, 0x2663), /*                        club ♣ BLACK CLUB SUIT */\n    new codepair(0x0aed, 0x2666), /*                     diamond ♦ BLACK DIAMOND SUIT */\n    new codepair(0x0aee, 0x2665), /*                       heart ♥ BLACK HEART SUIT */\n    new codepair(0x0af0, 0x2720), /*                maltesecross ✠ MALTESE CROSS */\n    new codepair(0x0af1, 0x2020), /*                      dagger † DAGGER */\n    new codepair(0x0af2, 0x2021), /*                doubledagger ‡ DOUBLE DAGGER */\n    new codepair(0x0af3, 0x2713), /*                   checkmark ✓ CHECK MARK */\n    new codepair(0x0af4, 0x2717), /*                 ballotcross ✗ BALLOT X */\n    new codepair(0x0af5, 0x266f), /*                musicalsharp ♯ MUSIC SHARP SIGN */\n    new codepair(0x0af6, 0x266d), /*                 musicalflat ♭ MUSIC FLAT SIGN */\n    new codepair(0x0af7, 0x2642), /*                  malesymbol ♂ MALE SIGN */\n    new codepair(0x0af8, 0x2640), /*                femalesymbol ♀ FEMALE SIGN */\n    new codepair(0x0af9, 0x260e), /*                   telephone ☎ BLACK TELEPHONE */\n    new codepair(0x0afa, 0x2315), /*           telephonerecorder ⌕ TELEPHONE RECORDER */\n    new codepair(0x0afb, 0x2117), /*         phonographcopyright ℗ SOUND RECORDING COPYRIGHT */\n    new codepair(0x0afc, 0x2038), /*                       caret ‸ CARET */\n    new codepair(0x0afd, 0x201a), /*          singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */\n    new codepair(0x0afe, 0x201e), /*          doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */\n  /*  0x0aff                                    cursor ? ??? */\n    new codepair(0x0ba3, 0x003c), /*                   leftcaret < LESS-THAN SIGN */\n    new codepair(0x0ba6, 0x003e), /*                  rightcaret > GREATER-THAN SIGN */\n    new codepair(0x0ba8, 0x2228), /*                   downcaret ∨ LOGICAL OR */\n    new codepair(0x0ba9, 0x2227), /*                     upcaret ∧ LOGICAL AND */\n    new codepair(0x0bc0, 0x00af), /*                     overbar ¯ MACRON */\n    new codepair(0x0bc2, 0x22a5), /*                    downtack ⊥ UP TACK */\n    new codepair(0x0bc3, 0x2229), /*                      upshoe ∩ INTERSECTION */\n    new codepair(0x0bc4, 0x230a), /*                   downstile ⌊ LEFT FLOOR */\n    new codepair(0x0bc6, 0x005f), /*                    underbar _ LOW LINE */\n    new codepair(0x0bca, 0x2218), /*                         jot ∘ RING OPERATOR */\n    new codepair(0x0bcc, 0x2395), /*                        quad ⎕ APL FUNCTIONAL SYMBOL QUAD */\n    new codepair(0x0bce, 0x22a4), /*                      uptack ⊤ DOWN TACK */\n    new codepair(0x0bcf, 0x25cb), /*                      circle ○ WHITE CIRCLE */\n    new codepair(0x0bd3, 0x2308), /*                     upstile ⌈ LEFT CEILING */\n    new codepair(0x0bd6, 0x222a), /*                    downshoe ∪ UNION */\n    new codepair(0x0bd8, 0x2283), /*                   rightshoe ⊃ SUPERSET OF */\n    new codepair(0x0bda, 0x2282), /*                    leftshoe ⊂ SUBSET OF */\n    new codepair(0x0bdc, 0x22a2), /*                    lefttack ⊢ RIGHT TACK */\n    new codepair(0x0bfc, 0x22a3), /*                   righttack ⊣ LEFT TACK */\n    new codepair(0x0cdf, 0x2017), /*        hebrew_doublelowline ‗ DOUBLE LOW LINE */\n    new codepair(0x0ce0, 0x05d0), /*                hebrew_aleph א HEBREW LETTER ALEF */\n    new codepair(0x0ce1, 0x05d1), /*                  hebrew_bet ב HEBREW LETTER BET */\n    new codepair(0x0ce2, 0x05d2), /*                hebrew_gimel ג HEBREW LETTER GIMEL */\n    new codepair(0x0ce3, 0x05d3), /*                hebrew_dalet ד HEBREW LETTER DALET */\n    new codepair(0x0ce4, 0x05d4), /*                   hebrew_he ה HEBREW LETTER HE */\n    new codepair(0x0ce5, 0x05d5), /*                  hebrew_waw ו HEBREW LETTER VAV */\n    new codepair(0x0ce6, 0x05d6), /*                 hebrew_zain ז HEBREW LETTER ZAYIN */\n    new codepair(0x0ce7, 0x05d7), /*                 hebrew_chet ח HEBREW LETTER HET */\n    new codepair(0x0ce8, 0x05d8), /*                  hebrew_tet ט HEBREW LETTER TET */\n    new codepair(0x0ce9, 0x05d9), /*                  hebrew_yod י HEBREW LETTER YOD */\n    new codepair(0x0cea, 0x05da), /*            hebrew_finalkaph ך HEBREW LETTER FINAL KAF */\n    new codepair(0x0ceb, 0x05db), /*                 hebrew_kaph כ HEBREW LETTER KAF */\n    new codepair(0x0cec, 0x05dc), /*                hebrew_lamed ל HEBREW LETTER LAMED */\n    new codepair(0x0ced, 0x05dd), /*             hebrew_finalmem ם HEBREW LETTER FINAL MEM */\n    new codepair(0x0cee, 0x05de), /*                  hebrew_mem מ HEBREW LETTER MEM */\n    new codepair(0x0cef, 0x05df), /*             hebrew_finalnun ן HEBREW LETTER FINAL NUN */\n    new codepair(0x0cf0, 0x05e0), /*                  hebrew_nun נ HEBREW LETTER NUN */\n    new codepair(0x0cf1, 0x05e1), /*               hebrew_samech ס HEBREW LETTER SAMEKH */\n    new codepair(0x0cf2, 0x05e2), /*                 hebrew_ayin ע HEBREW LETTER AYIN */\n    new codepair(0x0cf3, 0x05e3), /*              hebrew_finalpe ף HEBREW LETTER FINAL PE */\n    new codepair(0x0cf4, 0x05e4), /*                   hebrew_pe פ HEBREW LETTER PE */\n    new codepair(0x0cf5, 0x05e5), /*            hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */\n    new codepair(0x0cf6, 0x05e6), /*                 hebrew_zade צ HEBREW LETTER TSADI */\n    new codepair(0x0cf7, 0x05e7), /*                 hebrew_qoph ק HEBREW LETTER QOF */\n    new codepair(0x0cf8, 0x05e8), /*                 hebrew_resh ר HEBREW LETTER RESH */\n    new codepair(0x0cf9, 0x05e9), /*                 hebrew_shin ש HEBREW LETTER SHIN */\n    new codepair(0x0cfa, 0x05ea), /*                  hebrew_taw ת HEBREW LETTER TAV */\n    new codepair(0x0da1, 0x0e01), /*                  Thai_kokai ก THAI CHARACTER KO KAI */\n    new codepair(0x0da2, 0x0e02), /*                Thai_khokhai ข THAI CHARACTER KHO KHAI */\n    new codepair(0x0da3, 0x0e03), /*               Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */\n    new codepair(0x0da4, 0x0e04), /*               Thai_khokhwai ค THAI CHARACTER KHO KHWAI */\n    new codepair(0x0da5, 0x0e05), /*                Thai_khokhon ฅ THAI CHARACTER KHO KHON */\n    new codepair(0x0da6, 0x0e06), /*             Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */\n    new codepair(0x0da7, 0x0e07), /*                 Thai_ngongu ง THAI CHARACTER NGO NGU */\n    new codepair(0x0da8, 0x0e08), /*                Thai_chochan จ THAI CHARACTER CHO CHAN */\n    new codepair(0x0da9, 0x0e09), /*               Thai_choching ฉ THAI CHARACTER CHO CHING */\n    new codepair(0x0daa, 0x0e0a), /*               Thai_chochang ช THAI CHARACTER CHO CHANG */\n    new codepair(0x0dab, 0x0e0b), /*                   Thai_soso ซ THAI CHARACTER SO SO */\n    new codepair(0x0dac, 0x0e0c), /*                Thai_chochoe ฌ THAI CHARACTER CHO CHOE */\n    new codepair(0x0dad, 0x0e0d), /*                 Thai_yoying ญ THAI CHARACTER YO YING */\n    new codepair(0x0dae, 0x0e0e), /*                Thai_dochada ฎ THAI CHARACTER DO CHADA */\n    new codepair(0x0daf, 0x0e0f), /*                Thai_topatak ฏ THAI CHARACTER TO PATAK */\n    new codepair(0x0db0, 0x0e10), /*                Thai_thothan ฐ THAI CHARACTER THO THAN */\n    new codepair(0x0db1, 0x0e11), /*          Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */\n    new codepair(0x0db2, 0x0e12), /*             Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */\n    new codepair(0x0db3, 0x0e13), /*                  Thai_nonen ณ THAI CHARACTER NO NEN */\n    new codepair(0x0db4, 0x0e14), /*                  Thai_dodek ด THAI CHARACTER DO DEK */\n    new codepair(0x0db5, 0x0e15), /*                  Thai_totao ต THAI CHARACTER TO TAO */\n    new codepair(0x0db6, 0x0e16), /*               Thai_thothung ถ THAI CHARACTER THO THUNG */\n    new codepair(0x0db7, 0x0e17), /*              Thai_thothahan ท THAI CHARACTER THO THAHAN */\n    new codepair(0x0db8, 0x0e18), /*               Thai_thothong ธ THAI CHARACTER THO THONG */\n    new codepair(0x0db9, 0x0e19), /*                   Thai_nonu น THAI CHARACTER NO NU */\n    new codepair(0x0dba, 0x0e1a), /*               Thai_bobaimai บ THAI CHARACTER BO BAIMAI */\n    new codepair(0x0dbb, 0x0e1b), /*                  Thai_popla ป THAI CHARACTER PO PLA */\n    new codepair(0x0dbc, 0x0e1c), /*               Thai_phophung ผ THAI CHARACTER PHO PHUNG */\n    new codepair(0x0dbd, 0x0e1d), /*                   Thai_fofa ฝ THAI CHARACTER FO FA */\n    new codepair(0x0dbe, 0x0e1e), /*                Thai_phophan พ THAI CHARACTER PHO PHAN */\n    new codepair(0x0dbf, 0x0e1f), /*                  Thai_fofan ฟ THAI CHARACTER FO FAN */\n    new codepair(0x0dc0, 0x0e20), /*             Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */\n    new codepair(0x0dc1, 0x0e21), /*                   Thai_moma ม THAI CHARACTER MO MA */\n    new codepair(0x0dc2, 0x0e22), /*                  Thai_yoyak ย THAI CHARACTER YO YAK */\n    new codepair(0x0dc3, 0x0e23), /*                  Thai_rorua ร THAI CHARACTER RO RUA */\n    new codepair(0x0dc4, 0x0e24), /*                     Thai_ru ฤ THAI CHARACTER RU */\n    new codepair(0x0dc5, 0x0e25), /*                 Thai_loling ล THAI CHARACTER LO LING */\n    new codepair(0x0dc6, 0x0e26), /*                     Thai_lu ฦ THAI CHARACTER LU */\n    new codepair(0x0dc7, 0x0e27), /*                 Thai_wowaen ว THAI CHARACTER WO WAEN */\n    new codepair(0x0dc8, 0x0e28), /*                 Thai_sosala ศ THAI CHARACTER SO SALA */\n    new codepair(0x0dc9, 0x0e29), /*                 Thai_sorusi ษ THAI CHARACTER SO RUSI */\n    new codepair(0x0dca, 0x0e2a), /*                  Thai_sosua ส THAI CHARACTER SO SUA */\n    new codepair(0x0dcb, 0x0e2b), /*                  Thai_hohip ห THAI CHARACTER HO HIP */\n    new codepair(0x0dcc, 0x0e2c), /*                Thai_lochula ฬ THAI CHARACTER LO CHULA */\n    new codepair(0x0dcd, 0x0e2d), /*                   Thai_oang อ THAI CHARACTER O ANG */\n    new codepair(0x0dce, 0x0e2e), /*               Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */\n    new codepair(0x0dcf, 0x0e2f), /*              Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */\n    new codepair(0x0dd0, 0x0e30), /*                  Thai_saraa ะ THAI CHARACTER SARA A */\n    new codepair(0x0dd1, 0x0e31), /*             Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */\n    new codepair(0x0dd2, 0x0e32), /*                 Thai_saraaa า THAI CHARACTER SARA AA */\n    new codepair(0x0dd3, 0x0e33), /*                 Thai_saraam ำ THAI CHARACTER SARA AM */\n    new codepair(0x0dd4, 0x0e34), /*                  Thai_sarai ิ THAI CHARACTER SARA I */\n    new codepair(0x0dd5, 0x0e35), /*                 Thai_saraii ี THAI CHARACTER SARA II */\n    new codepair(0x0dd6, 0x0e36), /*                 Thai_saraue ึ THAI CHARACTER SARA UE */\n    new codepair(0x0dd7, 0x0e37), /*                Thai_sarauee ื THAI CHARACTER SARA UEE */\n    new codepair(0x0dd8, 0x0e38), /*                  Thai_sarau ุ THAI CHARACTER SARA U */\n    new codepair(0x0dd9, 0x0e39), /*                 Thai_sarauu ู THAI CHARACTER SARA UU */\n    new codepair(0x0dda, 0x0e3a), /*                Thai_phinthu ฺ THAI CHARACTER PHINTHU */\n  /*  0x0dde                    Thai_maihanakat_maitho ? ??? */\n    new codepair(0x0ddf, 0x0e3f), /*                   Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */\n    new codepair(0x0de0, 0x0e40), /*                  Thai_sarae เ THAI CHARACTER SARA E */\n    new codepair(0x0de1, 0x0e41), /*                 Thai_saraae แ THAI CHARACTER SARA AE */\n    new codepair(0x0de2, 0x0e42), /*                  Thai_sarao โ THAI CHARACTER SARA O */\n    new codepair(0x0de3, 0x0e43), /*          Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */\n    new codepair(0x0de4, 0x0e44), /*         Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */\n    new codepair(0x0de5, 0x0e45), /*            Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */\n    new codepair(0x0de6, 0x0e46), /*               Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */\n    new codepair(0x0de7, 0x0e47), /*              Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */\n    new codepair(0x0de8, 0x0e48), /*                  Thai_maiek ่ THAI CHARACTER MAI EK */\n    new codepair(0x0de9, 0x0e49), /*                 Thai_maitho ้ THAI CHARACTER MAI THO */\n    new codepair(0x0dea, 0x0e4a), /*                 Thai_maitri ๊ THAI CHARACTER MAI TRI */\n    new codepair(0x0deb, 0x0e4b), /*            Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */\n    new codepair(0x0dec, 0x0e4c), /*            Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */\n    new codepair(0x0ded, 0x0e4d), /*               Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */\n    new codepair(0x0df0, 0x0e50), /*                 Thai_leksun ๐ THAI DIGIT ZERO */\n    new codepair(0x0df1, 0x0e51), /*                Thai_leknung ๑ THAI DIGIT ONE */\n    new codepair(0x0df2, 0x0e52), /*                Thai_leksong ๒ THAI DIGIT TWO */\n    new codepair(0x0df3, 0x0e53), /*                 Thai_leksam ๓ THAI DIGIT THREE */\n    new codepair(0x0df4, 0x0e54), /*                  Thai_leksi ๔ THAI DIGIT FOUR */\n    new codepair(0x0df5, 0x0e55), /*                  Thai_lekha ๕ THAI DIGIT FIVE */\n    new codepair(0x0df6, 0x0e56), /*                 Thai_lekhok ๖ THAI DIGIT SIX */\n    new codepair(0x0df7, 0x0e57), /*                Thai_lekchet ๗ THAI DIGIT SEVEN */\n    new codepair(0x0df8, 0x0e58), /*                Thai_lekpaet ๘ THAI DIGIT EIGHT */\n    new codepair(0x0df9, 0x0e59), /*                 Thai_lekkao ๙ THAI DIGIT NINE */\n    new codepair(0x0ea1, 0x3131), /*               Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */\n    new codepair(0x0ea2, 0x3132), /*          Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */\n    new codepair(0x0ea3, 0x3133), /*           Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */\n    new codepair(0x0ea4, 0x3134), /*                Hangul_Nieun ㄴ HANGUL LETTER NIEUN */\n    new codepair(0x0ea5, 0x3135), /*           Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */\n    new codepair(0x0ea6, 0x3136), /*           Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */\n    new codepair(0x0ea7, 0x3137), /*               Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */\n    new codepair(0x0ea8, 0x3138), /*          Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */\n    new codepair(0x0ea9, 0x3139), /*                Hangul_Rieul ㄹ HANGUL LETTER RIEUL */\n    new codepair(0x0eaa, 0x313a), /*          Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */\n    new codepair(0x0eab, 0x313b), /*           Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */\n    new codepair(0x0eac, 0x313c), /*           Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */\n    new codepair(0x0ead, 0x313d), /*            Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */\n    new codepair(0x0eae, 0x313e), /*           Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */\n    new codepair(0x0eaf, 0x313f), /*          Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */\n    new codepair(0x0eb0, 0x3140), /*           Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */\n    new codepair(0x0eb1, 0x3141), /*                Hangul_Mieum ㅁ HANGUL LETTER MIEUM */\n    new codepair(0x0eb2, 0x3142), /*                Hangul_Pieub ㅂ HANGUL LETTER PIEUP */\n    new codepair(0x0eb3, 0x3143), /*           Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */\n    new codepair(0x0eb4, 0x3144), /*            Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */\n    new codepair(0x0eb5, 0x3145), /*                 Hangul_Sios ㅅ HANGUL LETTER SIOS */\n    new codepair(0x0eb6, 0x3146), /*            Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */\n    new codepair(0x0eb7, 0x3147), /*                Hangul_Ieung ㅇ HANGUL LETTER IEUNG */\n    new codepair(0x0eb8, 0x3148), /*                Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */\n    new codepair(0x0eb9, 0x3149), /*           Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */\n    new codepair(0x0eba, 0x314a), /*                Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */\n    new codepair(0x0ebb, 0x314b), /*               Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */\n    new codepair(0x0ebc, 0x314c), /*                Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */\n    new codepair(0x0ebd, 0x314d), /*               Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */\n    new codepair(0x0ebe, 0x314e), /*                Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */\n    new codepair(0x0ebf, 0x314f), /*                    Hangul_A ㅏ HANGUL LETTER A */\n    new codepair(0x0ec0, 0x3150), /*                   Hangul_AE ㅐ HANGUL LETTER AE */\n    new codepair(0x0ec1, 0x3151), /*                   Hangul_YA ㅑ HANGUL LETTER YA */\n    new codepair(0x0ec2, 0x3152), /*                  Hangul_YAE ㅒ HANGUL LETTER YAE */\n    new codepair(0x0ec3, 0x3153), /*                   Hangul_EO ㅓ HANGUL LETTER EO */\n    new codepair(0x0ec4, 0x3154), /*                    Hangul_E ㅔ HANGUL LETTER E */\n    new codepair(0x0ec5, 0x3155), /*                  Hangul_YEO ㅕ HANGUL LETTER YEO */\n    new codepair(0x0ec6, 0x3156), /*                   Hangul_YE ㅖ HANGUL LETTER YE */\n    new codepair(0x0ec7, 0x3157), /*                    Hangul_O ㅗ HANGUL LETTER O */\n    new codepair(0x0ec8, 0x3158), /*                   Hangul_WA ㅘ HANGUL LETTER WA */\n    new codepair(0x0ec9, 0x3159), /*                  Hangul_WAE ㅙ HANGUL LETTER WAE */\n    new codepair(0x0eca, 0x315a), /*                   Hangul_OE ㅚ HANGUL LETTER OE */\n    new codepair(0x0ecb, 0x315b), /*                   Hangul_YO ㅛ HANGUL LETTER YO */\n    new codepair(0x0ecc, 0x315c), /*                    Hangul_U ㅜ HANGUL LETTER U */\n    new codepair(0x0ecd, 0x315d), /*                  Hangul_WEO ㅝ HANGUL LETTER WEO */\n    new codepair(0x0ece, 0x315e), /*                   Hangul_WE ㅞ HANGUL LETTER WE */\n    new codepair(0x0ecf, 0x315f), /*                   Hangul_WI ㅟ HANGUL LETTER WI */\n    new codepair(0x0ed0, 0x3160), /*                   Hangul_YU ㅠ HANGUL LETTER YU */\n    new codepair(0x0ed1, 0x3161), /*                   Hangul_EU ㅡ HANGUL LETTER EU */\n    new codepair(0x0ed2, 0x3162), /*                   Hangul_YI ㅢ HANGUL LETTER YI */\n    new codepair(0x0ed3, 0x3163), /*                    Hangul_I ㅣ HANGUL LETTER I */\n    new codepair(0x0ed4, 0x11a8), /*             Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */\n    new codepair(0x0ed5, 0x11a9), /*        Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */\n    new codepair(0x0ed6, 0x11aa), /*         Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */\n    new codepair(0x0ed7, 0x11ab), /*              Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */\n    new codepair(0x0ed8, 0x11ac), /*         Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */\n    new codepair(0x0ed9, 0x11ad), /*         Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */\n    new codepair(0x0eda, 0x11ae), /*             Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */\n    new codepair(0x0edb, 0x11af), /*              Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */\n    new codepair(0x0edc, 0x11b0), /*        Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */\n    new codepair(0x0edd, 0x11b1), /*         Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */\n    new codepair(0x0ede, 0x11b2), /*         Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */\n    new codepair(0x0edf, 0x11b3), /*          Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */\n    new codepair(0x0ee0, 0x11b4), /*         Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */\n    new codepair(0x0ee1, 0x11b5), /*        Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */\n    new codepair(0x0ee2, 0x11b6), /*         Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */\n    new codepair(0x0ee3, 0x11b7), /*              Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */\n    new codepair(0x0ee4, 0x11b8), /*              Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */\n    new codepair(0x0ee5, 0x11b9), /*          Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */\n    new codepair(0x0ee6, 0x11ba), /*               Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */\n    new codepair(0x0ee7, 0x11bb), /*          Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */\n    new codepair(0x0ee8, 0x11bc), /*              Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */\n    new codepair(0x0ee9, 0x11bd), /*              Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */\n    new codepair(0x0eea, 0x11be), /*              Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */\n    new codepair(0x0eeb, 0x11bf), /*             Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */\n    new codepair(0x0eec, 0x11c0), /*              Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */\n    new codepair(0x0eed, 0x11c1), /*             Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */\n    new codepair(0x0eee, 0x11c2), /*              Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */\n    new codepair(0x0eef, 0x316d), /*     Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */\n    new codepair(0x0ef0, 0x3171), /*    Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */\n    new codepair(0x0ef1, 0x3178), /*    Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */\n    new codepair(0x0ef2, 0x317f), /*              Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */\n    new codepair(0x0ef3, 0x3181), /*    Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */\n    new codepair(0x0ef4, 0x3184), /*   Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */\n    new codepair(0x0ef5, 0x3186), /*          Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */\n    new codepair(0x0ef6, 0x318d), /*                Hangul_AraeA ㆍ HANGUL LETTER ARAEA */\n    new codepair(0x0ef7, 0x318e), /*               Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */\n    new codepair(0x0ef8, 0x11eb), /*            Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */\n    new codepair(0x0ef9, 0x11f0), /*  Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */\n    new codepair(0x0efa, 0x11f9), /*        Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */\n    new codepair(0x0eff, 0x20a9), /*                  Korean_Won ₩ WON SIGN */\n    new codepair(0x13bc, 0x0152), /*                          OE Œ LATIN CAPITAL LIGATURE OE */\n    new codepair(0x13bd, 0x0153), /*                          oe œ LATIN SMALL LIGATURE OE */\n    new codepair(0x13be, 0x0178), /*                  Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */\n    new codepair(0x20ac, 0x20ac), /*                    EuroSign € EURO SIGN */\n    new codepair(0xfe50, 0x0300), /*                               COMBINING GRAVE ACCENT */\n    new codepair(0xfe51, 0x0301), /*                               COMBINING ACUTE ACCENT */\n    new codepair(0xfe52, 0x0302), /*                               COMBINING CIRCUMFLEX ACCENT */\n    new codepair(0xfe53, 0x0303), /*                               COMBINING TILDE */\n    new codepair(0xfe54, 0x0304), /*                               COMBINING MACRON */\n    new codepair(0xfe55, 0x0306), /*                               COMBINING BREVE */\n    new codepair(0xfe56, 0x0307), /*                               COMBINING DOT ABOVE */\n    new codepair(0xfe57, 0x0308), /*                               COMBINING DIAERESIS */\n    new codepair(0xfe58, 0x030a), /*                               COMBINING RING ABOVE */\n    new codepair(0xfe59, 0x030b), /*                               COMBINING DOUBLE ACUTE ACCENT */\n    new codepair(0xfe5a, 0x030c), /*                               COMBINING CARON */\n    new codepair(0xfe5b, 0x0327), /*                               COMBINING CEDILLA */\n    new codepair(0xfe5c, 0x0328), /*                               COMBINING OGONEK */\n    new codepair(0xfe5d, 0x1da5), /*                               MODIFIER LETTER SMALL IOTA */\n    new codepair(0xfe5e, 0x3099), /*                               COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK */\n    new codepair(0xfe5f, 0x309a), /*                               COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */\n    new codepair(0xfe60, 0x0323), /*                               COMBINING DOT BELOW */\n  };\n\n  public static combiningpair[] combinetab = {\n    new combiningpair(0x0060, 0x0300), /*                GRAVE ACCENT ` COMBINING GRAVE ACCENT */\n    new combiningpair(0x00b4, 0x0301), /*                ACUTE ACCENT ´ COMBINING ACUTE ACCENT */\n    new combiningpair(0x0027, 0x0301), /*                  APOSTROPHE ' COMBINING ACUTE ACCENT */\n    new combiningpair(0x0384, 0x0301), /*                 GREEK TONOS ΄ COMBINING ACUTE ACCENT */\n    new combiningpair(0x005e, 0x0302), /*           CIRCUMFLEX ACCENT ^ COMBINING CIRCUMFLEX ACCENT */\n    new combiningpair(0x007e, 0x0303), /*                       TILDE ~ COMBINING TILDE */\n    new combiningpair(0x00af, 0x0304), /*                      MACRON ¯ COMBINING MACRON */\n    new combiningpair(0x02d8, 0x0306), /*                       BREVE ˘ COMBINING BREVE */\n    new combiningpair(0x02d9, 0x0307), /*                   DOT ABOVE ˙ COMBINING DOT ABOVE */\n    new combiningpair(0x00a8, 0x0308), /*                   DIAERESIS ¨ COMBINING DIAERESIS */\n    new combiningpair(0x0022, 0x0308), /*              QUOTATION MARK \" COMBINING DIAERESIS */\n    new combiningpair(0x02da, 0x030a), /*                  RING ABOVE ˚ COMBINING RING ABOVE */\n    new combiningpair(0x00b0, 0x030a), /*                 DEGREE SIGN ° COMBINING RING ABOVE */\n    new combiningpair(0x02dd, 0x030b), /*         DOUBLE ACUTE ACCENT ˝ COMBINING DOUBLE ACUTE ACCENT */\n    new combiningpair(0x02c7, 0x030c), /*                       CARON ˇ COMBINING CARON */\n    new combiningpair(0x00b8, 0x0327), /*                     CEDILLA ¸ COMBINING CEDILLA */\n    new combiningpair(0x02db, 0x0328), /*                      OGONEK ¸ COMBINING OGONEK */\n    new combiningpair(0x037a, 0x0345), /*         GREEK YPOGEGRAMMENI ͺ COMBINING GREEK YPOGEGRAMMENI */\n    new combiningpair(0x309b, 0x3099), /* KATAKANA-HIRAGANA VOICED SOUND MARK ゛COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK */\n    new combiningpair(0x309c, 0x309a), /* KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK ゜COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */\n    new combiningpair(0x002e, 0x0323), /*                   FULL STOP . COMBINING DOT BELOW */\n    new combiningpair(0x0385, 0x0344), /*       GREEK DIALYTIKA TONOS ΅ COMBINING GREEK DIALYTIKA TONOS */\n  };\n\n  public static int keysym2ucs(int keysym)\n  {\n    int min = 0;\n    int max = keysymtab.length - 1;\n    int mid;\n\n    /* first check for Latin-1 characters (1:1 mapping) */\n    if ((keysym >= 0x0020 && keysym <= 0x007e) ||\n        (keysym >= 0x00a0 && keysym <= 0x00ff))\n      return keysym;\n\n    /* also check for directly encoded 24-bit UCS characters */\n    if ((keysym & 0xff000000) == 0x01000000)\n      return keysym & 0x00ffffff;\n\n    /* binary search in table */\n    while (max >= min) {\n      mid = (min + max) / 2;\n      if (keysymtab[mid].keysym < keysym)\n        min = mid + 1;\n      else if (keysymtab[mid].keysym > keysym)\n        max = mid - 1;\n      else {\n        /* found it */\n        return keysymtab[mid].ucs;\n      }\n    }\n\n    /* no matching Unicode value found */\n    return -1;\n  }\n\n  public static int ucs2keysym(int ucs) {\n    int cur = 0;\n    int max = keysymtab.length - 1;\n\n    /* first check for Latin-1 characters (1:1 mapping) */\n    if ((ucs >= 0x0020 && ucs <= 0x007e) ||\n        (ucs >= 0x00a0 && ucs <= 0x00ff))\n      return ucs;\n\n    /* linear search in table */\n    while (cur <= max) {\n      if (keysymtab[cur].ucs == ucs)\n        return keysymtab[cur].keysym;\n      cur++;\n    }\n\n    /* use the directly encoded 24-bit UCS character */\n    if ((ucs & 0xff000000) == 0)\n      return ucs | 0x01000000;\n\n    /* no matching Unicode value found */\n    return NoSymbol;\n  }\n\n  public static int ucs2combining(int spacing)\n  {\n    int cur = 0;\n    int max = combinetab.length - 1;\n\n    /* linear search in table */\n    while (cur <= max) {\n      if (combinetab[cur].spacing == spacing)\n        return combinetab[cur].combining;\n      cur++;\n    }\n\n    /* no matching Unicode value found */\n    return -1;\n  }\n\n  private static final int NoSymbol = 0;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Keysymdef.java",
    "content": "/* Copyright (C) 2017 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class Keysymdef {\n\n  public static final int XK_VoidSymbol = 0xFFFFFF; /* void symbol */\n\n  /*\n   * TTY Functions, cleverly chosen to map to ascii, for convenience of\n   * programming, but could have been arbitrary (at the cost of lookup\n   * tables in client code.\n   */\n\n  public static final int XK_BackSpace = 0xFF08; /* back space, back char */\n  public static final int XK_Tab = 0xFF09;\n  public static final int XK_Linefeed = 0xFF0A; /* Linefeed, LF */\n  public static final int XK_Clear = 0xFF0B;\n  public static final int XK_Return = 0xFF0D; /* Return, enter */\n  public static final int XK_Pause = 0xFF13; /* Pause, hold */\n  public static final int XK_Scroll_Lock = 0xFF14;\n  public static final int XK_Sys_Req = 0xFF15;\n  public static final int XK_Escape = 0xFF1B;\n  public static final int XK_Delete = 0xFFFF; /* Delete, rubout */\n\n  /* International & multi-key character composition */\n\n  public static final int XK_Multi_key = 0xFF20;  /* Multi-key character compose */\n  public static final int XK_Codeinput = 0xFF37;\n  public static final int XK_SingleCandidate = 0xFF3C;\n  public static final int XK_MultipleCandidate = 0xFF3D;\n  public static final int XK_PreviousCandidate = 0xFF3E;\n\n  /* Japanese keyboard support */\n\n  public static final int XK_Kanji = 0xFF21; /* Kanji, Kanji convert */\n  public static final int XK_Muhenkan = 0xFF22;  /* Cancel Conversion */\n  public static final int XK_Henkan_Mode = 0xFF23;  /* Start/Stop Conversion */\n  public static final int XK_Henkan = 0xFF23;  /* Alias for Henkan_Mode */\n  public static final int XK_Romaji = 0xFF24;  /* to Romaji */\n  public static final int XK_Hiragana = 0xFF25;  /* to Hiragana */\n  public static final int XK_Katakana = 0xFF26;  /* to Katakana */\n  public static final int XK_Hiragana_Katakana = 0xFF27;  /* Hiragana/Katakana toggle */\n  public static final int XK_Zenkaku = 0xFF28;  /* to Zenkaku */\n  public static final int XK_Hankaku = 0xFF29;  /* to Hankaku */\n  public static final int XK_Zenkaku_Hankaku = 0xFF2A;  /* Zenkaku/Hankaku toggle */\n  public static final int XK_Touroku = 0xFF2B;  /* Add to Dictionary */\n  public static final int XK_Massyo = 0xFF2C;  /* Delete from Dictionary */\n  public static final int XK_Kana_Lock = 0xFF2D;  /* Kana Lock */\n  public static final int XK_Kana_Shift = 0xFF2E;  /* Kana Shift */\n  public static final int XK_Eisu_Shift = 0xFF2F;  /* Alphanumeric Shift */\n  public static final int XK_Eisu_toggle = 0xFF30;  /* Alphanumeric toggle */\n  public static final int XK_Kanji_Bangou = 0xFF37;  /* Codeinput */\n  public static final int XK_Zen_Koho = 0xFF3D; /* Multiple/All Candidate(s) */\n  public static final int XK_Mae_Koho = 0xFF3E; /* Previous Candidate */\n\n  /* 0xFF31 thru 0xFF3F are under XK_KOREAN */\n\n  /* Cursor control & motion */\n\n  public static final int XK_Home = 0xFF50;\n  public static final int XK_Left = 0xFF51; /* Move left, left arrow */\n  public static final int XK_Up = 0xFF52; /* Move up, up arrow */\n  public static final int XK_Right = 0xFF53; /* Move right, right arrow */\n  public static final int XK_Down = 0xFF54; /* Move down, down arrow */\n  public static final int XK_Prior = 0xFF55; /* Prior, previous */\n  public static final int XK_Page_Up = 0xFF55;\n  public static final int XK_Next = 0xFF56; /* Next */\n  public static final int XK_Page_Down = 0xFF56;\n  public static final int XK_End = 0xFF57; /* EOL */\n  public static final int XK_Begin = 0xFF58; /* BOL */\n\n\n  /* Misc Functions */\n\n  public static final int XK_Select = 0xFF60; /* Select, mark */\n  public static final int XK_Print = 0xFF61;\n  public static final int XK_Execute = 0xFF62; /* Execute, run, do */\n  public static final int XK_Insert = 0xFF63; /* Insert, insert here */\n  public static final int XK_Undo = 0xFF65; /* Undo, oops */\n  public static final int XK_Redo = 0xFF66; /* redo, again */\n  public static final int XK_Menu = 0xFF67;\n  public static final int XK_Find = 0xFF68; /* Find, search */\n  public static final int XK_Cancel = 0xFF69; /* Cancel, stop, abort, exit */\n  public static final int XK_Help = 0xFF6A; /* Help */\n  public static final int XK_Break = 0xFF6B;\n  public static final int XK_Mode_switch = 0xFF7E; /* Character set switch */\n  public static final int XK_script_switch = 0xFF7E;  /* Alias for mode_switch */\n  public static final int XK_Num_Lock = 0xFF7F;\n\n  /* Keypad Functions, keypad numbers cleverly chosen to map to ascii */\n\n  public static final int XK_KP_Space = 0xFF80; /* space */\n  public static final int XK_KP_Tab = 0xFF89;\n  public static final int XK_KP_Enter = 0xFF8D; /* enter */\n  public static final int XK_KP_F1 = 0xFF91; /* PF1, KP_A, ... */\n  public static final int XK_KP_F2 = 0xFF92;\n  public static final int XK_KP_F3 = 0xFF93;\n  public static final int XK_KP_F4 = 0xFF94;\n  public static final int XK_KP_Home = 0xFF95;\n  public static final int XK_KP_Left = 0xFF96;\n  public static final int XK_KP_Up = 0xFF97;\n  public static final int XK_KP_Right = 0xFF98;\n  public static final int XK_KP_Down = 0xFF99;\n  public static final int XK_KP_Prior = 0xFF9A;\n  public static final int XK_KP_Page_Up = 0xFF9A;\n  public static final int XK_KP_Next = 0xFF9B;\n  public static final int XK_KP_Page_Down = 0xFF9B;\n  public static final int XK_KP_End = 0xFF9C;\n  public static final int XK_KP_Begin = 0xFF9D;\n  public static final int XK_KP_Insert = 0xFF9E;\n  public static final int XK_KP_Delete = 0xFF9F;\n  public static final int XK_KP_Equal = 0xFFBD; /* equals */\n  public static final int XK_KP_Multiply = 0xFFAA;\n  public static final int XK_KP_Add = 0xFFAB;\n  public static final int XK_KP_Separator = 0xFFAC; /* separator, often comma */\n  public static final int XK_KP_Subtract = 0xFFAD;\n  public static final int XK_KP_Decimal = 0xFFAE;\n  public static final int XK_KP_Divide = 0xFFAF;\n\n  public static final int XK_KP_0 = 0xFFB0;\n  public static final int XK_KP_1 = 0xFFB1;\n  public static final int XK_KP_2 = 0xFFB2;\n  public static final int XK_KP_3 = 0xFFB3;\n  public static final int XK_KP_4 = 0xFFB4;\n  public static final int XK_KP_5 = 0xFFB5;\n  public static final int XK_KP_6 = 0xFFB6;\n  public static final int XK_KP_7 = 0xFFB7;\n  public static final int XK_KP_8 = 0xFFB8;\n  public static final int XK_KP_9 = 0xFFB9;\n\n  /*\n   * Auxiliary Functions; note the duplicate definitions for left and right;\n   * function keys;  Sun keyboards and a few other manufactures have such;\n   * function key groups on the left and/or right sides of the keyboard.\n   * We've not found a keyboard with more than 35 function keys total.\n   */\n\n  public static final int XK_F1 = 0xFFBE;\n  public static final int XK_F2 = 0xFFBF;\n  public static final int XK_F3 = 0xFFC0;\n  public static final int XK_F4 = 0xFFC1;\n  public static final int XK_F5 = 0xFFC2;\n  public static final int XK_F6 = 0xFFC3;\n  public static final int XK_F7 = 0xFFC4;\n  public static final int XK_F8 = 0xFFC5;\n  public static final int XK_F9 = 0xFFC6;\n  public static final int XK_F10 = 0xFFC7;\n  public static final int XK_F11 = 0xFFC8;\n  public static final int XK_L1 = 0xFFC8;\n  public static final int XK_F12 = 0xFFC9;\n  public static final int XK_L2 = 0xFFC9;\n  public static final int XK_F13 = 0xFFCA;\n  public static final int XK_L3 = 0xFFCA;\n  public static final int XK_F14 = 0xFFCB;\n  public static final int XK_L4 = 0xFFCB;\n  public static final int XK_F15 = 0xFFCC;\n  public static final int XK_L5 = 0xFFCC;\n  public static final int XK_F16 = 0xFFCD;\n  public static final int XK_L6 = 0xFFCD;\n  public static final int XK_F17 = 0xFFCE;\n  public static final int XK_L7 = 0xFFCE;\n  public static final int XK_F18 = 0xFFCF;\n  public static final int XK_L8 = 0xFFCF;\n  public static final int XK_F19 = 0xFFD0;\n  public static final int XK_L9 = 0xFFD0;\n  public static final int XK_F20 = 0xFFD1;\n  public static final int XK_L10 = 0xFFD1;\n  public static final int XK_F21 = 0xFFD2;\n  public static final int XK_R1 = 0xFFD2;\n  public static final int XK_F22 = 0xFFD3;\n  public static final int XK_R2 = 0xFFD3;\n  public static final int XK_F23 = 0xFFD4;\n  public static final int XK_R3 = 0xFFD4;\n  public static final int XK_F24 = 0xFFD5;\n  public static final int XK_R4 = 0xFFD5;\n  public static final int XK_F25 = 0xFFD6;\n  public static final int XK_R5 = 0xFFD6;\n  public static final int XK_F26 = 0xFFD7;\n  public static final int XK_R6 = 0xFFD7;\n  public static final int XK_F27 = 0xFFD8;\n  public static final int XK_R7 = 0xFFD8;\n  public static final int XK_F28 = 0xFFD9;\n  public static final int XK_R8 = 0xFFD9;\n  public static final int XK_F29 = 0xFFDA;\n  public static final int XK_R9 = 0xFFDA;\n  public static final int XK_F30 = 0xFFDB;\n  public static final int XK_R10 = 0xFFDB;\n  public static final int XK_F31 = 0xFFDC;\n  public static final int XK_R11 = 0xFFDC;\n  public static final int XK_F32 = 0xFFDD;\n  public static final int XK_R12 = 0xFFDD;\n  public static final int XK_F33 = 0xFFDE;\n  public static final int XK_R13 = 0xFFDE;\n  public static final int XK_F34 = 0xFFDF;\n  public static final int XK_R14 = 0xFFDF;\n  public static final int XK_F35 = 0xFFE0;\n  public static final int XK_R15 = 0xFFE0;\n\n  /* Modifiers */\n\n  public static final int XK_Shift_L = 0xFFE1; /* Left shift */\n  public static final int XK_Shift_R = 0xFFE2; /* Right shift */\n  public static final int XK_Control_L = 0xFFE3; /* Left control */\n  public static final int XK_Control_R = 0xFFE4; /* Right control */\n  public static final int XK_Caps_Lock = 0xFFE5; /* Caps lock */\n  public static final int XK_Shift_Lock = 0xFFE6; /* Shift lock */\n\n  public static final int XK_Meta_L = 0xFFE7; /* Left meta */\n  public static final int XK_Meta_R = 0xFFE8; /* Right meta */\n  public static final int XK_Alt_L = 0xFFE9; /* Left alt */\n  public static final int XK_Alt_R = 0xFFEA; /* Right alt */\n  public static final int XK_Super_L = 0xFFEB; /* Left super */\n  public static final int XK_Super_R = 0xFFEC; /* Right super */\n  public static final int XK_Hyper_L = 0xFFED; /* Left hyper */\n  public static final int XK_Hyper_R = 0xFFEE; /* Right hyper */\n\n  /*\n   * ISO 9995 Function and Modifier Keys;\n   * Byte 3 = 0xFE;\n   */\n\n  public static final int XK_ISO_Lock = 0xFE01;\n  public static final int XK_ISO_Level2_Latch = 0xFE02;\n  public static final int XK_ISO_Level3_Shift = 0xFE03;\n  public static final int XK_ISO_Level3_Latch = 0xFE04;\n  public static final int XK_ISO_Level3_Lock = 0xFE05;\n  public static final int XK_ISO_Group_Shift = 0xFF7E; /* Alias for mode_switch */\n  public static final int XK_ISO_Group_Latch = 0xFE06;\n  public static final int XK_ISO_Group_Lock = 0xFE07;\n  public static final int XK_ISO_Next_Group = 0xFE08;\n  public static final int XK_ISO_Next_Group_Lock = 0xFE09;\n  public static final int XK_ISO_Prev_Group = 0xFE0A;\n  public static final int XK_ISO_Prev_Group_Lock = 0xFE0B;\n  public static final int XK_ISO_First_Group = 0xFE0C;\n  public static final int XK_ISO_First_Group_Lock = 0xFE0D;\n  public static final int XK_ISO_Last_Group = 0xFE0E;\n  public static final int XK_ISO_Last_Group_Lock = 0xFE0F;\n\n  public static final int XK_ISO_Left_Tab = 0xFE20;\n  public static final int XK_ISO_Move_Line_Up = 0xFE21;\n  public static final int XK_ISO_Move_Line_Down = 0xFE22;\n  public static final int XK_ISO_Partial_Line_Up = 0xFE23;\n  public static final int XK_ISO_Partial_Line_Down = 0xFE24;\n  public static final int XK_ISO_Partial_Space_Left = 0xFE25;\n  public static final int XK_ISO_Partial_Space_Right = 0xFE26;\n  public static final int XK_ISO_Set_Margin_Left = 0xFE27;\n  public static final int XK_ISO_Set_Margin_Right = 0xFE28;\n  public static final int XK_ISO_Release_Margin_Left = 0xFE29;\n  public static final int XK_ISO_Release_Margin_Right = 0xFE2A;\n  public static final int XK_ISO_Release_Both_Margins = 0xFE2B;\n  public static final int XK_ISO_Fast_Cursor_Left = 0xFE2C;\n  public static final int XK_ISO_Fast_Cursor_Right = 0xFE2D;\n  public static final int XK_ISO_Fast_Cursor_Up = 0xFE2E;\n  public static final int XK_ISO_Fast_Cursor_Down = 0xFE2F;\n  public static final int XK_ISO_Continuous_Underline = 0xFE30;\n  public static final int XK_ISO_Discontinuous_Underline = 0xFE31;\n  public static final int XK_ISO_Emphasize = 0xFE32;\n  public static final int XK_ISO_Center_Object = 0xFE33;\n  public static final int XK_ISO_Enter = 0xFE34;\n\n  public static final int XK_dead_grave = 0xFE50;\n  public static final int XK_dead_acute = 0xFE51;\n  public static final int XK_dead_circumflex = 0xFE52;\n  public static final int XK_dead_tilde = 0xFE53;\n  public static final int XK_dead_macron = 0xFE54;\n  public static final int XK_dead_breve = 0xFE55;\n  public static final int XK_dead_abovedot = 0xFE56;\n  public static final int XK_dead_diaeresis = 0xFE57;\n  public static final int XK_dead_abovering = 0xFE58;\n  public static final int XK_dead_doubleacute = 0xFE59;\n  public static final int XK_dead_caron = 0xFE5A;\n  public static final int XK_dead_cedilla = 0xFE5B;\n  public static final int XK_dead_ogonek = 0xFE5C;\n  public static final int XK_dead_iota = 0xFE5D;\n  public static final int XK_dead_voiced_sound = 0xFE5E;\n  public static final int XK_dead_semivoiced_sound = 0xFE5F;\n  public static final int XK_dead_belowdot = 0xFE60;\n\n  public static final int XK_First_Virtual_Screen = 0xFED0;\n  public static final int XK_Prev_Virtual_Screen = 0xFED1;\n  public static final int XK_Next_Virtual_Screen = 0xFED2;\n  public static final int XK_Last_Virtual_Screen = 0xFED4;\n  public static final int XK_Terminate_Server = 0xFED5;\n\n  public static final int XK_AccessX_Enable = 0xFE70;\n  public static final int XK_AccessX_Feedback_Enable = 0xFE71;\n  public static final int XK_RepeatKeys_Enable = 0xFE72;\n  public static final int XK_SlowKeys_Enable = 0xFE73;\n  public static final int XK_BounceKeys_Enable = 0xFE74;\n  public static final int XK_StickyKeys_Enable = 0xFE75;\n  public static final int XK_MouseKeys_Enable = 0xFE76;\n  public static final int XK_MouseKeys_Accel_Enable = 0xFE77;\n  public static final int XK_Overlay1_Enable = 0xFE78;\n  public static final int XK_Overlay2_Enable = 0xFE79;\n  public static final int XK_AudibleBell_Enable = 0xFE7A;\n\n  public static final int XK_Pointer_Left = 0xFEE0;\n  public static final int XK_Pointer_Right = 0xFEE1;\n  public static final int XK_Pointer_Up = 0xFEE2;\n  public static final int XK_Pointer_Down = 0xFEE3;\n  public static final int XK_Pointer_UpLeft = 0xFEE4;\n  public static final int XK_Pointer_UpRight = 0xFEE5;\n  public static final int XK_Pointer_DownLeft = 0xFEE6;\n  public static final int XK_Pointer_DownRight = 0xFEE7;\n  public static final int XK_Pointer_Button_Dflt = 0xFEE8;\n  public static final int XK_Pointer_Button1 = 0xFEE9;\n  public static final int XK_Pointer_Button2 = 0xFEEA;\n  public static final int XK_Pointer_Button3 = 0xFEEB;\n  public static final int XK_Pointer_Button4 = 0xFEEC;\n  public static final int XK_Pointer_Button5 = 0xFEED;\n  public static final int XK_Pointer_DblClick_Dflt = 0xFEEE;\n  public static final int XK_Pointer_DblClick1 = 0xFEEF;\n  public static final int XK_Pointer_DblClick2 = 0xFEF0;\n  public static final int XK_Pointer_DblClick3 = 0xFEF1;\n  public static final int XK_Pointer_DblClick4 = 0xFEF2;\n  public static final int XK_Pointer_DblClick5 = 0xFEF3;\n  public static final int XK_Pointer_Drag_Dflt = 0xFEF4;\n  public static final int XK_Pointer_Drag1 = 0xFEF5;\n  public static final int XK_Pointer_Drag2 = 0xFEF6;\n  public static final int XK_Pointer_Drag3 = 0xFEF7;\n  public static final int XK_Pointer_Drag4 = 0xFEF8;\n  public static final int XK_Pointer_Drag5 = 0xFEFD;\n\n  public static final int XK_Pointer_EnableKeys = 0xFEF9;\n  public static final int XK_Pointer_Accelerate = 0xFEFA;\n  public static final int XK_Pointer_DfltBtnNext = 0xFEFB;\n  public static final int XK_Pointer_DfltBtnPrev = 0xFEFC;\n\n  /*\n   * 3270 Terminal Keys;\n   * Byte 3 = 0xFD;\n   */\n\n  public static final int XK_3270_Duplicate = 0xFD01;\n  public static final int XK_3270_FieldMark = 0xFD02;\n  public static final int XK_3270_Right2 = 0xFD03;\n  public static final int XK_3270_Left2 = 0xFD04;\n  public static final int XK_3270_BackTab = 0xFD05;\n  public static final int XK_3270_EraseEOF = 0xFD06;\n  public static final int XK_3270_EraseInput = 0xFD07;\n  public static final int XK_3270_Reset = 0xFD08;\n  public static final int XK_3270_Quit = 0xFD09;\n  public static final int XK_3270_PA1 = 0xFD0A;\n  public static final int XK_3270_PA2 = 0xFD0B;\n  public static final int XK_3270_PA3 = 0xFD0C;\n  public static final int XK_3270_Test = 0xFD0D;\n  public static final int XK_3270_Attn = 0xFD0E;\n  public static final int XK_3270_CursorBlink = 0xFD0F;\n  public static final int XK_3270_AltCursor = 0xFD10;\n  public static final int XK_3270_KeyClick = 0xFD11;\n  public static final int XK_3270_Jump = 0xFD12;\n  public static final int XK_3270_Ident = 0xFD13;\n  public static final int XK_3270_Rule = 0xFD14;\n  public static final int XK_3270_Copy = 0xFD15;\n  public static final int XK_3270_Play = 0xFD16;\n  public static final int XK_3270_Setup = 0xFD17;\n  public static final int XK_3270_Record = 0xFD18;\n  public static final int XK_3270_ChangeScreen = 0xFD19;\n  public static final int XK_3270_DeleteWord = 0xFD1A;\n  public static final int XK_3270_ExSelect = 0xFD1B;\n  public static final int XK_3270_CursorSelect = 0xFD1C;\n  public static final int XK_3270_PrintScreen = 0xFD1D;\n  public static final int XK_3270_Enter = 0xFD1E;\n\n  /*\n   *  Latin 1;\n   *  Byte 3 = 0;\n   */\n  public static final int XK_space = 0x020;\n  public static final int XK_exclam = 0x021;\n  public static final int XK_quotedbl = 0x022;\n  public static final int XK_numbersign = 0x023;\n  public static final int XK_dollar = 0x024;\n  public static final int XK_percent = 0x025;\n  public static final int XK_ampersand = 0x026;\n  public static final int XK_apostrophe = 0x027;\n  public static final int XK_quoteright = 0x027; /* deprecated */\n  public static final int XK_parenleft = 0x028;\n  public static final int XK_parenright = 0x029;\n  public static final int XK_asterisk = 0x02a;\n  public static final int XK_plus = 0x02b;\n  public static final int XK_comma = 0x02c;\n  public static final int XK_minus = 0x02d;\n  public static final int XK_period = 0x02e;\n  public static final int XK_slash = 0x02f;\n  public static final int XK_0 = 0x030;\n  public static final int XK_1 = 0x031;\n  public static final int XK_2 = 0x032;\n  public static final int XK_3 = 0x033;\n  public static final int XK_4 = 0x034;\n  public static final int XK_5 = 0x035;\n  public static final int XK_6 = 0x036;\n  public static final int XK_7 = 0x037;\n  public static final int XK_8 = 0x038;\n  public static final int XK_9 = 0x039;\n  public static final int XK_colon = 0x03a;\n  public static final int XK_semicolon = 0x03b;\n  public static final int XK_less = 0x03c;\n  public static final int XK_equal = 0x03d;\n  public static final int XK_greater = 0x03e;\n  public static final int XK_question = 0x03f;\n  public static final int XK_at = 0x040;\n  public static final int XK_A = 0x041;\n  public static final int XK_B = 0x042;\n  public static final int XK_C = 0x043;\n  public static final int XK_D = 0x044;\n  public static final int XK_E = 0x045;\n  public static final int XK_F = 0x046;\n  public static final int XK_G = 0x047;\n  public static final int XK_H = 0x048;\n  public static final int XK_I = 0x049;\n  public static final int XK_J = 0x04a;\n  public static final int XK_K = 0x04b;\n  public static final int XK_L = 0x04c;\n  public static final int XK_M = 0x04d;\n  public static final int XK_N = 0x04e;\n  public static final int XK_O = 0x04f;\n  public static final int XK_P = 0x050;\n  public static final int XK_Q = 0x051;\n  public static final int XK_R = 0x052;\n  public static final int XK_S = 0x053;\n  public static final int XK_T = 0x054;\n  public static final int XK_U = 0x055;\n  public static final int XK_V = 0x056;\n  public static final int XK_W = 0x057;\n  public static final int XK_X = 0x058;\n  public static final int XK_Y = 0x059;\n  public static final int XK_Z = 0x05a;\n  public static final int XK_bracketleft = 0x05b;\n  public static final int XK_backslash = 0x05c;\n  public static final int XK_bracketright = 0x05d;\n  public static final int XK_asciicircum = 0x05e;\n  public static final int XK_underscore = 0x05f;\n  public static final int XK_grave = 0x060;\n  public static final int XK_quoteleft = 0x060; /* deprecated */\n  public static final int XK_a = 0x061;\n  public static final int XK_b = 0x062;\n  public static final int XK_c = 0x063;\n  public static final int XK_d = 0x064;\n  public static final int XK_e = 0x065;\n  public static final int XK_f = 0x066;\n  public static final int XK_g = 0x067;\n  public static final int XK_h = 0x068;\n  public static final int XK_i = 0x069;\n  public static final int XK_j = 0x06a;\n  public static final int XK_k = 0x06b;\n  public static final int XK_l = 0x06c;\n  public static final int XK_m = 0x06d;\n  public static final int XK_n = 0x06e;\n  public static final int XK_o = 0x06f;\n  public static final int XK_p = 0x070;\n  public static final int XK_q = 0x071;\n  public static final int XK_r = 0x072;\n  public static final int XK_s = 0x073;\n  public static final int XK_t = 0x074;\n  public static final int XK_u = 0x075;\n  public static final int XK_v = 0x076;\n  public static final int XK_w = 0x077;\n  public static final int XK_x = 0x078;\n  public static final int XK_y = 0x079;\n  public static final int XK_z = 0x07a;\n  public static final int XK_braceleft = 0x07b;\n  public static final int XK_bar = 0x07c;\n  public static final int XK_braceright = 0x07d;\n  public static final int XK_asciitilde = 0x07e;\n\n  public static final int XK_nobreakspace = 0x0a0;\n  public static final int XK_exclamdown = 0x0a1;\n  public static final int XK_cent = 0x0a2;\n  public static final int XK_sterling = 0x0a3;\n  public static final int XK_currency = 0x0a4;\n  public static final int XK_yen = 0x0a5;\n  public static final int XK_brokenbar = 0x0a6;\n  public static final int XK_section = 0x0a7;\n  public static final int XK_diaeresis = 0x0a8;\n  public static final int XK_copyright = 0x0a9;\n  public static final int XK_ordfeminine = 0x0aa;\n  public static final int XK_guillemotleft = 0x0ab; /* left angle quotation mark */\n  public static final int XK_notsign = 0x0ac;\n  public static final int XK_hyphen = 0x0ad;\n  public static final int XK_registered = 0x0ae;\n  public static final int XK_macron = 0x0af;\n  public static final int XK_degree = 0x0b0;\n  public static final int XK_plusminus = 0x0b1;\n  public static final int XK_twosuperior = 0x0b2;\n  public static final int XK_threesuperior = 0x0b3;\n  public static final int XK_acute = 0x0b4;\n  public static final int XK_mu = 0x0b5;\n  public static final int XK_paragraph = 0x0b6;\n  public static final int XK_periodcentered = 0x0b7;\n  public static final int XK_cedilla = 0x0b8;\n  public static final int XK_onesuperior = 0x0b9;\n  public static final int XK_masculine = 0x0ba;\n  public static final int XK_guillemotright = 0x0bb; /* right angle quotation mark */\n  public static final int XK_onequarter = 0x0bc;\n  public static final int XK_onehalf = 0x0bd;\n  public static final int XK_threequarters = 0x0be;\n  public static final int XK_questiondown = 0x0bf;\n  public static final int XK_Agrave = 0x0c0;\n  public static final int XK_Aacute = 0x0c1;\n  public static final int XK_Acircumflex = 0x0c2;\n  public static final int XK_Atilde = 0x0c3;\n  public static final int XK_Adiaeresis = 0x0c4;\n  public static final int XK_Aring = 0x0c5;\n  public static final int XK_AE = 0x0c6;\n  public static final int XK_Ccedilla = 0x0c7;\n  public static final int XK_Egrave = 0x0c8;\n  public static final int XK_Eacute = 0x0c9;\n  public static final int XK_Ecircumflex = 0x0ca;\n  public static final int XK_Ediaeresis = 0x0cb;\n  public static final int XK_Igrave = 0x0cc;\n  public static final int XK_Iacute = 0x0cd;\n  public static final int XK_Icircumflex = 0x0ce;\n  public static final int XK_Idiaeresis = 0x0cf;\n  public static final int XK_ETH = 0x0d0;\n  public static final int XK_Eth = 0x0d0; /* deprecated */\n  public static final int XK_Ntilde = 0x0d1;\n  public static final int XK_Ograve = 0x0d2;\n  public static final int XK_Oacute = 0x0d3;\n  public static final int XK_Ocircumflex = 0x0d4;\n  public static final int XK_Otilde = 0x0d5;\n  public static final int XK_Odiaeresis = 0x0d6;\n  public static final int XK_multiply = 0x0d7;\n  public static final int XK_Ooblique = 0x0d8;\n  public static final int XK_Ugrave = 0x0d9;\n  public static final int XK_Uacute = 0x0da;\n  public static final int XK_Ucircumflex = 0x0db;\n  public static final int XK_Udiaeresis = 0x0dc;\n  public static final int XK_Yacute = 0x0dd;\n  public static final int XK_THORN = 0x0de;\n  public static final int XK_Thorn = 0x0de; /* deprecated */\n  public static final int XK_ssharp = 0x0df;\n  public static final int XK_agrave = 0x0e0;\n  public static final int XK_aacute = 0x0e1;\n  public static final int XK_acircumflex = 0x0e2;\n  public static final int XK_atilde = 0x0e3;\n  public static final int XK_adiaeresis = 0x0e4;\n  public static final int XK_aring = 0x0e5;\n  public static final int XK_ae = 0x0e6;\n  public static final int XK_ccedilla = 0x0e7;\n  public static final int XK_egrave = 0x0e8;\n  public static final int XK_eacute = 0x0e9;\n  public static final int XK_ecircumflex = 0x0ea;\n  public static final int XK_ediaeresis = 0x0eb;\n  public static final int XK_igrave = 0x0ec;\n  public static final int XK_iacute = 0x0ed;\n  public static final int XK_icircumflex = 0x0ee;\n  public static final int XK_idiaeresis = 0x0ef;\n  public static final int XK_eth = 0x0f0;\n  public static final int XK_ntilde = 0x0f1;\n  public static final int XK_ograve = 0x0f2;\n  public static final int XK_oacute = 0x0f3;\n  public static final int XK_ocircumflex = 0x0f4;\n  public static final int XK_otilde = 0x0f5;\n  public static final int XK_odiaeresis = 0x0f6;\n  public static final int XK_division = 0x0f7;\n  public static final int XK_oslash = 0x0f8;\n  public static final int XK_ugrave = 0x0f9;\n  public static final int XK_uacute = 0x0fa;\n  public static final int XK_ucircumflex = 0x0fb;\n  public static final int XK_udiaeresis = 0x0fc;\n  public static final int XK_yacute = 0x0fd;\n  public static final int XK_thorn = 0x0fe;\n  public static final int XK_ydiaeresis = 0x0ff;\n\n  /*\n   *   Latin 2;\n   *   Byte 3 = 1;\n   */\n\n  public static final int XK_Aogonek = 0x1a1;\n  public static final int XK_breve = 0x1a2;\n  public static final int XK_Lstroke = 0x1a3;\n  public static final int XK_Lcaron = 0x1a5;\n  public static final int XK_Sacute = 0x1a6;\n  public static final int XK_Scaron = 0x1a9;\n  public static final int XK_Scedilla = 0x1aa;\n  public static final int XK_Tcaron = 0x1ab;\n  public static final int XK_Zacute = 0x1ac;\n  public static final int XK_Zcaron = 0x1ae;\n  public static final int XK_Zabovedot = 0x1af;\n  public static final int XK_aogonek = 0x1b1;\n  public static final int XK_ogonek = 0x1b2;\n  public static final int XK_lstroke = 0x1b3;\n  public static final int XK_lcaron = 0x1b5;\n  public static final int XK_sacute = 0x1b6;\n  public static final int XK_caron = 0x1b7;\n  public static final int XK_scaron = 0x1b9;\n  public static final int XK_scedilla = 0x1ba;\n  public static final int XK_tcaron = 0x1bb;\n  public static final int XK_zacute = 0x1bc;\n  public static final int XK_doubleacute = 0x1bd;\n  public static final int XK_zcaron = 0x1be;\n  public static final int XK_zabovedot = 0x1bf;\n  public static final int XK_Racute = 0x1c0;\n  public static final int XK_Abreve = 0x1c3;\n  public static final int XK_Lacute = 0x1c5;\n  public static final int XK_Cacute = 0x1c6;\n  public static final int XK_Ccaron = 0x1c8;\n  public static final int XK_Eogonek = 0x1ca;\n  public static final int XK_Ecaron = 0x1cc;\n  public static final int XK_Dcaron = 0x1cf;\n  public static final int XK_Dstroke = 0x1d0;\n  public static final int XK_Nacute = 0x1d1;\n  public static final int XK_Ncaron = 0x1d2;\n  public static final int XK_Odoubleacute = 0x1d5;\n  public static final int XK_Rcaron = 0x1d8;\n  public static final int XK_Uring = 0x1d9;\n  public static final int XK_Udoubleacute = 0x1db;\n  public static final int XK_Tcedilla = 0x1de;\n  public static final int XK_racute = 0x1e0;\n  public static final int XK_abreve = 0x1e3;\n  public static final int XK_lacute = 0x1e5;\n  public static final int XK_cacute = 0x1e6;\n  public static final int XK_ccaron = 0x1e8;\n  public static final int XK_eogonek = 0x1ea;\n  public static final int XK_ecaron = 0x1ec;\n  public static final int XK_dcaron = 0x1ef;\n  public static final int XK_dstroke = 0x1f0;\n  public static final int XK_nacute = 0x1f1;\n  public static final int XK_ncaron = 0x1f2;\n  public static final int XK_odoubleacute = 0x1f5;\n  public static final int XK_udoubleacute = 0x1fb;\n  public static final int XK_rcaron = 0x1f8;\n  public static final int XK_uring = 0x1f9;\n  public static final int XK_tcedilla = 0x1fe;\n  public static final int XK_abovedot = 0x1ff;\n\n  /*\n   *   Latin 3;\n   *   Byte 3 = 2;\n   */\n\n  public static final int XK_Hstroke = 0x2a1;\n  public static final int XK_Hcircumflex = 0x2a6;\n  public static final int XK_Iabovedot = 0x2a9;\n  public static final int XK_Gbreve = 0x2ab;\n  public static final int XK_Jcircumflex = 0x2ac;\n  public static final int XK_hstroke = 0x2b1;\n  public static final int XK_hcircumflex = 0x2b6;\n  public static final int XK_idotless = 0x2b9;\n  public static final int XK_gbreve = 0x2bb;\n  public static final int XK_jcircumflex = 0x2bc;\n  public static final int XK_Cabovedot = 0x2c5;\n  public static final int XK_Ccircumflex = 0x2c6;\n  public static final int XK_Gabovedot = 0x2d5;\n  public static final int XK_Gcircumflex = 0x2d8;\n  public static final int XK_Ubreve = 0x2dd;\n  public static final int XK_Scircumflex = 0x2de;\n  public static final int XK_cabovedot = 0x2e5;\n  public static final int XK_ccircumflex = 0x2e6;\n  public static final int XK_gabovedot = 0x2f5;\n  public static final int XK_gcircumflex = 0x2f8;\n  public static final int XK_ubreve = 0x2fd;\n  public static final int XK_scircumflex = 0x2fe;\n\n\n  /*\n   *   Latin 4;\n   *   Byte 3 = 3;\n   */\n\n  public static final int XK_kra = 0x3a2;\n  public static final int XK_kappa = 0x3a2; /* deprecated */\n  public static final int XK_Rcedilla = 0x3a3;\n  public static final int XK_Itilde = 0x3a5;\n  public static final int XK_Lcedilla = 0x3a6;\n  public static final int XK_Emacron = 0x3aa;\n  public static final int XK_Gcedilla = 0x3ab;\n  public static final int XK_Tslash = 0x3ac;\n  public static final int XK_rcedilla = 0x3b3;\n  public static final int XK_itilde = 0x3b5;\n  public static final int XK_lcedilla = 0x3b6;\n  public static final int XK_emacron = 0x3ba;\n  public static final int XK_gcedilla = 0x3bb;\n  public static final int XK_tslash = 0x3bc;\n  public static final int XK_ENG = 0x3bd;\n  public static final int XK_eng = 0x3bf;\n  public static final int XK_Amacron = 0x3c0;\n  public static final int XK_Iogonek = 0x3c7;\n  public static final int XK_Eabovedot = 0x3cc;\n  public static final int XK_Imacron = 0x3cf;\n  public static final int XK_Ncedilla = 0x3d1;\n  public static final int XK_Omacron = 0x3d2;\n  public static final int XK_Kcedilla = 0x3d3;\n  public static final int XK_Uogonek = 0x3d9;\n  public static final int XK_Utilde = 0x3dd;\n  public static final int XK_Umacron = 0x3de;\n  public static final int XK_amacron = 0x3e0;\n  public static final int XK_iogonek = 0x3e7;\n  public static final int XK_eabovedot = 0x3ec;\n  public static final int XK_imacron = 0x3ef;\n  public static final int XK_ncedilla = 0x3f1;\n  public static final int XK_omacron = 0x3f2;\n  public static final int XK_kcedilla = 0x3f3;\n  public static final int XK_uogonek = 0x3f9;\n  public static final int XK_utilde = 0x3fd;\n  public static final int XK_umacron = 0x3fe;\n\n  /*\n   * Latin-9 (a.k.a. Latin-0)\n   * Byte 3 = 19;\n   */\n\n  public static final int XK_OE = 0x13bc;\n  public static final int XK_oe = 0x13bd;\n  public static final int XK_Ydiaeresis = 0x13be;\n\n  /*\n   * Katakana;\n   * Byte 3 = 4;\n   */\n\n  public static final int XK_overline = 0x47e;\n  public static final int XK_kana_fullstop = 0x4a1;\n  public static final int XK_kana_openingbracket = 0x4a2;\n  public static final int XK_kana_closingbracket = 0x4a3;\n  public static final int XK_kana_comma = 0x4a4;\n  public static final int XK_kana_conjunctive = 0x4a5;\n  public static final int XK_kana_middledot = 0x4a5;  /* deprecated */\n  public static final int XK_kana_WO = 0x4a6;\n  public static final int XK_kana_a = 0x4a7;\n  public static final int XK_kana_i = 0x4a8;\n  public static final int XK_kana_u = 0x4a9;\n  public static final int XK_kana_e = 0x4aa;\n  public static final int XK_kana_o = 0x4ab;\n  public static final int XK_kana_ya = 0x4ac;\n  public static final int XK_kana_yu = 0x4ad;\n  public static final int XK_kana_yo = 0x4ae;\n  public static final int XK_kana_tsu = 0x4af;\n  public static final int XK_kana_tu = 0x4af;  /* deprecated */\n  public static final int XK_prolongedsound = 0x4b0;\n  public static final int XK_kana_A = 0x4b1;\n  public static final int XK_kana_I = 0x4b2;\n  public static final int XK_kana_U = 0x4b3;\n  public static final int XK_kana_E = 0x4b4;\n  public static final int XK_kana_O = 0x4b5;\n  public static final int XK_kana_KA = 0x4b6;\n  public static final int XK_kana_KI = 0x4b7;\n  public static final int XK_kana_KU = 0x4b8;\n  public static final int XK_kana_KE = 0x4b9;\n  public static final int XK_kana_KO = 0x4ba;\n  public static final int XK_kana_SA = 0x4bb;\n  public static final int XK_kana_SHI = 0x4bc;\n  public static final int XK_kana_SU = 0x4bd;\n  public static final int XK_kana_SE = 0x4be;\n  public static final int XK_kana_SO = 0x4bf;\n  public static final int XK_kana_TA = 0x4c0;\n  public static final int XK_kana_CHI = 0x4c1;\n  public static final int XK_kana_TI = 0x4c1;  /* deprecated */\n  public static final int XK_kana_TSU = 0x4c2;\n  public static final int XK_kana_TU = 0x4c2;  /* deprecated */\n  public static final int XK_kana_TE = 0x4c3;\n  public static final int XK_kana_TO = 0x4c4;\n  public static final int XK_kana_NA = 0x4c5;\n  public static final int XK_kana_NI = 0x4c6;\n  public static final int XK_kana_NU = 0x4c7;\n  public static final int XK_kana_NE = 0x4c8;\n  public static final int XK_kana_NO = 0x4c9;\n  public static final int XK_kana_HA = 0x4ca;\n  public static final int XK_kana_HI = 0x4cb;\n  public static final int XK_kana_FU = 0x4cc;\n  public static final int XK_kana_HU = 0x4cc;  /* deprecated */\n  public static final int XK_kana_HE = 0x4cd;\n  public static final int XK_kana_HO = 0x4ce;\n  public static final int XK_kana_MA = 0x4cf;\n  public static final int XK_kana_MI = 0x4d0;\n  public static final int XK_kana_MU = 0x4d1;\n  public static final int XK_kana_ME = 0x4d2;\n  public static final int XK_kana_MO = 0x4d3;\n  public static final int XK_kana_YA = 0x4d4;\n  public static final int XK_kana_YU = 0x4d5;\n  public static final int XK_kana_YO = 0x4d6;\n  public static final int XK_kana_RA = 0x4d7;\n  public static final int XK_kana_RI = 0x4d8;\n  public static final int XK_kana_RU = 0x4d9;\n  public static final int XK_kana_RE = 0x4da;\n  public static final int XK_kana_RO = 0x4db;\n  public static final int XK_kana_WA = 0x4dc;\n  public static final int XK_kana_N = 0x4dd;\n  public static final int XK_voicedsound = 0x4de;\n  public static final int XK_semivoicedsound = 0x4df;\n  public static final int XK_kana_switch = 0xFF7E;  /* Alias for mode_switch */\n\n  /*\n   *  Arabic;\n   *  Byte 3 = 5;\n   */\n\n  public static final int XK_Arabic_comma = 0x5ac;\n  public static final int XK_Arabic_semicolon = 0x5bb;\n  public static final int XK_Arabic_question_mark = 0x5bf;\n  public static final int XK_Arabic_hamza = 0x5c1;\n  public static final int XK_Arabic_maddaonalef = 0x5c2;\n  public static final int XK_Arabic_hamzaonalef = 0x5c3;\n  public static final int XK_Arabic_hamzaonwaw = 0x5c4;\n  public static final int XK_Arabic_hamzaunderalef = 0x5c5;\n  public static final int XK_Arabic_hamzaonyeh = 0x5c6;\n  public static final int XK_Arabic_alef = 0x5c7;\n  public static final int XK_Arabic_beh = 0x5c8;\n  public static final int XK_Arabic_tehmarbuta = 0x5c9;\n  public static final int XK_Arabic_teh = 0x5ca;\n  public static final int XK_Arabic_theh = 0x5cb;\n  public static final int XK_Arabic_jeem = 0x5cc;\n  public static final int XK_Arabic_hah = 0x5cd;\n  public static final int XK_Arabic_khah = 0x5ce;\n  public static final int XK_Arabic_dal = 0x5cf;\n  public static final int XK_Arabic_thal = 0x5d0;\n  public static final int XK_Arabic_ra = 0x5d1;\n  public static final int XK_Arabic_zain = 0x5d2;\n  public static final int XK_Arabic_seen = 0x5d3;\n  public static final int XK_Arabic_sheen = 0x5d4;\n  public static final int XK_Arabic_sad = 0x5d5;\n  public static final int XK_Arabic_dad = 0x5d6;\n  public static final int XK_Arabic_tah = 0x5d7;\n  public static final int XK_Arabic_zah = 0x5d8;\n  public static final int XK_Arabic_ain = 0x5d9;\n  public static final int XK_Arabic_ghain = 0x5da;\n  public static final int XK_Arabic_tatweel = 0x5e0;\n  public static final int XK_Arabic_feh = 0x5e1;\n  public static final int XK_Arabic_qaf = 0x5e2;\n  public static final int XK_Arabic_kaf = 0x5e3;\n  public static final int XK_Arabic_lam = 0x5e4;\n  public static final int XK_Arabic_meem = 0x5e5;\n  public static final int XK_Arabic_noon = 0x5e6;\n  public static final int XK_Arabic_ha = 0x5e7;\n  public static final int XK_Arabic_heh = 0x5e7;  /* deprecated */\n  public static final int XK_Arabic_waw = 0x5e8;\n  public static final int XK_Arabic_alefmaksura = 0x5e9;\n  public static final int XK_Arabic_yeh = 0x5ea;\n  public static final int XK_Arabic_fathatan = 0x5eb;\n  public static final int XK_Arabic_dammatan = 0x5ec;\n  public static final int XK_Arabic_kasratan = 0x5ed;\n  public static final int XK_Arabic_fatha = 0x5ee;\n  public static final int XK_Arabic_damma = 0x5ef;\n  public static final int XK_Arabic_kasra = 0x5f0;\n  public static final int XK_Arabic_shadda = 0x5f1;\n  public static final int XK_Arabic_sukun = 0x5f2;\n  public static final int XK_Arabic_switch = 0xFF7E;  /* Alias for mode_switch */\n\n  /*\n   * Cyrillic;\n   * Byte 3 = 6;\n   */\n  public static final int XK_Serbian_dje = 0x6a1;\n  public static final int XK_Macedonia_gje = 0x6a2;\n  public static final int XK_Cyrillic_io = 0x6a3;\n  public static final int XK_Ukrainian_ie = 0x6a4;\n  public static final int XK_Ukranian_je = 0x6a4;  /* deprecated */\n  public static final int XK_Macedonia_dse = 0x6a5;\n  public static final int XK_Ukrainian_i = 0x6a6;\n  public static final int XK_Ukranian_i = 0x6a6;  /* deprecated */\n  public static final int XK_Ukrainian_yi = 0x6a7;\n  public static final int XK_Ukranian_yi = 0x6a7;  /* deprecated */\n  public static final int XK_Cyrillic_je = 0x6a8;\n  public static final int XK_Serbian_je = 0x6a8;  /* deprecated */\n  public static final int XK_Cyrillic_lje = 0x6a9;\n  public static final int XK_Serbian_lje = 0x6a9;  /* deprecated */\n  public static final int XK_Cyrillic_nje = 0x6aa;\n  public static final int XK_Serbian_nje = 0x6aa;  /* deprecated */\n  public static final int XK_Serbian_tshe = 0x6ab;\n  public static final int XK_Macedonia_kje = 0x6ac;\n  public static final int XK_Byelorussian_shortu = 0x6ae;\n  public static final int XK_Cyrillic_dzhe = 0x6af;\n  public static final int XK_Serbian_dze = 0x6af;  /* deprecated */\n  public static final int XK_numerosign = 0x6b0;\n  public static final int XK_Serbian_DJE = 0x6b1;\n  public static final int XK_Macedonia_GJE = 0x6b2;\n  public static final int XK_Cyrillic_IO = 0x6b3;\n  public static final int XK_Ukrainian_IE = 0x6b4;\n  public static final int XK_Ukranian_JE = 0x6b4;  /* deprecated */\n  public static final int XK_Macedonia_DSE = 0x6b5;\n  public static final int XK_Ukrainian_I = 0x6b6;\n  public static final int XK_Ukranian_I = 0x6b6;  /* deprecated */\n  public static final int XK_Ukrainian_YI = 0x6b7;\n  public static final int XK_Ukranian_YI = 0x6b7;  /* deprecated */\n  public static final int XK_Cyrillic_JE = 0x6b8;\n  public static final int XK_Serbian_JE = 0x6b8;  /* deprecated */\n  public static final int XK_Cyrillic_LJE = 0x6b9;\n  public static final int XK_Serbian_LJE = 0x6b9;  /* deprecated */\n  public static final int XK_Cyrillic_NJE = 0x6ba;\n  public static final int XK_Serbian_NJE = 0x6ba;  /* deprecated */\n  public static final int XK_Serbian_TSHE = 0x6bb;\n  public static final int XK_Macedonia_KJE = 0x6bc;\n  public static final int XK_Byelorussian_SHORTU = 0x6be;\n  public static final int XK_Cyrillic_DZHE = 0x6bf;\n  public static final int XK_Serbian_DZE = 0x6bf;  /* deprecated */\n  public static final int XK_Cyrillic_yu = 0x6c0;\n  public static final int XK_Cyrillic_a = 0x6c1;\n  public static final int XK_Cyrillic_be = 0x6c2;\n  public static final int XK_Cyrillic_tse = 0x6c3;\n  public static final int XK_Cyrillic_de = 0x6c4;\n  public static final int XK_Cyrillic_ie = 0x6c5;\n  public static final int XK_Cyrillic_ef = 0x6c6;\n  public static final int XK_Cyrillic_ghe = 0x6c7;\n  public static final int XK_Cyrillic_ha = 0x6c8;\n  public static final int XK_Cyrillic_i = 0x6c9;\n  public static final int XK_Cyrillic_shorti = 0x6ca;\n  public static final int XK_Cyrillic_ka = 0x6cb;\n  public static final int XK_Cyrillic_el = 0x6cc;\n  public static final int XK_Cyrillic_em = 0x6cd;\n  public static final int XK_Cyrillic_en = 0x6ce;\n  public static final int XK_Cyrillic_o = 0x6cf;\n  public static final int XK_Cyrillic_pe = 0x6d0;\n  public static final int XK_Cyrillic_ya = 0x6d1;\n  public static final int XK_Cyrillic_er = 0x6d2;\n  public static final int XK_Cyrillic_es = 0x6d3;\n  public static final int XK_Cyrillic_te = 0x6d4;\n  public static final int XK_Cyrillic_u = 0x6d5;\n  public static final int XK_Cyrillic_zhe = 0x6d6;\n  public static final int XK_Cyrillic_ve = 0x6d7;\n  public static final int XK_Cyrillic_softsign = 0x6d8;\n  public static final int XK_Cyrillic_yeru = 0x6d9;\n  public static final int XK_Cyrillic_ze = 0x6da;\n  public static final int XK_Cyrillic_sha = 0x6db;\n  public static final int XK_Cyrillic_e = 0x6dc;\n  public static final int XK_Cyrillic_shcha = 0x6dd;\n  public static final int XK_Cyrillic_che = 0x6de;\n  public static final int XK_Cyrillic_hardsign = 0x6df;\n  public static final int XK_Cyrillic_YU = 0x6e0;\n  public static final int XK_Cyrillic_A = 0x6e1;\n  public static final int XK_Cyrillic_BE = 0x6e2;\n  public static final int XK_Cyrillic_TSE = 0x6e3;\n  public static final int XK_Cyrillic_DE = 0x6e4;\n  public static final int XK_Cyrillic_IE = 0x6e5;\n  public static final int XK_Cyrillic_EF = 0x6e6;\n  public static final int XK_Cyrillic_GHE = 0x6e7;\n  public static final int XK_Cyrillic_HA = 0x6e8;\n  public static final int XK_Cyrillic_I = 0x6e9;\n  public static final int XK_Cyrillic_SHORTI = 0x6ea;\n  public static final int XK_Cyrillic_KA = 0x6eb;\n  public static final int XK_Cyrillic_EL = 0x6ec;\n  public static final int XK_Cyrillic_EM = 0x6ed;\n  public static final int XK_Cyrillic_EN = 0x6ee;\n  public static final int XK_Cyrillic_O = 0x6ef;\n  public static final int XK_Cyrillic_PE = 0x6f0;\n  public static final int XK_Cyrillic_YA = 0x6f1;\n  public static final int XK_Cyrillic_ER = 0x6f2;\n  public static final int XK_Cyrillic_ES = 0x6f3;\n  public static final int XK_Cyrillic_TE = 0x6f4;\n  public static final int XK_Cyrillic_U = 0x6f5;\n  public static final int XK_Cyrillic_ZHE = 0x6f6;\n  public static final int XK_Cyrillic_VE = 0x6f7;\n  public static final int XK_Cyrillic_SOFTSIGN = 0x6f8;\n  public static final int XK_Cyrillic_YERU = 0x6f9;\n  public static final int XK_Cyrillic_ZE = 0x6fa;\n  public static final int XK_Cyrillic_SHA = 0x6fb;\n  public static final int XK_Cyrillic_E = 0x6fc;\n  public static final int XK_Cyrillic_SHCHA = 0x6fd;\n  public static final int XK_Cyrillic_CHE = 0x6fe;\n  public static final int XK_Cyrillic_HARDSIGN = 0x6ff;\n\n  /*\n   * Greek;\n   * Byte 3 = 7;\n   */\n\n  public static final int XK_Greek_ALPHAaccent = 0x7a1;\n  public static final int XK_Greek_EPSILONaccent = 0x7a2;\n  public static final int XK_Greek_ETAaccent = 0x7a3;\n  public static final int XK_Greek_IOTAaccent = 0x7a4;\n  public static final int XK_Greek_IOTAdiaeresis = 0x7a5;\n  public static final int XK_Greek_OMICRONaccent = 0x7a7;\n  public static final int XK_Greek_UPSILONaccent = 0x7a8;\n  public static final int XK_Greek_UPSILONdieresis = 0x7a9;\n  public static final int XK_Greek_OMEGAaccent = 0x7ab;\n  public static final int XK_Greek_accentdieresis = 0x7ae;\n  public static final int XK_Greek_horizbar = 0x7af;\n  public static final int XK_Greek_alphaaccent = 0x7b1;\n  public static final int XK_Greek_epsilonaccent = 0x7b2;\n  public static final int XK_Greek_etaaccent = 0x7b3;\n  public static final int XK_Greek_iotaaccent = 0x7b4;\n  public static final int XK_Greek_iotadieresis = 0x7b5;\n  public static final int XK_Greek_iotaaccentdieresis = 0x7b6;\n  public static final int XK_Greek_omicronaccent = 0x7b7;\n  public static final int XK_Greek_upsilonaccent = 0x7b8;\n  public static final int XK_Greek_upsilondieresis = 0x7b9;\n  public static final int XK_Greek_upsilonaccentdieresis = 0x7ba;\n  public static final int XK_Greek_omegaaccent = 0x7bb;\n  public static final int XK_Greek_ALPHA = 0x7c1;\n  public static final int XK_Greek_BETA = 0x7c2;\n  public static final int XK_Greek_GAMMA = 0x7c3;\n  public static final int XK_Greek_DELTA = 0x7c4;\n  public static final int XK_Greek_EPSILON = 0x7c5;\n  public static final int XK_Greek_ZETA = 0x7c6;\n  public static final int XK_Greek_ETA = 0x7c7;\n  public static final int XK_Greek_THETA = 0x7c8;\n  public static final int XK_Greek_IOTA = 0x7c9;\n  public static final int XK_Greek_KAPPA = 0x7ca;\n  public static final int XK_Greek_LAMDA = 0x7cb;\n  public static final int XK_Greek_LAMBDA = 0x7cb;\n  public static final int XK_Greek_MU = 0x7cc;\n  public static final int XK_Greek_NU = 0x7cd;\n  public static final int XK_Greek_XI = 0x7ce;\n  public static final int XK_Greek_OMICRON = 0x7cf;\n  public static final int XK_Greek_PI = 0x7d0;\n  public static final int XK_Greek_RHO = 0x7d1;\n  public static final int XK_Greek_SIGMA = 0x7d2;\n  public static final int XK_Greek_TAU = 0x7d4;\n  public static final int XK_Greek_UPSILON = 0x7d5;\n  public static final int XK_Greek_PHI = 0x7d6;\n  public static final int XK_Greek_CHI = 0x7d7;\n  public static final int XK_Greek_PSI = 0x7d8;\n  public static final int XK_Greek_OMEGA = 0x7d9;\n  public static final int XK_Greek_alpha = 0x7e1;\n  public static final int XK_Greek_beta = 0x7e2;\n  public static final int XK_Greek_gamma = 0x7e3;\n  public static final int XK_Greek_delta = 0x7e4;\n  public static final int XK_Greek_epsilon = 0x7e5;\n  public static final int XK_Greek_zeta = 0x7e6;\n  public static final int XK_Greek_eta = 0x7e7;\n  public static final int XK_Greek_theta = 0x7e8;\n  public static final int XK_Greek_iota = 0x7e9;\n  public static final int XK_Greek_kappa = 0x7ea;\n  public static final int XK_Greek_lamda = 0x7eb;\n  public static final int XK_Greek_lambda = 0x7eb;\n  public static final int XK_Greek_mu = 0x7ec;\n  public static final int XK_Greek_nu = 0x7ed;\n  public static final int XK_Greek_xi = 0x7ee;\n  public static final int XK_Greek_omicron = 0x7ef;\n  public static final int XK_Greek_pi = 0x7f0;\n  public static final int XK_Greek_rho = 0x7f1;\n  public static final int XK_Greek_sigma = 0x7f2;\n  public static final int XK_Greek_finalsmallsigma = 0x7f3;\n  public static final int XK_Greek_tau = 0x7f4;\n  public static final int XK_Greek_upsilon = 0x7f5;\n  public static final int XK_Greek_phi = 0x7f6;\n  public static final int XK_Greek_chi = 0x7f7;\n  public static final int XK_Greek_psi = 0x7f8;\n  public static final int XK_Greek_omega = 0x7f9;\n  public static final int XK_Greek_switch = 0xFF7E;  /* Alias for mode_switch */\n\n  /*\n   * Technical;\n   * Byte 3 = 8;\n   */\n\n  public static final int XK_leftradical = 0x8a1;\n  public static final int XK_topleftradical = 0x8a2;\n  public static final int XK_horizconnector = 0x8a3;\n  public static final int XK_topintegral = 0x8a4;\n  public static final int XK_botintegral = 0x8a5;\n  public static final int XK_vertconnector = 0x8a6;\n  public static final int XK_topleftsqbracket = 0x8a7;\n  public static final int XK_botleftsqbracket = 0x8a8;\n  public static final int XK_toprightsqbracket = 0x8a9;\n  public static final int XK_botrightsqbracket = 0x8aa;\n  public static final int XK_topleftparens = 0x8ab;\n  public static final int XK_botleftparens = 0x8ac;\n  public static final int XK_toprightparens = 0x8ad;\n  public static final int XK_botrightparens = 0x8ae;\n  public static final int XK_leftmiddlecurlybrace = 0x8af;\n  public static final int XK_rightmiddlecurlybrace = 0x8b0;\n  public static final int XK_topleftsummation = 0x8b1;\n  public static final int XK_botleftsummation = 0x8b2;\n  public static final int XK_topvertsummationconnector = 0x8b3;\n  public static final int XK_botvertsummationconnector = 0x8b4;\n  public static final int XK_toprightsummation = 0x8b5;\n  public static final int XK_botrightsummation = 0x8b6;\n  public static final int XK_rightmiddlesummation = 0x8b7;\n  public static final int XK_lessthanequal = 0x8bc;\n  public static final int XK_notequal = 0x8bd;\n  public static final int XK_greaterthanequal = 0x8be;\n  public static final int XK_integral = 0x8bf;\n  public static final int XK_therefore = 0x8c0;\n  public static final int XK_variation = 0x8c1;\n  public static final int XK_infinity = 0x8c2;\n  public static final int XK_nabla = 0x8c5;\n  public static final int XK_approximate = 0x8c8;\n  public static final int XK_similarequal = 0x8c9;\n  public static final int XK_ifonlyif = 0x8cd;\n  public static final int XK_implies = 0x8ce;\n  public static final int XK_identical = 0x8cf;\n  public static final int XK_radical = 0x8d6;\n  public static final int XK_includedin = 0x8da;\n  public static final int XK_includes = 0x8db;\n  public static final int XK_intersection = 0x8dc;\n  public static final int XK_union = 0x8dd;\n  public static final int XK_logicaland = 0x8de;\n  public static final int XK_logicalor = 0x8df;\n  public static final int XK_partialderivative = 0x8ef;\n  public static final int XK_function = 0x8f6;\n  public static final int XK_leftarrow = 0x8fb;\n  public static final int XK_uparrow = 0x8fc;\n  public static final int XK_rightarrow = 0x8fd;\n  public static final int XK_downarrow = 0x8fe;\n\n  /*\n   *  Special;\n   *  Byte 3 = 9;\n   */\n\n  public static final int XK_blank = 0x9df;\n  public static final int XK_soliddiamond = 0x9e0;\n  public static final int XK_checkerboard = 0x9e1;\n  public static final int XK_ht = 0x9e2;\n  public static final int XK_ff = 0x9e3;\n  public static final int XK_cr = 0x9e4;\n  public static final int XK_lf = 0x9e5;\n  public static final int XK_nl = 0x9e8;\n  public static final int XK_vt = 0x9e9;\n  public static final int XK_lowrightcorner = 0x9ea;\n  public static final int XK_uprightcorner = 0x9eb;\n  public static final int XK_upleftcorner = 0x9ec;\n  public static final int XK_lowleftcorner = 0x9ed;\n  public static final int XK_crossinglines = 0x9ee;\n  public static final int XK_horizlinescan1 = 0x9ef;\n  public static final int XK_horizlinescan3 = 0x9f0;\n  public static final int XK_horizlinescan5 = 0x9f1;\n  public static final int XK_horizlinescan7 = 0x9f2;\n  public static final int XK_horizlinescan9 = 0x9f3;\n  public static final int XK_leftt = 0x9f4;\n  public static final int XK_rightt = 0x9f5;\n  public static final int XK_bott = 0x9f6;\n  public static final int XK_topt = 0x9f7;\n  public static final int XK_vertbar = 0x9f8;\n\n  /*\n   *  Publishing;\n   *  Byte 3 = a;\n   */\n\n  public static final int XK_emspace = 0xaa1;\n  public static final int XK_enspace = 0xaa2;\n  public static final int XK_em3space = 0xaa3;\n  public static final int XK_em4space = 0xaa4;\n  public static final int XK_digitspace = 0xaa5;\n  public static final int XK_punctspace = 0xaa6;\n  public static final int XK_thinspace = 0xaa7;\n  public static final int XK_hairspace = 0xaa8;\n  public static final int XK_emdash = 0xaa9;\n  public static final int XK_endash = 0xaaa;\n  public static final int XK_signifblank = 0xaac;\n  public static final int XK_ellipsis = 0xaae;\n  public static final int XK_doubbaselinedot = 0xaaf;\n  public static final int XK_onethird = 0xab0;\n  public static final int XK_twothirds = 0xab1;\n  public static final int XK_onefifth = 0xab2;\n  public static final int XK_twofifths = 0xab3;\n  public static final int XK_threefifths = 0xab4;\n  public static final int XK_fourfifths = 0xab5;\n  public static final int XK_onesixth = 0xab6;\n  public static final int XK_fivesixths = 0xab7;\n  public static final int XK_careof = 0xab8;\n  public static final int XK_figdash = 0xabb;\n  public static final int XK_leftanglebracket = 0xabc;\n  public static final int XK_decimalpoint = 0xabd;\n  public static final int XK_rightanglebracket = 0xabe;\n  public static final int XK_marker = 0xabf;\n  public static final int XK_oneeighth = 0xac3;\n  public static final int XK_threeeighths = 0xac4;\n  public static final int XK_fiveeighths = 0xac5;\n  public static final int XK_seveneighths = 0xac6;\n  public static final int XK_trademark = 0xac9;\n  public static final int XK_signaturemark = 0xaca;\n  public static final int XK_trademarkincircle = 0xacb;\n  public static final int XK_leftopentriangle = 0xacc;\n  public static final int XK_rightopentriangle = 0xacd;\n  public static final int XK_emopencircle = 0xace;\n  public static final int XK_emopenrectangle = 0xacf;\n  public static final int XK_leftsinglequotemark = 0xad0;\n  public static final int XK_rightsinglequotemark = 0xad1;\n  public static final int XK_leftdoublequotemark = 0xad2;\n  public static final int XK_rightdoublequotemark = 0xad3;\n  public static final int XK_prescription = 0xad4;\n  public static final int XK_minutes = 0xad6;\n  public static final int XK_seconds = 0xad7;\n  public static final int XK_latincross = 0xad9;\n  public static final int XK_hexagram = 0xada;\n  public static final int XK_filledrectbullet = 0xadb;\n  public static final int XK_filledlefttribullet = 0xadc;\n  public static final int XK_filledrighttribullet = 0xadd;\n  public static final int XK_emfilledcircle = 0xade;\n  public static final int XK_emfilledrect = 0xadf;\n  public static final int XK_enopencircbullet = 0xae0;\n  public static final int XK_enopensquarebullet = 0xae1;\n  public static final int XK_openrectbullet = 0xae2;\n  public static final int XK_opentribulletup = 0xae3;\n  public static final int XK_opentribulletdown = 0xae4;\n  public static final int XK_openstar = 0xae5;\n  public static final int XK_enfilledcircbullet = 0xae6;\n  public static final int XK_enfilledsqbullet = 0xae7;\n  public static final int XK_filledtribulletup = 0xae8;\n  public static final int XK_filledtribulletdown = 0xae9;\n  public static final int XK_leftpointer = 0xaea;\n  public static final int XK_rightpointer = 0xaeb;\n  public static final int XK_club = 0xaec;\n  public static final int XK_diamond = 0xaed;\n  public static final int XK_heart = 0xaee;\n  public static final int XK_maltesecross = 0xaf0;\n  public static final int XK_dagger = 0xaf1;\n  public static final int XK_doubledagger = 0xaf2;\n  public static final int XK_checkmark = 0xaf3;\n  public static final int XK_ballotcross = 0xaf4;\n  public static final int XK_musicalsharp = 0xaf5;\n  public static final int XK_musicalflat = 0xaf6;\n  public static final int XK_malesymbol = 0xaf7;\n  public static final int XK_femalesymbol = 0xaf8;\n  public static final int XK_telephone = 0xaf9;\n  public static final int XK_telephonerecorder = 0xafa;\n  public static final int XK_phonographcopyright = 0xafb;\n  public static final int XK_caret = 0xafc;\n  public static final int XK_singlelowquotemark = 0xafd;\n  public static final int XK_doublelowquotemark = 0xafe;\n  public static final int XK_cursor = 0xaff;\n\n  /*\n   *  APL;\n   *  Byte 3 = b;\n   */\n\n  public static final int XK_leftcaret = 0xba3;\n  public static final int XK_rightcaret = 0xba6;\n  public static final int XK_downcaret = 0xba8;\n  public static final int XK_upcaret = 0xba9;\n  public static final int XK_overbar = 0xbc0;\n  public static final int XK_downtack = 0xbc2;\n  public static final int XK_upshoe = 0xbc3;\n  public static final int XK_downstile = 0xbc4;\n  public static final int XK_underbar = 0xbc6;\n  public static final int XK_jot = 0xbca;\n  public static final int XK_quad = 0xbcc;\n  public static final int XK_uptack = 0xbce;\n  public static final int XK_circle = 0xbcf;\n  public static final int XK_upstile = 0xbd3;\n  public static final int XK_downshoe = 0xbd6;\n  public static final int XK_rightshoe = 0xbd8;\n  public static final int XK_leftshoe = 0xbda;\n  public static final int XK_lefttack = 0xbdc;\n  public static final int XK_righttack = 0xbfc;\n\n  /*\n   * Hebrew;\n   * Byte 3 = c;\n   */\n\n  public static final int XK_hebrew_doublelowline = 0xcdf;\n  public static final int XK_hebrew_aleph = 0xce0;\n  public static final int XK_hebrew_bet = 0xce1;\n  public static final int XK_hebrew_beth = 0xce1;  /* deprecated */\n  public static final int XK_hebrew_gimel = 0xce2;\n  public static final int XK_hebrew_gimmel = 0xce2;  /* deprecated */\n  public static final int XK_hebrew_dalet = 0xce3;\n  public static final int XK_hebrew_daleth = 0xce3;  /* deprecated */\n  public static final int XK_hebrew_he = 0xce4;\n  public static final int XK_hebrew_waw = 0xce5;\n  public static final int XK_hebrew_zain = 0xce6;\n  public static final int XK_hebrew_zayin = 0xce6;  /* deprecated */\n  public static final int XK_hebrew_chet = 0xce7;\n  public static final int XK_hebrew_het = 0xce7;  /* deprecated */\n  public static final int XK_hebrew_tet = 0xce8;\n  public static final int XK_hebrew_teth = 0xce8;  /* deprecated */\n  public static final int XK_hebrew_yod = 0xce9;\n  public static final int XK_hebrew_finalkaph = 0xcea;\n  public static final int XK_hebrew_kaph = 0xceb;\n  public static final int XK_hebrew_lamed = 0xcec;\n  public static final int XK_hebrew_finalmem = 0xced;\n  public static final int XK_hebrew_mem = 0xcee;\n  public static final int XK_hebrew_finalnun = 0xcef;\n  public static final int XK_hebrew_nun = 0xcf0;\n  public static final int XK_hebrew_samech = 0xcf1;\n  public static final int XK_hebrew_samekh = 0xcf1;  /* deprecated */\n  public static final int XK_hebrew_ayin = 0xcf2;\n  public static final int XK_hebrew_finalpe = 0xcf3;\n  public static final int XK_hebrew_pe = 0xcf4;\n  public static final int XK_hebrew_finalzade = 0xcf5;\n  public static final int XK_hebrew_finalzadi = 0xcf5;  /* deprecated */\n  public static final int XK_hebrew_zade = 0xcf6;\n  public static final int XK_hebrew_zadi = 0xcf6;  /* deprecated */\n  public static final int XK_hebrew_qoph = 0xcf7;\n  public static final int XK_hebrew_kuf = 0xcf7;  /* deprecated */\n  public static final int XK_hebrew_resh = 0xcf8;\n  public static final int XK_hebrew_shin = 0xcf9;\n  public static final int XK_hebrew_taw = 0xcfa;\n  public static final int XK_hebrew_taf = 0xcfa;  /* deprecated */\n  public static final int XK_Hebrew_switch = 0xFF7E;  /* Alias for mode_switch */\n\n  /*\n   * Thai;\n   * Byte 3 = d;\n   */\n\n  public static final int XK_Thai_kokai = 0xda1;\n  public static final int XK_Thai_khokhai = 0xda2;\n  public static final int XK_Thai_khokhuat = 0xda3;\n  public static final int XK_Thai_khokhwai = 0xda4;\n  public static final int XK_Thai_khokhon = 0xda5;\n  public static final int XK_Thai_khorakhang = 0xda6;\n  public static final int XK_Thai_ngongu = 0xda7;\n  public static final int XK_Thai_chochan = 0xda8;\n  public static final int XK_Thai_choching = 0xda9;\n  public static final int XK_Thai_chochang = 0xdaa;\n  public static final int XK_Thai_soso = 0xdab;\n  public static final int XK_Thai_chochoe = 0xdac;\n  public static final int XK_Thai_yoying = 0xdad;\n  public static final int XK_Thai_dochada = 0xdae;\n  public static final int XK_Thai_topatak = 0xdaf;\n  public static final int XK_Thai_thothan = 0xdb0;\n  public static final int XK_Thai_thonangmontho = 0xdb1;\n  public static final int XK_Thai_thophuthao = 0xdb2;\n  public static final int XK_Thai_nonen = 0xdb3;\n  public static final int XK_Thai_dodek = 0xdb4;\n  public static final int XK_Thai_totao = 0xdb5;\n  public static final int XK_Thai_thothung = 0xdb6;\n  public static final int XK_Thai_thothahan = 0xdb7;\n  public static final int XK_Thai_thothong = 0xdb8;\n  public static final int XK_Thai_nonu = 0xdb9;\n  public static final int XK_Thai_bobaimai = 0xdba;\n  public static final int XK_Thai_popla = 0xdbb;\n  public static final int XK_Thai_phophung = 0xdbc;\n  public static final int XK_Thai_fofa = 0xdbd;\n  public static final int XK_Thai_phophan = 0xdbe;\n  public static final int XK_Thai_fofan = 0xdbf;\n  public static final int XK_Thai_phosamphao = 0xdc0;\n  public static final int XK_Thai_moma = 0xdc1;\n  public static final int XK_Thai_yoyak = 0xdc2;\n  public static final int XK_Thai_rorua = 0xdc3;\n  public static final int XK_Thai_ru = 0xdc4;\n  public static final int XK_Thai_loling = 0xdc5;\n  public static final int XK_Thai_lu = 0xdc6;\n  public static final int XK_Thai_wowaen = 0xdc7;\n  public static final int XK_Thai_sosala = 0xdc8;\n  public static final int XK_Thai_sorusi = 0xdc9;\n  public static final int XK_Thai_sosua = 0xdca;\n  public static final int XK_Thai_hohip = 0xdcb;\n  public static final int XK_Thai_lochula = 0xdcc;\n  public static final int XK_Thai_oang = 0xdcd;\n  public static final int XK_Thai_honokhuk = 0xdce;\n  public static final int XK_Thai_paiyannoi = 0xdcf;\n  public static final int XK_Thai_saraa = 0xdd0;\n  public static final int XK_Thai_maihanakat = 0xdd1;\n  public static final int XK_Thai_saraaa = 0xdd2;\n  public static final int XK_Thai_saraam = 0xdd3;\n  public static final int XK_Thai_sarai = 0xdd4;\n  public static final int XK_Thai_saraii = 0xdd5;\n  public static final int XK_Thai_saraue = 0xdd6;\n  public static final int XK_Thai_sarauee = 0xdd7;\n  public static final int XK_Thai_sarau = 0xdd8;\n  public static final int XK_Thai_sarauu = 0xdd9;\n  public static final int XK_Thai_phinthu = 0xdda;\n  public static final int XK_Thai_maihanakat_maitho = 0xdde;\n  public static final int XK_Thai_baht = 0xddf;\n  public static final int XK_Thai_sarae = 0xde0;\n  public static final int XK_Thai_saraae = 0xde1;\n  public static final int XK_Thai_sarao = 0xde2;\n  public static final int XK_Thai_saraaimaimuan = 0xde3;\n  public static final int XK_Thai_saraaimaimalai = 0xde4;\n  public static final int XK_Thai_lakkhangyao = 0xde5;\n  public static final int XK_Thai_maiyamok = 0xde6;\n  public static final int XK_Thai_maitaikhu = 0xde7;\n  public static final int XK_Thai_maiek = 0xde8;\n  public static final int XK_Thai_maitho = 0xde9;\n  public static final int XK_Thai_maitri = 0xdea;\n  public static final int XK_Thai_maichattawa = 0xdeb;\n  public static final int XK_Thai_thanthakhat = 0xdec;\n  public static final int XK_Thai_nikhahit = 0xded;\n  public static final int XK_Thai_leksun = 0xdf0;\n  public static final int XK_Thai_leknung = 0xdf1;\n  public static final int XK_Thai_leksong = 0xdf2;\n  public static final int XK_Thai_leksam = 0xdf3;\n  public static final int XK_Thai_leksi = 0xdf4;\n  public static final int XK_Thai_lekha = 0xdf5;\n  public static final int XK_Thai_lekhok = 0xdf6;\n  public static final int XK_Thai_lekchet = 0xdf7;\n  public static final int XK_Thai_lekpaet = 0xdf8;\n  public static final int XK_Thai_lekkao = 0xdf9;\n\n  /*\n   *   Korean;\n   *   Byte 3 = e;\n   */\n\n  public static final int XK_Hangul = 0xff31;    /* Hangul start/stop(toggle) */\n  public static final int XK_Hangul_Start = 0xff32;    /* Hangul start */\n  public static final int XK_Hangul_End = 0xff33;    /* Hangul end, English start */\n  public static final int XK_Hangul_Hanja = 0xff34;    /* Start Hangul->Hanja Conversion */\n  public static final int XK_Hangul_Jamo = 0xff35;    /* Hangul Jamo mode */\n  public static final int XK_Hangul_Romaja = 0xff36;    /* Hangul Romaja mode */\n  public static final int XK_Hangul_Codeinput = 0xff37;    /* Hangul code input mode */\n  public static final int XK_Hangul_Jeonja = 0xff38;    /* Jeonja mode */\n  public static final int XK_Hangul_Banja = 0xff39;    /* Banja mode */\n  public static final int XK_Hangul_PreHanja = 0xff3a;    /* Pre Hanja conversion */\n  public static final int XK_Hangul_PostHanja = 0xff3b;    /* Post Hanja conversion */\n  public static final int XK_Hangul_SingleCandidate = 0xff3c;    /* Single candidate */\n  public static final int XK_Hangul_MultipleCandidate = 0xff3d;    /* Multiple candidate */\n  public static final int XK_Hangul_PreviousCandidate = 0xff3e;    /* Previous candidate */\n  public static final int XK_Hangul_Special = 0xff3f;    /* Special symbols */\n  public static final int XK_Hangul_switch = 0xFF7E;    /* Alias for mode_switch */\n\n  /* Hangul Consonant Characters */\n  public static final int XK_Hangul_Kiyeog = 0xea1;\n  public static final int XK_Hangul_SsangKiyeog = 0xea2;\n  public static final int XK_Hangul_KiyeogSios = 0xea3;\n  public static final int XK_Hangul_Nieun = 0xea4;\n  public static final int XK_Hangul_NieunJieuj = 0xea5;\n  public static final int XK_Hangul_NieunHieuh = 0xea6;\n  public static final int XK_Hangul_Dikeud = 0xea7;\n  public static final int XK_Hangul_SsangDikeud = 0xea8;\n  public static final int XK_Hangul_Rieul = 0xea9;\n  public static final int XK_Hangul_RieulKiyeog = 0xeaa;\n  public static final int XK_Hangul_RieulMieum = 0xeab;\n  public static final int XK_Hangul_RieulPieub = 0xeac;\n  public static final int XK_Hangul_RieulSios = 0xead;\n  public static final int XK_Hangul_RieulTieut = 0xeae;\n  public static final int XK_Hangul_RieulPhieuf = 0xeaf;\n  public static final int XK_Hangul_RieulHieuh = 0xeb0;\n  public static final int XK_Hangul_Mieum = 0xeb1;\n  public static final int XK_Hangul_Pieub = 0xeb2;\n  public static final int XK_Hangul_SsangPieub = 0xeb3;\n  public static final int XK_Hangul_PieubSios = 0xeb4;\n  public static final int XK_Hangul_Sios = 0xeb5;\n  public static final int XK_Hangul_SsangSios = 0xeb6;\n  public static final int XK_Hangul_Ieung = 0xeb7;\n  public static final int XK_Hangul_Jieuj = 0xeb8;\n  public static final int XK_Hangul_SsangJieuj = 0xeb9;\n  public static final int XK_Hangul_Cieuc = 0xeba;\n  public static final int XK_Hangul_Khieuq = 0xebb;\n  public static final int XK_Hangul_Tieut = 0xebc;\n  public static final int XK_Hangul_Phieuf = 0xebd;\n  public static final int XK_Hangul_Hieuh = 0xebe;\n\n  /* Hangul Vowel Characters */\n  public static final int XK_Hangul_A = 0xebf;\n  public static final int XK_Hangul_AE = 0xec0;\n  public static final int XK_Hangul_YA = 0xec1;\n  public static final int XK_Hangul_YAE = 0xec2;\n  public static final int XK_Hangul_EO = 0xec3;\n  public static final int XK_Hangul_E = 0xec4;\n  public static final int XK_Hangul_YEO = 0xec5;\n  public static final int XK_Hangul_YE = 0xec6;\n  public static final int XK_Hangul_O = 0xec7;\n  public static final int XK_Hangul_WA = 0xec8;\n  public static final int XK_Hangul_WAE = 0xec9;\n  public static final int XK_Hangul_OE = 0xeca;\n  public static final int XK_Hangul_YO = 0xecb;\n  public static final int XK_Hangul_U = 0xecc;\n  public static final int XK_Hangul_WEO = 0xecd;\n  public static final int XK_Hangul_WE = 0xece;\n  public static final int XK_Hangul_WI = 0xecf;\n  public static final int XK_Hangul_YU = 0xed0;\n  public static final int XK_Hangul_EU = 0xed1;\n  public static final int XK_Hangul_YI = 0xed2;\n  public static final int XK_Hangul_I = 0xed3;\n\n  /* Hangul syllable-final (JongSeong) Characters */\n  public static final int XK_Hangul_J_Kiyeog = 0xed4;\n  public static final int XK_Hangul_J_SsangKiyeog = 0xed5;\n  public static final int XK_Hangul_J_KiyeogSios = 0xed6;\n  public static final int XK_Hangul_J_Nieun = 0xed7;\n  public static final int XK_Hangul_J_NieunJieuj = 0xed8;\n  public static final int XK_Hangul_J_NieunHieuh = 0xed9;\n  public static final int XK_Hangul_J_Dikeud = 0xeda;\n  public static final int XK_Hangul_J_Rieul = 0xedb;\n  public static final int XK_Hangul_J_RieulKiyeog = 0xedc;\n  public static final int XK_Hangul_J_RieulMieum = 0xedd;\n  public static final int XK_Hangul_J_RieulPieub = 0xede;\n  public static final int XK_Hangul_J_RieulSios = 0xedf;\n  public static final int XK_Hangul_J_RieulTieut = 0xee0;\n  public static final int XK_Hangul_J_RieulPhieuf = 0xee1;\n  public static final int XK_Hangul_J_RieulHieuh = 0xee2;\n  public static final int XK_Hangul_J_Mieum = 0xee3;\n  public static final int XK_Hangul_J_Pieub = 0xee4;\n  public static final int XK_Hangul_J_PieubSios = 0xee5;\n  public static final int XK_Hangul_J_Sios = 0xee6;\n  public static final int XK_Hangul_J_SsangSios = 0xee7;\n  public static final int XK_Hangul_J_Ieung = 0xee8;\n  public static final int XK_Hangul_J_Jieuj = 0xee9;\n  public static final int XK_Hangul_J_Cieuc = 0xeea;\n  public static final int XK_Hangul_J_Khieuq = 0xeeb;\n  public static final int XK_Hangul_J_Tieut = 0xeec;\n  public static final int XK_Hangul_J_Phieuf = 0xeed;\n  public static final int XK_Hangul_J_Hieuh = 0xeee;\n\n  /* Ancient Hangul Consonant Characters */\n  public static final int XK_Hangul_RieulYeorinHieuh = 0xeef;\n  public static final int XK_Hangul_SunkyeongeumMieum = 0xef0;\n  public static final int XK_Hangul_SunkyeongeumPieub = 0xef1;\n  public static final int XK_Hangul_PanSios = 0xef2;\n  public static final int XK_Hangul_KkogjiDalrinIeung = 0xef3;\n  public static final int XK_Hangul_SunkyeongeumPhieuf = 0xef4;\n  public static final int XK_Hangul_YeorinHieuh = 0xef5;\n\n  /* Ancient Hangul Vowel Characters */\n  public static final int XK_Hangul_AraeA = 0xef6;\n  public static final int XK_Hangul_AraeAE = 0xef7;\n\n  /* Ancient Hangul syllable-final (JongSeong) Characters */\n  public static final int XK_Hangul_J_PanSios = 0xef8;\n  public static final int XK_Hangul_J_KkogjiDalrinIeung = 0xef9;\n  public static final int XK_Hangul_J_YeorinHieuh = 0xefa;\n\n  /* Korean currency symbol */\n  public static final int XK_Korean_Won = 0xeff;\n\n  public static final int XK_EcuSign = 0x20a0;\n  public static final int XK_ColonSign = 0x20a1;\n  public static final int XK_CruzeiroSign = 0x20a2;\n  public static final int XK_FFrancSign = 0x20a3;\n  public static final int XK_LiraSign = 0x20a4;\n  public static final int XK_MillSign = 0x20a5;\n  public static final int XK_NairaSign = 0x20a6;\n  public static final int XK_PesetaSign = 0x20a7;\n  public static final int XK_RupeeSign = 0x20a8;\n  public static final int XK_WonSign = 0x20a9;\n  public static final int XK_NewSheqelSign = 0x20aa;\n  public static final int XK_DongSign = 0x20ab;\n  public static final int XK_EuroSign = 0x20ac;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/LogWriter.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class LogWriter {\n\n  public LogWriter(String name_) {\n    name = name_;\n    level = globalLogLevel;\n    next = log_writers;\n    log_writers = this;\n  }\n\n  public void setLevel(int level_) { level = level_; }\n\n  public void write(int level, String str) {\n    if (level <= this.level) {\n      System.err.println(name+\": \"+str);\n    }\n  }\n\n  public void error(String fmt, Object... args) {\n    write(0, String.format(fmt, args));\n  }\n  public void status(String fmt, Object... args) {\n    write(10, String.format(fmt, args));\n  }\n  public void info(String fmt, Object... args) {\n    write(30, String.format(fmt, args));\n  }\n  public void debug(String fmt, Object... args) {\n    write(100, String.format(fmt, args));\n  }\n\n  public static boolean setLogParams(String params) {\n    globalLogLevel = Integer.parseInt(params);\n    LogWriter current = log_writers;\n    while (current != null) {\n      current.setLevel(globalLogLevel);\n      current = current.next;\n    }\n    return true;\n//      int colon = params.indexOf(':');\n//      String logwriter_name = params.substring(0, colon);\n//      params = params.substring(colon+1);\n//      colon = params.indexOf(':');\n//      String logger_name = params.substring(0, colon);\n//      params = params.substring(colon+1);\n//      int level = Integer.parseInt(params);\n//      // XXX ignore logger name for the moment\n\n//      System.err.println(\"setting level to \"+level);\n//      System.err.println(\"logwriters is \"+log_writers);\n//      if (logwriter_name.equals(\"*\")) {\n//        LogWriter current = log_writers;\n//        while (current != null) {\n//          //current.setLog(logger);\n//          System.err.println(\"setting level of \"+current.name+\" to \"+level);\n//          current.setLevel(level);\n//          current = current.next;\n//        }\n//        return true;\n//      }\n\n//      LogWriter logwriter = getLogWriter(logwriter_name);\n//      if (logwriter == null) {\n//        System.err.println(\"no logwriter found: \"+logwriter_name);\n//        return false;\n//      }\n\n//      //logwriter.setLog(logger);\n//      logwriter.setLevel(level);\n//      return true;\n  }\n\n\n  static LogWriter getLogWriter(String name) {\n    LogWriter current = log_writers;\n    while (current != null) {\n      if (name.equalsIgnoreCase(current.name)) return current;\n      current = current.next;\n    }\n    return null;\n  }\n\n  String name;\n  int level;\n  LogWriter next;\n  static LogWriter log_writers;\n  static int globalLogLevel = 30;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/ManagedPixelBuffer.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2016-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.awt.image.*;\n\npublic class ManagedPixelBuffer extends FullFramePixelBuffer {\n\n  public ManagedPixelBuffer() {\n    datasize = 0;\n    checkDataSize();\n  }\n\n  public ManagedPixelBuffer(PixelFormat pf, int w, int h)\n  {\n    super(pf, w, h, null);\n    datasize = 0;\n    checkDataSize();\n  }\n\n  public void setPF(PixelFormat pf) {\n    format = pf; checkDataSize();\n  }\n\n  public void setSize(int w, int h) {\n    width_ = w; height_ = h; checkDataSize();\n  }\n\n  final void checkDataSize() {\n    int new_datasize = width_ * height_;\n    if (datasize < new_datasize) {\n      if (data != null) {\n        datasize = 0; data = null;\n      }\n      if (new_datasize > 0) {\n        ColorModel cm = format.getColorModel();\n        data = cm.createCompatibleWritableRaster(width_, height_);\n        image = new BufferedImage(cm, data, cm.isAlphaPremultiplied(), null);\n        datasize = new_datasize;\n      }\n    }\n  }\n\n  protected int datasize;\n  static LogWriter vlog = new LogWriter(\"ManagedPixelBuffer\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/ModifiablePixelBuffer.java",
    "content": "/* Copyright 2016-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n// -=- Modifiable generic pixel buffer class\n\npackage com.tigervnc.rfb;\n\nimport java.awt.image.*;\nimport java.awt.Color;\nimport java.awt.color.ColorSpace;\nimport java.lang.*;\nimport java.nio.*;\nimport java.util.*;\n\nimport static java.awt.image.DataBuffer.*;\n\npublic abstract class ModifiablePixelBuffer extends PixelBuffer\n{\n\n  public ModifiablePixelBuffer(PixelFormat pf, int w, int h)\n  {\n    super(pf, w, h);\n  }\n\n  protected ModifiablePixelBuffer()\n  {\n  }\n\n  ///////////////////////////////////////////////\n  // Access to pixel data\n  //\n\n  // Get a writeable pointer into the buffer\n  //   Like getBuffer(), the pointer is to the top-left pixel of the\n  //   specified Rect.\n  public abstract WritableRaster getBufferRW(Rect r);\n  // Commit the modified contents\n  //   Ensures that the changes to the specified Rect is properly\n  //   stored away and any temporary buffers are freed. The Rect given\n  //   here needs to match the Rect given to the earlier call to\n  //   getBufferRW().\n  public abstract void commitBufferRW(Rect r);\n\n  static LogWriter vlog = new LogWriter(\"ModifiablePixelBuffer\");\n  ///////////////////////////////////////////////\n  // Basic rendering operations\n  // These operations DO NOT clip to the pixelbuffer area, or trap overruns.\n\n  // Fill a rectangle\n  public void fillRect(Rect r, byte[] pix)\n  {\n    WritableRaster buf;\n    int w, h;\n\n    w = r.width();\n    h = r.height();\n\n    if (h == 0 || w ==0)\n      return;\n\n    buf = getBufferRW(r);\n\n    ByteBuffer src =\n      ByteBuffer.allocate(r.area()*format.bpp/8).order(format.getByteOrder());\n    for (int i=0; i < r.area(); i++)\n      src.put(pix);\n    Raster raster = format.rasterFromBuffer(r, (ByteBuffer)src.rewind());\n    synchronized(image) {\n      buf.setDataElements(0, 0, raster);\n    }\n\n    commitBufferRW(r);\n  }\n\n  // Copy pixel data to the buffer\n  public void imageRect(Rect r, byte[] pixels)\n  {\n    WritableRaster dest = getBufferRW(r);\n\n    int length = r.area()*format.bpp/8;\n    ByteBuffer src =\n      ByteBuffer.wrap(pixels, 0, length).order(format.getByteOrder());\n    Raster raster = format.rasterFromBuffer(r, src);\n    synchronized(image) {\n      dest.setDataElements(0, 0, raster);\n    }\n\n    commitBufferRW(r);\n  }\n\n  // Copy pixel data from one PixelBuffer location to another\n  public void copyRect(Rect rect, Point move_by_delta)\n  {\n    Raster srcData;\n    WritableRaster dstData;\n\n    Rect drect, srect;\n\n    drect = new Rect(rect.tl, rect.br);\n    if (!drect.enclosed_by(getRect())) {\n      String msg = \"Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d\";\n      vlog.error(String.format(msg, drect.width(), drect.height(),\n                               drect.tl.x, drect.tl.y, width(), height()));\n      drect = drect.intersect(getRect());\n    }\n\n    if (drect.is_empty())\n      return;\n\n    srect = drect.translate(move_by_delta.negate());\n    if (!srect.enclosed_by(getRect())) {\n      String msg = \"Source rect %dx%d at %d,%d exceeds framebuffer %dx%d\";\n      vlog.error(String.format(msg, srect.width(), srect.height(),\n                               srect.tl.x, srect.tl.y, width(), height()));\n      srect = srect.intersect(getRect());\n      // Need to readjust the destination now that the area has changed\n      drect = srect.translate(move_by_delta);\n    }\n\n    if (srect.is_empty())\n      return;\n\n    srcData = getBuffer(srect);\n    dstData = getBufferRW(drect);\n\n    synchronized(image) {\n      dstData.setDataElements(0, 0, srcData);\n    }\n\n    commitBufferRW(rect);\n  }\n\n  // Copy pixel data to the buffer through a mask\n  //   pixels is a pointer to the pixel to be copied to r.tl.\n  //   maskPos specifies the pixel offset in the mask to start from.\n  //   mask_ is a pointer to the mask bits at (0,0).\n  //   pStride and mStride are the strides of the pixel and mask buffers.\n  public void maskRect(Rect r, Object pixels, byte[] mask_)\n  {\n    Rect cr = getRect().intersect(r);\n    if (cr.is_empty()) return;\n    WritableRaster data = getBufferRW(cr);\n\n    // FIXME\n    ColorModel cm = format.getColorModel();\n    SampleModel sm =\n      cm.createCompatibleSampleModel(r.width(), r.height());\n    DataBuffer db = null;\n    ByteBuffer src =\n      ByteBuffer.wrap((byte[])pixels).order(format.getByteOrder());\n    Buffer dst;\n    switch (sm.getTransferType()) {\n    case TYPE_INT:\n      dst = IntBuffer.allocate(src.remaining()).put(src.asIntBuffer());\n      db = new DataBufferInt(((IntBuffer)dst).array(), r.area());\n      break;\n    case TYPE_BYTE:\n      db = new DataBufferByte(src.array(), r.area());\n      break;\n    case TYPE_SHORT:\n      dst = ShortBuffer.allocate(src.remaining()).put(src.asShortBuffer());\n      db = new DataBufferShort(((ShortBuffer)dst).array(), r.area());\n      break;\n    }\n    assert(db != null);\n    Raster raster =\n      Raster.createRaster(sm, db, new java.awt.Point(0, 0));\n    ColorConvertOp converter = format.getColorConvertOp(cm.getColorSpace());\n    WritableRaster t = data.createCompatibleWritableRaster();\n    converter.filter(raster, t);\n\n    int w = cr.width();\n    int h = cr.height();\n\n    Point offset = new Point(cr.tl.x-r.tl.x, cr.tl.y-r.tl.y);\n\n    int maskBytesPerRow = (w + 7) / 8;\n\n    synchronized(image) {\n      for (int y = 0; y < h; y++) {\n        int cy = offset.y + y;\n        for (int x = 0; x < w; x++) {\n          int cx = offset.x + x;\n          int byte_ = cy * maskBytesPerRow + y / 8;\n          int bit = 7 - cx % 8;\n\n          if ((mask_[byte_] & (1 << bit)) != 0)\n            data.setDataElements(x+cx, y+cy, t.getDataElements(x+cx, y+cy, null));\n        }\n      }\n    }\n\n    commitBufferRW(r);\n  }\n\n  //   pixel is the Pixel value to be used where mask_ is set\n  public void maskRect(Rect r, int pixel, byte[] mask)\n  {\n    // FIXME\n  }\n\n  // Render in a specific format\n  //   Does the exact same thing as the above methods, but the given\n  //   pixel values are defined by the given PixelFormat. \n  public void fillRect(PixelFormat pf, Rect dest, byte[] pix)\n  {\n    WritableRaster dstBuffer = getBufferRW(dest);\n\n    ColorModel cm = pf.getColorModel();\n    if (cm.isCompatibleRaster(dstBuffer) &&\n        cm.isCompatibleSampleModel(dstBuffer.getSampleModel())) {\n      fillRect(dest, pix);\n    } else {\n      ByteBuffer src =\n        ByteBuffer.allocate(dest.area()*pf.bpp/8).order(pf.getByteOrder());\n      for (int i=0; i < dest.area(); i++)\n        src.put(pix);\n      Raster raster = pf.rasterFromBuffer(dest, (ByteBuffer)src.rewind());\n      ColorConvertOp converter = format.getColorConvertOp(cm.getColorSpace());\n      synchronized(image) {\n        converter.filter(raster, dstBuffer);\n      }\n    }\n\n    commitBufferRW(dest);\n  }\n\n  public void imageRect(PixelFormat pf, Rect dest, byte[] pixels)\n  {\n    WritableRaster dstBuffer = getBufferRW(dest);\n\n    ColorModel cm = pf.getColorModel();\n    if (cm.isCompatibleRaster(dstBuffer) &&\n        cm.isCompatibleSampleModel(dstBuffer.getSampleModel())) {\n      imageRect(dest, pixels);\n    } else {\n      int length = dest.area()*pf.bpp/8;\n      ByteBuffer src = ByteBuffer.wrap(pixels, 0, length).order(pf.getByteOrder());\n      Raster raster = pf.rasterFromBuffer(dest, src);\n      ColorConvertOp converter = format.getColorConvertOp(cm.getColorSpace());\n      synchronized(image) {\n        converter.filter(raster, dstBuffer);\n      }\n    }\n\n    commitBufferRW(dest);\n  }\n\n  public void imageRect(PixelFormat pf, Rect dest, Raster pixels)\n  {\n    WritableRaster dstBuffer = getBufferRW(dest);\n\n    ColorModel cm = pf.getColorModel();\n    if (cm.isCompatibleRaster(dstBuffer) &&\n        cm.isCompatibleSampleModel(dstBuffer.getSampleModel())) {\n      synchronized(image) {\n        dstBuffer.setDataElements(0, 0, pixels);\n      }\n    } else {\n      ColorConvertOp converter = format.getColorConvertOp(cm.getColorSpace());\n      synchronized(image) {\n        converter.filter(pixels, dstBuffer);\n      }\n    }\n\n    commitBufferRW(dest);\n  }\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/MsgTypes.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class MsgTypes {\n  // server to client\n\n  public static final int msgTypeFramebufferUpdate = 0;\n  public static final int msgTypeSetColourMapEntries = 1;\n  public static final int msgTypeBell = 2;\n  public static final int msgTypeServerCutText = 3;\n\n  public static final int msgTypeEndOfContinuousUpdates = 150;\n\n  public static final int msgTypeServerFence = 248;\n\n  // client to server\n\n  public static final int msgTypeSetPixelFormat = 0;\n  public static final int msgTypeFixColourMapEntries = 1;\n  public static final int msgTypeSetEncodings = 2;\n  public static final int msgTypeFramebufferUpdateRequest = 3;\n  public static final int msgTypeKeyEvent = 4;\n  public static final int msgTypePointerEvent = 5;\n  public static final int msgTypeClientCutText = 6;\n\n  public static final int msgTypeEnableContinuousUpdates = 150;\n\n  public static final int msgTypeClientFence = 248;\n\n  public static final int msgTypeSetDesktopSize = 251;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/PixelBuffer.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2016-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n// -=- Generic pixel buffer class\n\npackage com.tigervnc.rfb;\n\nimport java.awt.*;\nimport java.awt.image.*;\nimport java.awt.Color;\nimport java.nio.*;\nimport java.util.concurrent.atomic.*;\n\npublic abstract class PixelBuffer {\n\n  // We do a lot of byte offset calculations that assume the result fits\n  // inside a signed 32 bit integer. Limit the maximum size of pixel\n  // buffers so that these calculations never overflow.\n\n  static final int maxPixelBufferWidth = 16384;\n  static final int maxPixelBufferHeight = 16384;\n\n  public PixelBuffer(PixelFormat pf, int w, int h) {\n    format = pf;\n    width_ = w;\n    height_= h;\n    setSize(w, h);\n  }\n\n  protected PixelBuffer() { width_ = 0; height_ = 0; }\n\n  // Get pixel format\n  public final PixelFormat getPF() { return format; }\n\n  // Get width, height and number of pixels\n  public final int width() { return width_; }\n  public final int height() { return height_; }\n  public final int area() { return width_ * height_; }\n\n  // Get rectangle encompassing this buffer\n  //   Top-left of rectangle is either at (0,0), or the specified point.\n  public final Rect getRect() { return new Rect(0, 0, width_, height_); }\n  public final Rect getRect(Point pos) {\n    return new Rect(pos, pos.translate(new Point(width_, height_)));\n  }\n\n  ///////////////////////////////////////////////\n  // Access to pixel data\n  //\n\n  // Get a pointer into the buffer\n  //   The pointer is to the top-left pixel of the specified Rect.\n  public abstract Raster getBuffer(Rect r);\n\n  // Get pixel data for a given part of the buffer\n  //   Data is copied into the supplied buffer, with the specified\n  //   stride. Try to avoid using this though as getBuffer() will in\n  //   most cases avoid the extra memory copy.\n  //void getImage(void* imageBuf, const Rect& r, int stride=0) const;\n  // Get pixel data in a given format\n  //   Works just the same as getImage(), but guaranteed to be in a\n  //   specific format.\n  //void getImage(const PixelFormat& pf, void* imageBuf,\n  //                const Rect& r, int stride=0) const;\n  public Image getImage() { return image; }\n\n  public void setSize(int width, int height)\n  {\n    if ((width < 0) || (width > maxPixelBufferWidth))\n      throw new Exception(\"Invalid PixelBuffer width of \"+width+\" pixels requested\");\n    if ((height < 0) || (height > maxPixelBufferHeight))\n      throw new Exception(\"Invalid PixelBuffer height of \"+height+\" pixels requested\");\n\n    width_ = width;\n    height_ = height;\n  }\n\n  ///////////////////////////////////////////////\n  // Framebuffer update methods\n  //\n\n  // Ensure that the specified rectangle of buffer is up to date.\n  //   Overridden by derived classes implementing framebuffer access\n  //   to copy the required display data into place.\n  //public abstract void grabRegion(Region& region) {}\n\n  protected PixelFormat format;\n  protected int width_, height_;\n  protected Image image;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/PixelFormat.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009 Pierre Ossman for Cendio AB\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright (C) 2011 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// PixelFormat\n//\n\npackage com.tigervnc.rfb;\n\nimport java.awt.color.*;\nimport java.awt.image.*;\nimport java.nio.*;\nimport java.util.*;\n\nimport com.tigervnc.rdr.*;\n\npublic class PixelFormat {\n\n  public PixelFormat(int b, int d, boolean e, boolean t,\n                     int rm, int gm, int bm, int rs, int gs, int bs)\n  {\n    bpp = b; depth = d; trueColour = t; bigEndian = e;\n    redMax = rm; greenMax = gm; blueMax = bm;\n    redShift = rs; greenShift = gs; blueShift = bs;\n    converters = new HashMap<Integer, ColorConvertOp>();\n    if (!isSane())\n      throw new Exception(\"invalid pixel format\");\n\n    updateState();\n  }\n\n  public PixelFormat()\n  {\n    this(8, 8, false, true, 7, 7, 3, 0, 3, 6);\n    updateState();\n  }\n\n  public boolean equal(PixelFormat other)\n  {\n    if (bpp != other.bpp || depth != other.depth)\n      return false;\n\n    if (redMax != other.redMax)\n      return false;\n    if (greenMax != other.greenMax)\n      return false;\n    if (blueMax != other.blueMax)\n      return false;\n\n    // Endianness requires more care to determine compatibility\n    if (bigEndian == other.bigEndian || bpp == 8) {\n      if (redShift != other.redShift)\n        return false;\n      if (greenShift != other.greenShift)\n        return false;\n      if (blueShift != other.blueShift)\n        return false;\n    } else {\n      // Has to be the same byte for each channel\n      if (redShift/8 != (3 - other.redShift/8))\n        return false;\n      if (greenShift/8 != (3 - other.greenShift/8))\n        return false;\n      if (blueShift/8 != (3 - other.blueShift/8))\n        return false;\n\n      // And the same bit offset within the byte\n      if (redShift%8 != other.redShift%8)\n        return false;\n      if (greenShift%8 != other.greenShift%8)\n        return false;\n      if (blueShift%8 != other.blueShift%8)\n        return false;\n\n      // And not cross a byte boundary\n      if (redShift/8 != (redShift + redBits - 1)/8)\n        return false;\n      if (greenShift/8 != (greenShift + greenBits - 1)/8)\n        return false;\n      if (blueShift/8 != (blueShift + blueBits - 1)/8)\n        return false;\n    }\n\n    return true;\n  }\n\n  public void read(InStream is) {\n    bpp = is.readU8();\n    depth = is.readU8();\n    bigEndian = is.readU8()!=0;\n    trueColour = is.readU8()!=0;\n    redMax = is.readU16();\n    greenMax = is.readU16();\n    blueMax = is.readU16();\n    redShift = is.readU8();\n    greenShift = is.readU8();\n    blueShift = is.readU8();\n    is.skip(3);\n\n    // We have no real support for colour maps. If the client\n    // wants one, then we force a 8-bit true colour format and\n    // pretend it's a colour map.\n    if (!trueColour) {\n      redMax = 7;\n      greenMax = 7;\n      blueMax = 3;\n      redShift = 0;\n      greenShift = 3;\n      blueShift = 6;\n    }\n\n    if (!isSane())\n      throw new Exception(\"invalid pixel format: \"+print());\n\n    updateState();\n  }\n\n  public void write(OutStream os) {\n    os.writeU8(bpp);\n    os.writeU8(depth);\n    os.writeU8(bigEndian?1:0);\n    os.writeU8(trueColour?1:0);\n    os.writeU16(redMax);\n    os.writeU16(greenMax);\n    os.writeU16(blueMax);\n    os.writeU8(redShift);\n    os.writeU8(greenShift);\n    os.writeU8(blueShift);\n    os.pad(3);\n  }\n\n  public final boolean isBigEndian() {\n    return bigEndian;\n  }\n\n  public final boolean isLittleEndian() {\n    return ! bigEndian;\n  }\n\n  public final boolean is888() {\n    if(!trueColour)\n      return false;\n    if(bpp != 32)\n      return false;\n    if(depth != 24)\n      return false;\n    if(redMax != 255)\n      return false;\n    if(greenMax != 255)\n      return false;\n    if(blueMax != 255)\n      return false;\n    if ((redShift & 0x7) != 0)\n      return false;\n    if ((greenShift & 0x7) != 0)\n      return false;\n    if ((blueShift & 0x7) != 0)\n      return false;\n\n    return true;\n  }\n\n  public int pixelFromRGB(int red, int green, int blue, ColorModel cm)\n  {\n    if (trueColour) {\n      int r = (red   * redMax     + 32767) / 65535;\n      int g = (green * greenMax   + 32767) / 65535;\n      int b = (blue  * blueMax    + 32767) / 65535;\n\n      return (r << redShift) | (g << greenShift) | (b << blueShift);\n    } else if (cm != null) {\n      // Try to find the closest pixel by Cartesian distance\n      int colours = 1 << depth;\n      int diff = 256 * 256 * 4;\n      int col = 0;\n      for (int i=0; i<colours; i++) {\n        int r, g, b;\n        r = cm.getRed(i);\n        g = cm.getGreen(i);\n        b = cm.getBlue(i);\n        int rd = (r-red) >> 8;\n        int gd = (g-green) >> 8;\n        int bd = (b-blue) >> 8;\n        int d = rd*rd + gd*gd + bd*bd;\n        if (d < diff) {\n          col = i;\n          diff = d;\n        }\n      }\n      return col;\n    }\n    // XXX just return 0 for colour map?\n    return 0;\n  }\n\n  // This method should be invoked with duplicates of dst/src Buffers\n  public void bufferFromRGB(ByteBuffer dst, ByteBuffer src, int pixels)\n  {\n    bufferFromRGB(dst, src, pixels, pixels, 1);\n  }\n\n  // This method should be invoked with duplicates of dst/src Buffers\n  public void bufferFromRGB(ByteBuffer dst, ByteBuffer src,\n                            int w, int stride, int h)\n  {\n    if (is888()) {\n      // Optimised common case\n      int r, g, b, x;\n\n      if (bigEndian) {\n        r = dst.position() + (24 - redShift)/8;\n        g = dst.position() + (24 - greenShift)/8;\n        b = dst.position() + (24 - blueShift)/8;\n        x = dst.position() + (24 - (48 - redShift - greenShift - blueShift))/8;\n      } else {\n        r = dst.position() + redShift/8;\n        g = dst.position() + greenShift/8;\n        b = dst.position() + blueShift/8;\n        x = dst.position() + (48 - redShift - greenShift - blueShift)/8;\n      }\n\n      int dstPad = (stride - w) * 4;\n      while (h-- > 0) {\n        int w_ = w;\n        while (w_-- > 0) {\n          dst.put(r, src.get());\n          dst.put(g, src.get());\n          dst.put(b, src.get());\n          dst.put(x, (byte)0);\n          r += 4;\n          g += 4;\n          b += 4;\n          x += 4;\n        }\n        r += dstPad;\n        g += dstPad;\n        b += dstPad;\n        x += dstPad;\n      }\n    } else {\n      // Generic code\n      int dstPad = (stride - w) * bpp/8;\n      while (h-- > 0) {\n        int w_ = w;\n        while (w_-- > 0) {\n          int p;\n          int r, g, b;\n\n          r = src.get();\n          g = src.get();\n          b = src.get();\n\n          p = pixelFromRGB(r, g, b, model);\n\n          bufferFromPixel(dst, p);\n          dst.position(dst.position() + bpp/8);\n        }\n        dst.position(dst.position() + dstPad);\n      }\n    }\n  }\n\n  // This method should be invoked with duplicates of dst/src Buffers\n  public void rgbFromBuffer(ByteBuffer dst, ByteBuffer src, int pixels)\n  {\n    rgbFromBuffer(dst, src, pixels, pixels, 1);\n  }\n\n  // This method should be invoked with duplicates of dst/src Buffers\n  public void rgbFromBuffer(ByteBuffer dst, ByteBuffer src,\n                            int w, int stride, int h)\n  {\n    if (is888()) {\n      // Optimised common case\n      int r, g, b;\n\n      if (bigEndian) {\n        r = src.position() + (24 - redShift)/8;\n        g = src.position() + (24 - greenShift)/8;\n        b = src.position() + (24 - blueShift)/8;\n      } else {\n        r = src.position() + redShift/8;\n        g = src.position() + greenShift/8;\n        b = src.position() + blueShift/8;\n      }\n\n      int srcPad = (stride - w) * 4;\n      while (h-- > 0) {\n        int w_ = w;\n        while (w_-- > 0) {\n          dst.put(src.get(r));\n          dst.put(src.get(g));\n          dst.put(src.get(b));\n          r += 4;\n          g += 4;\n          b += 4;\n        }\n        r += srcPad;\n        g += srcPad;\n        b += srcPad;\n      }\n    } else {\n      // Generic code\n      int srcPad = (stride - w) * bpp/8;\n      while (h-- > 0) {\n        int w_ = w;\n        while (w_-- > 0) {\n          int p;\n          byte r, g, b;\n\n          p = pixelFromBuffer(src.duplicate());\n\n          r = (byte)getColorModel().getRed(p);\n          g = (byte)getColorModel().getGreen(p);\n          b = (byte)getColorModel().getBlue(p);\n\n          dst.put(r);\n          dst.put(g);\n          dst.put(b);\n          src.position(src.position() + bpp/8);\n        }\n        src.position(src.position() + srcPad);\n      }\n    }\n  }\n\n  public void rgbFromPixels(byte[] dst, int dstPtr, int[] src, int srcPtr, int pixels, ColorModel cm)\n  {\n    int p;\n    byte r, g, b;\n\n    for (int i=0; i < pixels; i++) {\n      p = src[i];\n\n      dst[dstPtr++] = (byte)cm.getRed(p);\n      dst[dstPtr++] = (byte)cm.getGreen(p);\n      dst[dstPtr++] = (byte)cm.getBlue(p);\n    }\n  }\n\n  // This method should be invoked with a duplicates of buffer\n  public int pixelFromBuffer(ByteBuffer buffer)\n  {\n    int p;\n\n    p = 0xff000000;\n\n    if (!bigEndian) {\n      switch (bpp) {\n      case 32:\n        p |= buffer.get() << 24;\n        p |= buffer.get() << 16;\n      case 16:\n        p |= buffer.get() << 8;\n      case 8:\n        p |= buffer.get();\n      }\n    } else {\n      p |= buffer.get(0);\n      if (bpp >= 16) {\n        p |= buffer.get(1) << 8;\n        if (bpp == 32) {\n          p |= buffer.get(2) << 16;\n          p |= buffer.get(3) << 24;\n        }\n      }\n    }\n\n    return p;\n  }\n\n  public String print() {\n    StringBuffer s = new StringBuffer();\n    s.append(\"depth \"+depth+\" (\"+bpp+\"bpp)\");\n    if (bpp != 8) {\n      if (bigEndian)\n        s.append(\" big-endian\");\n      else\n        s.append(\" little-endian\");\n    }\n\n    if (!trueColour) {\n      s.append(\" colour-map\");\n      return s.toString();\n    }\n\n    if (blueShift == 0 && greenShift > blueShift && redShift > greenShift &&\n        blueMax  == (1 << greenShift) - 1 &&\n        greenMax == (1 << (redShift-greenShift)) - 1 &&\n        redMax   == (1 << (depth-redShift)) - 1)\n    {\n      s.append(\" rgb\"+(depth-redShift)+(redShift-greenShift)+greenShift);\n      return s.toString();\n    }\n\n    if (redShift == 0 && greenShift > redShift && blueShift > greenShift &&\n        redMax   == (1 << greenShift) - 1 &&\n        greenMax == (1 << (blueShift-greenShift)) - 1 &&\n        blueMax  == (1 << (depth-blueShift)) - 1)\n    {\n      s.append(\" bgr\"+(depth-blueShift)+(blueShift-greenShift)+greenShift);\n      return s.toString();\n    }\n\n    s.append(\" rgb max \"+redMax+\",\"+greenMax+\",\"+blueMax+\" shift \"+redShift+\n             \",\"+greenShift+\",\"+blueShift);\n    return s.toString();\n  }\n\n  private static int bits(int value)\n  {\n    int bits;\n\n    bits = 16;\n\n    if ((value & 0xff00) == 0) {\n      bits -= 8;\n      value <<= 8;\n    }\n    if ((value & 0xf000) == 0) {\n      bits -= 4;\n      value <<= 4;\n    }\n    if ((value & 0xc000) == 0) {\n      bits -= 2;\n      value <<= 2;\n    }\n    if ((value & 0x8000) == 0) {\n      bits -= 1;\n      value <<= 1;\n    }\n\n    return bits;\n  }\n\n  private void updateState()\n  {\n    int endianTest = 1;\n\n    redBits = bits(redMax);\n    greenBits = bits(greenMax);\n    blueBits = bits(blueMax);\n\n    maxBits = redBits;\n    if (greenBits > maxBits)\n      maxBits = greenBits;\n    if (blueBits > maxBits)\n      maxBits = blueBits;\n\n    minBits = redBits;\n    if (greenBits < minBits)\n      minBits = greenBits;\n    if (blueBits < minBits)\n      minBits = blueBits;\n\n    if ((((char)endianTest) == 0) != bigEndian)\n      endianMismatch = true;\n    else\n      endianMismatch = false;\n\n    model = getColorModel(this);\n  }\n\n  private boolean isSane()\n  {\n    int totalBits;\n\n    if ((bpp != 8) && (bpp != 16) && (bpp != 32))\n      return false;\n    if (depth > bpp)\n      return false;\n\n    if (!trueColour && (depth != 8))\n      return false;\n\n    if ((redMax & (redMax + 1)) != 0)\n      return false;\n    if ((greenMax & (greenMax + 1)) != 0)\n      return false;\n    if ((blueMax & (blueMax + 1)) != 0)\n      return false;\n\n    /*\n     * We don't allow individual channels > 8 bits in order to keep our\n     * conversions simple.\n     */\n    if (redMax >= (1 << 8))\n      return false;\n    if (greenMax >= (1 << 8))\n      return false;\n    if (blueMax >= (1 << 8))\n      return false;\n\n    totalBits = bits(redMax) + bits(greenMax) + bits(blueMax);\n    if (totalBits > depth)\n      return false;\n\n    if ((bits(redMax) + redShift) > bpp)\n      return false;\n    if ((bits(greenMax) + greenShift) > bpp)\n      return false;\n    if ((bits(blueMax) + blueShift) > bpp)\n      return false;\n\n    if (((redMax << redShift) & (greenMax << greenShift)) != 0)\n      return false;\n    if (((redMax << redShift) & (blueMax << blueShift)) != 0)\n      return false;\n    if (((greenMax << greenShift) & (blueMax << blueShift)) != 0)\n      return false;\n\n    return true;\n  }\n\n  public void bufferFromPixel(ByteBuffer buffer, int p)\n  {\n    if (bigEndian) {\n      switch (bpp) {\n        case 32:\n          buffer.put((byte)((p >> 24) & 0xff));\n          buffer.put((byte)((p >> 16) & 0xff));\n          break;\n        case 16:\n          buffer.put((byte)((p >> 8) & 0xff));\n          break;\n        case 8:\n          buffer.put((byte)((p >> 0) & 0xff));\n          break;\n      }\n    } else {\n      buffer.put(0, (byte)((p >> 0) & 0xff));\n      if (bpp >= 16) {\n        buffer.put(1, (byte)((p >> 8) & 0xff));\n        if (bpp == 32) {\n          buffer.put(2, (byte)((p >> 16) & 0xff));\n          buffer.put(3, (byte)((p >> 24) & 0xff));\n        }\n      }\n    }\n  }\n\n  public ColorModel getColorModel()\n  {\n    return model;\n  }\n\n  public static ColorModel getColorModel(PixelFormat pf) {\n    if (!(pf.bpp == 32) && !(pf.bpp == 16) && !(pf.bpp == 8))\n      throw new Exception(\"Internal error: bpp must be 8, 16, or 32 in PixelBuffer (\"+pf.bpp+\")\");\n    ColorModel cm;\n    switch (pf.depth) {\n    case  3:\n      // Fall-through to depth 8\n    case  6:\n      // Fall-through to depth 8\n    case  8:\n      int rmask = pf.redMax << pf.redShift;\n      int gmask = pf.greenMax << pf.greenShift;\n      int bmask = pf.blueMax << pf.blueShift;\n      cm = new DirectColorModel(8, rmask, gmask, bmask);\n      break;\n    case 16:\n      cm = new DirectColorModel(32, 0xF800, 0x07C0, 0x003E);\n      break;\n    case 24:\n      cm = new DirectColorModel(32, (0xff << 16), (0xff << 8), 0xff);\n      break;\n    case 32:\n      cm = new DirectColorModel(32, (0xff << pf.redShift),\n        (0xff << pf.greenShift), (0xff << pf.blueShift));\n      break;\n    default:\n      throw new Exception(\"Unsupported color depth (\"+pf.depth+\")\");\n    }\n    assert(cm != null);\n    return cm;\n  }\n\n  public ColorConvertOp getColorConvertOp(ColorSpace src)\n  {\n    // The overhead associated with initializing ColorConvertOps is\n    // enough to justify maintaining a static lookup table.\n    if (converters.containsKey(src.getType()))\n      return converters.get(src.getType());\n    ColorSpace dst = model.getColorSpace();\n    converters.put(src.getType(), new ColorConvertOp(src, dst, null));\n    return converters.get(src.getType());\n  }\n\n  public ByteOrder getByteOrder()\n  {\n    if (isBigEndian())\n      return ByteOrder.BIG_ENDIAN;\n    else\n      return ByteOrder.LITTLE_ENDIAN;\n  }\n\n  public Raster rasterFromBuffer(Rect r, ByteBuffer buf)\n  {\n    Buffer dst;\n    DataBuffer db = null;\n\n    SampleModel sm =\n      model.createCompatibleSampleModel(r.width(), r.height());\n    switch (sm.getTransferType()) {\n    case DataBuffer.TYPE_INT:\n      dst = IntBuffer.allocate(r.area()).put(buf.asIntBuffer());\n      db = new DataBufferInt(((IntBuffer)dst).array(), r.area());\n      break;\n    case DataBuffer.TYPE_BYTE:\n      db = new DataBufferByte(buf.array(), r.area());\n      break;\n    case DataBuffer.TYPE_SHORT:\n      dst = ShortBuffer.allocate(r.area()).put(buf.asShortBuffer());\n      db = new DataBufferShort(((ShortBuffer)dst).array(), r.area());\n      break;\n    }\n    assert(db != null);\n    return Raster.createRaster(sm, db, new java.awt.Point(0, 0));\n  }\n\n  private static HashMap<Integer, ColorConvertOp> converters;\n\n  public int bpp;\n  public int depth;\n  public boolean bigEndian;\n  public boolean trueColour;\n  public int redMax;\n  public int greenMax;\n  public int blueMax;\n  public int redShift;\n  public int greenShift;\n  public int blueShift;\n\n  protected int redBits, greenBits, blueBits;\n  protected int maxBits, minBits;\n  protected boolean endianMismatch;\n\n  private ColorModel model;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Point.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class Point {\n\n  // Point\n  //\n  // Represents a point in 2D space, by X and Y coordinates.\n  // Can also be used to represent a delta, or offset, between\n  // two Points.\n  // Functions are provided to allow Points to be compared for\n  // equality and translated by a supplied offset.\n  // Functions are also provided to negate offset Points.\n\n  public Point() {x=0; y=0;}\n  public Point(int x_, int y_) { x=x_; y=y_;}\n  public final Point negate() {return new Point(-x, -y);}\n  public final boolean equals(Point p) {return (x==p.x && y==p.y);}\n  public final Point translate(Point p) {return new Point(x+p.x, y+p.y);}\n  public final Point subtract(Point p) {return new Point(x-p.x, y-p.y);}\n  public int x, y;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/RREDecoder.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2016-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.nio.*;\n\nimport com.tigervnc.rdr.*;\n\npublic class RREDecoder extends Decoder {\n\n  public RREDecoder() { super(DecoderFlags.DecoderPlain); }\n\n  public void readRect(Rect r, InStream is,\n                       ServerParams server, OutStream os)\n  {\n    int numRects;\n\n    numRects = is.readU32();\n    os.writeU32(numRects);\n\n    os.copyBytes(is, server.pf().bpp/8 + numRects * (server.pf().bpp/8 + 8));\n  }\n\n  public void decodeRect(Rect r, Object buffer,\n                         int buflen, ServerParams server,\n                         ModifiablePixelBuffer pb)\n  {\n    MemInStream is = new MemInStream((byte[])buffer, 0, buflen);\n    PixelFormat pf = server.pf();\n    switch (pf.bpp) {\n    case 8:  rreDecode8 (r, is, pf, pb); break;\n    case 16: rreDecode16(r, is, pf, pb); break;\n    case 32: rreDecode32(r, is, pf, pb); break;\n    }\n  }\n\n  private static ByteBuffer READ_PIXEL(InStream is, PixelFormat pf) {\n    ByteBuffer b = ByteBuffer.allocate(4);\n    switch (pf.bpp) {\n    case 8:\n      b.putInt(is.readOpaque8());\n      return ByteBuffer.allocate(1).put(b.get(3));\n    case 16:\n      b.putInt(is.readOpaque16());\n      return ByteBuffer.allocate(2).put(b.array(), 2, 2);\n    case 32:\n    default:\n      b.putInt(is.readOpaque32());\n      return b;\n    }\n  }\n\n  private void RRE_DECODE(Rect r, InStream is,\n                          PixelFormat pf, ModifiablePixelBuffer pb)\n  {\n    int nSubrects = is.readU32();\n    byte[] bg = READ_PIXEL(is, pf).array();\n    pb.fillRect(pf, r, bg);\n\n    for (int i = 0; i < nSubrects; i++) {\n      byte[] pix = READ_PIXEL(is, pf).array();\n      int x = is.readU16();\n      int y = is.readU16();\n      int w = is.readU16();\n      int h = is.readU16();\n      pb.fillRect(pf, new Rect(r.tl.x+x, r.tl.y+y, r.tl.x+x+w, r.tl.y+y+h), pix);\n    }\n  }\n\n  private void rreDecode8(Rect r, InStream is,\n                          PixelFormat pf,\n                          ModifiablePixelBuffer pb)\n  {\n    RRE_DECODE(r, is, pf, pb);\n  }\n\n  private void rreDecode16(Rect r, InStream is,\n                           PixelFormat pf,\n                           ModifiablePixelBuffer pb)\n  {\n    RRE_DECODE(r, is, pf, pb);\n  }\n\n  private void rreDecode32(Rect r, InStream is,\n                           PixelFormat pf,\n                           ModifiablePixelBuffer pb)\n  {\n    RRE_DECODE(r, is, pf, pb);\n  }\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/RawDecoder.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport com.tigervnc.rdr.*;\n\npublic class RawDecoder extends Decoder {\n\n  public RawDecoder() { super(DecoderFlags.DecoderPlain); }\n\n  public void readRect(Rect r, InStream is,\n                       ServerParams server, OutStream os)\n  {\n    os.copyBytes(is, r.area() * server.pf().bpp/8);\n  }\n\n  static LogWriter vlog = new LogWriter(\"RawDecoder\");\n  public void decodeRect(Rect r, Object buffer,\n                         int buflen, ServerParams server,\n                         ModifiablePixelBuffer pb)\n  {\n    assert(buflen >= r.area() * server.pf().bpp/8);\n    pb.imageRect(server.pf(), r, (byte[])buffer);\n  }\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Rect.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class Rect {\n\n  // Rect\n  //\n  // Represents a rectangular region defined by its top-left (tl)\n  // and bottom-right (br) Points.\n  // Rects may be compared for equality, checked to determine whether\n  // or not they are empty, cleared (made empty), or intersected with\n  // one another.  The bounding rectangle of two existing Rects\n  // may be calculated, as may the area of a Rect.\n  // Rects may also be translated, in the same way as Points, by\n  // an offset specified in a Point structure.\n\n  public Rect() {\n    tl=new Point(0,0);\n    br=new Point(0,0);\n  }\n  public Rect(Point tl_, Point br_) {\n    tl=new Point(tl_.x, tl_.y);\n    br=new Point(br_.x,br_.y);\n  }\n  public Rect(int x1, int y1, int x2, int y2) {\n    tl=new Point(x1, y1);\n    br=new Point(x2, y2);\n  }\n  public final void setXYWH(int x, int y, int w, int h) {\n    tl.x = x; tl.y = y; br.x = x+w; br.y = y+h;\n  }\n  public final Rect intersect(Rect r) {\n    Rect result = new Rect();\n    result.tl.x = Math.max(tl.x, r.tl.x);\n    result.tl.y = Math.max(tl.y, r.tl.y);\n    result.br.x = Math.max(Math.min(br.x, r.br.x), result.tl.x);\n    result.br.y = Math.max(Math.min(br.y, r.br.y), result.tl.y);\n    return result;\n  }\n  public final Rect union_boundary(Rect r) {\n    if (r.is_empty()) return this;\n    if (is_empty()) return r;\n    Rect result = new Rect();\n    result.tl.x = Math.min(tl.x, r.tl.x);\n    result.tl.y = Math.min(tl.y, r.tl.y);\n    result.br.x = Math.max(br.x, r.br.x);\n    result.br.y = Math.max(br.y, r.br.y);\n    return result;\n  }\n  public final Rect translate(Point p) {\n    return new Rect(tl.translate(p), br.translate(p));\n  }\n  public final boolean equals(Rect r) {return r.tl.equals(tl) && r.br.equals(br);}\n  public final boolean is_empty() {return (tl.x >= br.x) || (tl.y >= br.y);}\n  public final void clear() {tl = new Point(); br = new Point();}\n  public final boolean enclosed_by(Rect r) {\n    return (tl.x>=r.tl.x) && (tl.y>=r.tl.y) && (br.x<=r.br.x) && (br.y<=r.br.y);\n  }\n  public final boolean overlaps(Rect r) {\n    return tl.x < r.br.x && tl.y < r.br.y && br.x > r.tl.x && br.y > r.tl.y;\n  }\n  public final int area() {\n    int area = (br.x-tl.x)*(br.y-tl.y);\n    if (area > 0)\n      return area;\n    return 0;\n  }\n  public final Point dimensions() {return new Point(width(), height());}\n  public final int width() {return br.x-tl.x;}\n  public final int height() {return br.y-tl.y;}\n  public final boolean contains(Point p) {\n    return (tl.x<=p.x) && (tl.y<=p.y) && (br.x>p.x) && (br.y>p.y);\n  }\n  public Point tl;\n  public Point br;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Region.java",
    "content": "/* Copyright (C) 2016 Brian P. Hinz.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.awt.*;\nimport java.awt.geom.*;\n\npublic class Region extends Area {\n\n  // Create an empty region\n  public Region() {\n    super();\n  }\n\n  // Create a rectangular region\n  public Region(Rect r) {\n    super(new Rectangle(r.tl.x, r.tl.y, r.width(), r.height()));\n  }\n\n  public Region(Region r) {\n    super(r);\n  }\n\n  public void clear() { reset(); }\n\n  public void reset(Rect r) {\n    if (r.is_empty()) {\n      clear();\n    } else {\n      clear();\n      assign_union(new Region(r));\n    }\n  }\n\n  public void translate(Point delta) {\n    AffineTransform t = \n      AffineTransform.getTranslateInstance((double)delta.x, (double)delta.y);\n    transform(t);\n  }\n\n  public void assign_intersect(Region r) {\n    super.intersect(r);\n  }\n\n  public void assign_union(Region r) {\n    super.add(r);\n  }\n\n  public void assign_subtract(Region r) {\n    super.subtract(r);\n  }\n\n  public Region intersect(Region r) {\n    Region reg = new Region(this);\n    ((Area)reg).intersect(r);\n    return reg;\n  }\n\n  public Region union(Region r) {\n    Region reg = new Region(this);\n    ((Area)reg).add(r);\n    return reg;\n  }\n\n  public Region subtract(Region r) {\n    Region reg = new Region(this);\n    ((Area)reg).subtract(r);\n    return reg;\n  }\n\n  public boolean is_empty() { return isEmpty(); }\n\n  public Rect get_bounding_rect() {\n    Rectangle b = getBounds();\n    return new Rect((int)b.getX(), (int)b.getY(),\n                    (int)b.getWidth(), (int)b.getHeight());\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Screen.java",
    "content": "/* Copyright 2009 Pierre Ossman for Cendio AB\n * Copyright (C) 2011 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n// Represents a single RFB virtual screen, which includes\n// coordinates, an id and flags.\n\npackage com.tigervnc.rfb;\n\npublic class Screen {\n\n    public Screen() { id=0; flags=0; dimensions = new Rect(); }\n\n    public Screen(int id_, int x_, int y_, int w_, int h_, int flags_) {\n      id = id_;\n      dimensions = new Rect(x_, y_, x_+w_, y_+h_);\n      flags = flags_;\n    }\n\n    public final boolean operator(Screen r) {\n      if (id != r.id)\n        return false;\n      if (!dimensions.equals(r.dimensions))\n        return false;\n      if (flags != r.flags)\n        return false;\n      return true;\n    }\n\n    public int id;\n    public Rect dimensions;\n    public int flags;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/ScreenSet.java",
    "content": "/* Copyright 2009 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n// Management class for the RFB virtual screens\n\npackage com.tigervnc.rfb;\n\nimport java.util.*;\n\npublic class ScreenSet {\n\n  // Represents a complete screen configuration, excluding framebuffer\n  // dimensions.\n\n  public ScreenSet() {\n    screens = new ArrayList<Screen>();\n  }\n\n  public final ListIterator<Screen> begin() { return screens.listIterator(0); }\n  public final ListIterator<Screen> end() {\n    return screens.listIterator(screens.size());\n  }\n  public final int num_screens() { return screens.size(); }\n\n  public final void add_screen(Screen screen) { screens.add(screen); }\n  public final void remove_screen(int id) {\n    ListIterator iter, nextiter;\n    for (iter = begin(); iter != end(); iter = nextiter) {\n      nextiter = iter; nextiter.next();\n      if (((Screen)iter.next()).id == id)\n        iter.remove();\n    }\n  }\n\n  public final boolean validate(int fb_width, int fb_height) {\n      List<Integer> seen_ids = new ArrayList<Integer>();\n      Rect fb_rect = new Rect();\n\n      if (screens.isEmpty())\n        return false;\n      if (num_screens() > 255)\n        return false;\n\n      fb_rect.setXYWH(0, 0, fb_width, fb_height);\n\n      for (Iterator<Screen> iter = screens.iterator(); iter.hasNext(); ) {\n        Screen refScreen = (Screen)iter.next();\n        if (refScreen.dimensions.is_empty())\n          return false;\n        if (!refScreen.dimensions.enclosed_by(fb_rect))\n          return false;\n        if (seen_ids.lastIndexOf(refScreen.id) != -1)\n          return false;\n        seen_ids.add(refScreen.id);\n      }\n\n      return true;\n  }\n\n  public final void debug_print() {\n    vlog.debug(num_screens()+\" screen(s)\");\n    for (Iterator<Screen> iter = screens.iterator(); iter.hasNext(); ) {\n      Screen refScreen = (Screen)iter.next();\n      vlog.debug(\"    \"+refScreen.id+\" (0x\"+refScreen.id+\"): \"+\n                refScreen.dimensions.width()+\"x\"+refScreen.dimensions.height()+\n                \"+\"+refScreen.dimensions.tl.x+\"+\"+refScreen.dimensions.tl.y+\n                \" (flags 0x\"+refScreen.flags+\")\");\n    }\n  }\n\n  public ArrayList<Screen> screens;\n\n  static LogWriter vlog = new LogWriter(\"ScreenSet\");\n\n}\n\n"
  },
  {
    "path": "java/com/tigervnc/rfb/Security.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2011-2015 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// SecTypes.java - constants for the various security types.\n//\n\npackage com.tigervnc.rfb;\nimport java.util.*;\n\npublic class Security {\n\n  public static final int secTypeInvalid   = 0;\n  public static final int secTypeNone      = 1;\n  public static final int secTypeVncAuth   = 2;\n\n  public static final int secTypeRA2       = 5;\n  public static final int secTypeRA2ne     = 6;\n\n  public static final int secTypeSSPI      = 7;\n  public static final int secTypeSSPIne    = 8;\n\n  public static final int secTypeTight     = 16;\n  public static final int secTypeUltra     = 17;\n  public static final int secTypeTLS       = 18;\n  public static final int secTypeVeNCrypt  = 19;\n\n  public static final int secTypeRA256     = 129;\n  public static final int secTypeRAne256   = 130;\n\n  /* VeNCrypt subtypes */\n  public static final int secTypePlain     = 256;\n  public static final int secTypeTLSNone   = 257;\n  public static final int secTypeTLSVnc    = 258;\n  public static final int secTypeTLSPlain  = 259;\n  public static final int secTypeX509None  = 260;\n  public static final int secTypeX509Vnc   = 261;\n  public static final int secTypeX509Plain = 262;\n  public static final int secTypeIdent     = 265;\n  public static final int secTypeTLSIdent  = 266;\n  public static final int secTypeX509Ident = 267;\n\n  public static final int secTypeRA2UserPass = 1;\n  public static final int secTypeRA2Pass     = 2;\n\n  // result types\n\n  public static final int secResultOK = 0;\n  public static final int secResultFailed = 1;\n  public static final int secResultTooMany = 2; // deprecated\n\n  public Security() { }\n\n  public Security(StringParameter secTypes)\n  {\n    String secTypesStr;\n\n    secTypesStr = secTypes.getData();\n    enabledSecTypes = parseSecTypes(secTypesStr);\n\n    secTypesStr = null;\n  }\n\n  private List<Integer> enabledSecTypes = new ArrayList<Integer>();\n\n  public final List<Integer> GetEnabledSecTypes()\n  {\n    List<Integer> result = new ArrayList<Integer>();\n\n   /* Partial workaround for Vino's stupid behaviour. It doesn't allow\n    * the basic authentication types as part of the VeNCrypt handshake,\n    * making it impossible for a client to do opportunistic encryption.\n    * At least make it possible to connect when encryption is explicitly\n    * disabled. */\n    for (Iterator<Integer> i = enabledSecTypes.iterator(); i.hasNext(); ) {\n      int refType = (Integer)i.next();\n      if (refType >= 0x100) {\n        result.add(secTypeVeNCrypt);\n        break;\n      }\n    }\n\n    for (Iterator<Integer> i = enabledSecTypes.iterator(); i.hasNext(); ) {\n      int refType = (Integer)i.next();\n      if (refType < 0x100)\n        result.add(refType);\n    }\n\n    return (result);\n  }\n\n  public final List<Integer> GetEnabledExtSecTypes()\n  {\n    List<Integer> result = new ArrayList<Integer>();\n\n    for (Iterator<Integer> i = enabledSecTypes.iterator(); i.hasNext(); ) {\n      int refType = (Integer)i.next();\n      if (refType != secTypeVeNCrypt) /* Do not include VeNCrypt to avoid loops */\n        result.add(refType);\n    }\n\n    return (result);\n  }\n\n  public final void EnableSecType(int secType)\n  {\n\n    for (Iterator<Integer> i = enabledSecTypes.iterator(); i.hasNext(); )\n      if ((Integer)i.next() == secType)\n        return;\n\n    enabledSecTypes.add(secType);\n  }\n\n  public boolean IsSupported(int secType)\n  {\n    Iterator<Integer> i;\n\n    for (i = enabledSecTypes.iterator(); i.hasNext(); )\n     if ((Integer)i.next() == secType)\n       return true;\n    if (secType == secTypeVeNCrypt)\n     return true;\n\n    return false;\n  }\n\n  public String ToString()\n  {\n    Iterator<Integer> i;\n    String out = new String(\"\");\n    boolean firstpass = true;\n    String name;\n\n    for (i = enabledSecTypes.iterator(); i.hasNext(); ) {\n      name = secTypeName((Integer)i.next());\n      if (name.startsWith(\"[\")) /* Unknown security type */\n        continue;\n\n      if (!firstpass)\n        out = out.concat(\",\");\n      else\n        firstpass = false;\n      out = out.concat(name);\n    }\n\n    return out;\n  }\n\n  public void DisableSecType(int secType) { enabledSecTypes.remove((Object)secType); }\n\n  public static int secTypeNum(String name) {\n    if (name.equalsIgnoreCase(\"None\"))      return secTypeNone;\n    if (name.equalsIgnoreCase(\"VncAuth\"))   return secTypeVncAuth;\n    if (name.equalsIgnoreCase(\"Tight\"))\t    return secTypeTight;\n    if (name.equalsIgnoreCase(\"RA2\"))       return secTypeRA2;\n    if (name.equalsIgnoreCase(\"RA2ne\"))\t    return secTypeRA2ne;\n    if (name.equalsIgnoreCase(\"RA2_256\"))   return secTypeRA256;\n    if (name.equalsIgnoreCase(\"RA2ne_256\"))\treturn secTypeRAne256;\n    if (name.equalsIgnoreCase(\"SSPI\"))      return secTypeSSPI;\n    if (name.equalsIgnoreCase(\"SSPIne\"))\t  return secTypeSSPIne;\n    //if (name.equalsIgnoreCase(\"ultra\"))\t    return secTypeUltra;\n    //if (name.equalsIgnoreCase(\"TLS\"))\t      return secTypeTLS;\n    if (name.equalsIgnoreCase(\"VeNCrypt\"))  return secTypeVeNCrypt;\n\n    /* VeNCrypt subtypes */\n    if (name.equalsIgnoreCase(\"Plain\"))\t    return secTypePlain;\n    if (name.equalsIgnoreCase(\"Ident\"))\t    return secTypeIdent;\n    if (name.equalsIgnoreCase(\"TLSNone\"))\t  return secTypeTLSNone;\n    if (name.equalsIgnoreCase(\"TLSVnc\"))\t  return secTypeTLSVnc;\n    if (name.equalsIgnoreCase(\"TLSPlain\"))\treturn secTypeTLSPlain;\n    if (name.equalsIgnoreCase(\"TLSIdent\"))\treturn secTypeTLSIdent;\n    if (name.equalsIgnoreCase(\"X509None\"))\treturn secTypeX509None;\n    if (name.equalsIgnoreCase(\"X509Vnc\"))\t  return secTypeX509Vnc;\n    if (name.equalsIgnoreCase(\"X509Plain\")) return secTypeX509Plain;\n    if (name.equalsIgnoreCase(\"X509Ident\")) return secTypeX509Ident;\n\n    return secTypeInvalid;\n  }\n\n  public static String secTypeName(int num) {\n    switch (num) {\n    case secTypeNone:       return \"None\";\n    case secTypeVncAuth:    return \"VncAuth\";\n    case secTypeTight:      return \"Tight\";\n    case secTypeRA2:        return \"RA2\";\n    case secTypeRA2ne:      return \"RA2ne\";\n    case secTypeRA256:      return \"RA2_256\";\n    case secTypeRAne256:    return \"RA2ne_256\";\n    case secTypeSSPI:       return \"SSPI\";\n    case secTypeSSPIne:     return \"SSPIne\";\n    //case secTypeUltra:      return \"Ultra\";\n    //case secTypeTLS:        return \"TLS\";\n    case secTypeVeNCrypt:   return \"VeNCrypt\";\n\n    /* VeNCrypt subtypes */\n    case secTypePlain:      return \"Plain\";\n    case secTypeIdent:      return \"Ident\";\n    case secTypeTLSNone:    return \"TLSNone\";\n    case secTypeTLSVnc:     return \"TLSVnc\";\n    case secTypeTLSPlain:   return \"TLSPlain\";\n    case secTypeTLSIdent:   return \"TLSIdent\";\n    case secTypeX509None:   return \"X509None\";\n    case secTypeX509Vnc:    return \"X509Vnc\";\n    case secTypeX509Plain:  return \"X509Plain\";\n    case secTypeX509Ident:  return \"X509Ident\";\n    default:                return \"[unknown secType]\";\n    }\n  }\n\n  public final static List<Integer> parseSecTypes(String types_)\n  {\n    List<Integer> result = new ArrayList<Integer>();\n    String[] types = types_.split(\",\");\n    for (int i = 0; i < types.length; i++) {\n      int typeNum = secTypeNum(types[i]);\n      if (typeNum != secTypeInvalid)\n        result.add(typeNum);\n    }\n    return (result);\n  }\n\n  public final void SetSecTypes(List<Integer> secTypes) {\n    enabledSecTypes = secTypes;\n  }\n\n  static LogWriter vlog = new LogWriter(\"Security\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/SecurityClient.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2010 TigerVNC Team\n * Copyright (C) 2011-2017 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class SecurityClient extends Security {\n\n  public SecurityClient() { super(secTypes); }\n\n  public CSecurity GetCSecurity(int secType)\n  {\n    assert (CSecurity.upg != null); /* (upg == null) means bug in the viewer */\n    assert (CSecurityTLS.msg != null);\n\n    if (!IsSupported(secType))\n      throw new Exception(\"Security type not supported\");\n\n    switch (secType) {\n    case Security.secTypeNone: return (new CSecurityNone());\n    case Security.secTypeVncAuth: return (new CSecurityVncAuth());\n    case Security.secTypeVeNCrypt: return (new CSecurityVeNCrypt(this));\n    case Security.secTypePlain: return (new CSecurityPlain());\n    case Security.secTypeIdent: return (new CSecurityIdent());\n    case Security.secTypeTLSNone:\n      return (new CSecurityStack(secTypeTLSNone, \"TLS with no password\",\n  \t\t\t      new CSecurityTLS(true), null));\n    case Security.secTypeTLSVnc:\n      return (new CSecurityStack(secTypeTLSVnc, \"TLS with VNCAuth\",\n  \t\t\t      new CSecurityTLS(true), new CSecurityVncAuth()));\n    case Security.secTypeTLSPlain:\n      return (new CSecurityStack(secTypeTLSPlain, \"TLS with Username/Password\",\n  \t\t\t      new CSecurityTLS(true), new CSecurityPlain()));\n    case Security.secTypeTLSIdent:\n      return (new CSecurityStack(secTypeTLSIdent, \"TLS with username only\",\n  \t\t\t      new CSecurityTLS(true), new CSecurityIdent()));\n    case Security.secTypeX509None:\n      return (new CSecurityStack(secTypeX509None, \"X509 with no password\",\n  \t\t\t      new CSecurityTLS(false), null));\n    case Security.secTypeX509Vnc:\n      return (new CSecurityStack(secTypeX509Vnc, \"X509 with VNCAuth\",\n  \t\t\t      new CSecurityTLS(false), new CSecurityVncAuth()));\n    case Security.secTypeX509Plain:\n      return (new CSecurityStack(secTypeX509Plain, \"X509 with Username/Password\",\n  \t\t\t      new CSecurityTLS(false), new CSecurityPlain()));\n    case Security.secTypeX509Ident:\n      return (new CSecurityStack(secTypeX509Ident, \"X509 with username only\",\n  \t\t\t      new CSecurityTLS(false), new CSecurityIdent()));\n    case Security.secTypeRA2:\n      return (new CSecurityRSAAES(secType, 128, true));\n    case Security.secTypeRA2ne:\n      return (new CSecurityRSAAES(secType, 128, false));\n    case Security.secTypeRA256:\n      return (new CSecurityRSAAES(secType, 256, true));\n    case Security.secTypeRAne256:\n      return (new CSecurityRSAAES(secType, 256, false));\n    default:\n      throw new Exception(\"Security type not supported\");\n    }\n\n  }\n\n  public static void setDefaults()\n  {\n      CSecurityTLS.setDefaults();\n  }\n\n  public static StringParameter secTypes\n  = new StringParameter(\"SecurityTypes\",\n                        \"Specify which security scheme to use (None, VncAuth, Plain, Ident, TLSNone, TLSVnc, TLSPlain, TLSIdent, X509None, X509Vnc, X509Plain, X509Ident, RA2, RA2ne, RA2_256, RA2ne_256)\",\n                        \"X509Ident,X509Plain,TLSIdent,TLSPlain,X509Vnc,TLSVnc,X509None,TLSNone,Ident,RA2_256,RA2,RA2ne_256,RA2ne,VncAuth,None\", Configuration.ConfigurationObject.ConfViewer);\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/ServerParams.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright (C) 2012-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport com.tigervnc.rdr.*;\nimport java.util.ArrayList;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\npublic class ServerParams {\n\n  private static final int subsampleUndefined = -1;\n  private static final int subsampleNone = 0;\n  private static final int subsampleGray = 1;\n  private static final int subsample2X = 2;\n  private static final int subsample4X = 3;\n  private static final int subsample8X = 4;\n  private static final int subsample16X = 5;\n\n  public ServerParams()\n  {\n    majorVersion = 0; minorVersion = 0;\n    width_ = 0; height_ = 0; useCopyRect = false;\n    supportsLocalCursor = false; supportsLocalXCursor = false;\n    supportsLocalCursorWithAlpha = false;\n    supportsDesktopResize = false; supportsExtendedDesktopSize = false;\n    supportsDesktopRename = false; supportsLastRect = false;\n    supportsSetDesktopSize = false; supportsFence = false;\n    supportsContinuousUpdates = false;\n    supportsClientRedirect = false;\n    compressLevel = 6; qualityLevel = -1; fineQualityLevel = -1;\n    subsampling = subsampleUndefined; name_ = null; verStrPos = 0;\n\n    encodings_ = new ArrayList();\n    screenLayout_ = new ScreenSet();\n\n    setName(\"\");\n  }\n\n  public int majorVersion;\n  public int minorVersion;\n\n  public void setVersion(int major, int minor) {\n    majorVersion = major; minorVersion = minor;\n  }\n  public boolean isVersion(int major, int minor) {\n    return majorVersion == major && minorVersion == minor;\n  }\n  public boolean beforeVersion(int major, int minor) {\n    return (majorVersion < major ||\n            (majorVersion == major && minorVersion < minor));\n  }\n  public boolean afterVersion(int major, int minor) {\n    return !beforeVersion(major,minor+1);\n  }\n\n  public int width() { return width_; }\n  public int height() { return height_; }\n  public ScreenSet screenLayout() { return screenLayout_; }\n\n  public void setDimensions(int width, int height)\n  {\n    ScreenSet layout = new ScreenSet();\n    layout.add_screen(new Screen(0, 0, 0, width, height, 0));\n    setDimensions(width, height, layout);\n  }\n\n  public void setDimensions(int width, int height, ScreenSet layout)\n  {\n    if (!layout.validate(width, height))\n      throw new Exception(\"Attempted to configure an invalid screen layout\");\n\n    width_ = width;\n    height_ = height;\n    screenLayout_ = layout;\n  }\n\n  public PixelFormat pf() { return pf_; }\n  public void setPF(PixelFormat pf) {\n\n    pf_ = pf;\n\n    if (pf.bpp != 8 && pf.bpp != 16 && pf.bpp != 32)\n      throw new Exception(\"setPF: not 8, 16 or 32 bpp?\");\n  }\n\n  public String name() { return name_; }\n  public void setName(String name)\n  {\n    name_ = name;\n  }\n\n  public boolean supportsEncoding(int encoding)\n  {\n    return encodings_.indexOf(encoding) != -1;\n  }\n\n  public void setEncodings(int nEncodings, int[] encodings)\n  {\n    useCopyRect = false;\n    supportsLocalCursor = false;\n    supportsLocalCursorWithAlpha = false;\n    supportsDesktopResize = false;\n    supportsExtendedDesktopSize = false;\n    supportsLocalXCursor = false;\n    supportsLastRect = false;\n    compressLevel = -1;\n    qualityLevel = -1;\n    fineQualityLevel = -1;\n    subsampling = subsampleUndefined;\n\n    encodings_.clear();\n    encodings_.add(Encodings.encodingRaw);\n\n    for (int i = nEncodings-1; i >= 0; i--) {\n      switch (encodings[i]) {\n      case Encodings.encodingCopyRect:\n        useCopyRect = true;\n        break;\n      case Encodings.pseudoEncodingCursor:\n        supportsLocalCursor = true;\n        break;\n      case Encodings.pseudoEncodingXCursor:\n        supportsLocalXCursor = true;\n        break;\n      case Encodings.pseudoEncodingCursorWithAlpha:\n        supportsLocalCursorWithAlpha = true;\n        break;\n      case Encodings.pseudoEncodingDesktopSize:\n        supportsDesktopResize = true;\n        break;\n      case Encodings.pseudoEncodingExtendedDesktopSize:\n        supportsExtendedDesktopSize = true;\n        break;\n      case Encodings.pseudoEncodingDesktopName:\n        supportsDesktopRename = true;\n        break;\n      case Encodings.pseudoEncodingLastRect:\n        supportsLastRect = true;\n        break;\n      case Encodings.pseudoEncodingFence:\n        supportsFence = true;\n        break;\n      case Encodings.pseudoEncodingContinuousUpdates:\n        supportsContinuousUpdates = true;\n        break;\n      case Encodings.pseudoEncodingClientRedirect:\n        supportsClientRedirect = true;\n        break;\n      case Encodings.pseudoEncodingSubsamp1X:\n        subsampling = subsampleNone;\n        break;\n      case Encodings.pseudoEncodingSubsampGray:\n        subsampling = subsampleGray;\n        break;\n      case Encodings.pseudoEncodingSubsamp2X:\n        subsampling = subsample2X;\n        break;\n      case Encodings.pseudoEncodingSubsamp4X:\n        subsampling = subsample4X;\n        break;\n      case Encodings.pseudoEncodingSubsamp8X:\n        subsampling = subsample8X;\n        break;\n      case Encodings.pseudoEncodingSubsamp16X:\n        subsampling = subsample16X;\n        break;\n      }\n\n      if (encodings[i] >= Encodings.pseudoEncodingCompressLevel0 &&\n          encodings[i] <= Encodings.pseudoEncodingCompressLevel9)\n        compressLevel = encodings[i] - Encodings.pseudoEncodingCompressLevel0;\n\n      if (encodings[i] >= Encodings.pseudoEncodingQualityLevel0 &&\n          encodings[i] <= Encodings.pseudoEncodingQualityLevel9)\n        qualityLevel = encodings[i] - Encodings.pseudoEncodingQualityLevel0;\n\n      if (encodings[i] >= Encodings.pseudoEncodingFineQualityLevel0 &&\n          encodings[i] <= Encodings.pseudoEncodingFineQualityLevel100)\n        fineQualityLevel = encodings[i] - Encodings.pseudoEncodingFineQualityLevel0;\n\n      if (encodings[i] > 0)\n        encodings_.add(encodings[i]);\n    }\n  }\n\n  public boolean useCopyRect;\n\n  public boolean supportsLocalCursor;\n  public boolean supportsLocalXCursor;\n  public boolean supportsLocalCursorWithAlpha;\n  public boolean supportsDesktopResize;\n  public boolean supportsExtendedDesktopSize;\n  public boolean supportsDesktopRename;\n  public boolean supportsLastRect;\n  public boolean supportsClientRedirect;\n\n  public boolean supportsSetDesktopSize;\n  public boolean supportsFence;\n  public boolean supportsContinuousUpdates;\n\n  public int compressLevel;\n  public int qualityLevel;\n  public int fineQualityLevel;\n  public int subsampling;\n\n  private int width_;\n  private int height_;\n  private ScreenSet screenLayout_;\n\n  private PixelFormat pf_;\n  private String name_;\n  private Cursor cursor_;\n  private ArrayList encodings_;\n  private StringBuilder verStr;\n  private int verStrPos;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/StringParameter.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2004-2005 Cendio AB.\n * Copyright 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class StringParameter extends VoidParameter {\n  public StringParameter(String name_, String desc_, String v,\n                         Configuration.ConfigurationObject co)\n  {\n    super(name_, desc_, co);\n    value = v;\n    defValue = v;\n  }\n\n  public StringParameter(String name_, String desc_, String v)\n  {\n    this(name_, desc_, v, Configuration.ConfigurationObject.ConfGlobal);\n  }\n\n  public void setDefaultStr(String v) {\n    value = defValue = v;\n  }\n\n  public boolean setParam(String v) {\n    if (immutable) return true;\n    if (v == null)\n      throw new Exception(\"setParam(<null>) not allowed\");\n    value = v;\n    return value != null;\n  }\n\n  public String getDefaultStr() { return defValue; }\n  public String getValueStr() { return value; }\n\n  public String getValue() { return value; }\n  public String getData() { return value; }\n\n  protected String value;\n  protected String defValue;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/TightDecoder.java",
    "content": "/* Copyright (C) 2000-2003 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright 2004-2005 Cendio AB.\n * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport com.tigervnc.rdr.InStream;\nimport com.tigervnc.rdr.MemInStream;\nimport com.tigervnc.rdr.OutStream;\nimport com.tigervnc.rdr.ZlibInStream;\nimport java.util.ArrayList;\nimport java.io.InputStream;\nimport java.awt.image.*;\nimport java.awt.*;\nimport java.math.BigInteger;\nimport java.io.*;\nimport java.nio.*;\nimport javax.imageio.*;\nimport javax.imageio.stream.*;\n\npublic class TightDecoder extends Decoder {\n\n  final static int TIGHT_MAX_WIDTH = 2048;\n  final static int TIGHT_MIN_TO_COMPRESS = 12;\n\n  // Compression control\n  final static int tightExplicitFilter = 0x04;\n  final static int tightFill = 0x08;\n  final static int tightJpeg = 0x09;\n  final static int tightMaxSubencoding = 0x09;\n\n  // Filters to improve compression efficiency\n  final static int tightFilterCopy = 0x00;\n  final static int tightFilterPalette = 0x01;\n  final static int tightFilterGradient = 0x02;\n\n  public TightDecoder() {\n    super(DecoderFlags.DecoderPartiallyOrdered);\n    zis = new ZlibInStream[4];\n    for (int i = 0; i < 4; i++)\n      zis[i] = new ZlibInStream();\n  }\n\n  public void readRect(Rect r, InStream is,\n                       ServerParams server, OutStream os)\n  {\n    int comp_ctl;\n\n    comp_ctl = is.readU8();\n    os.writeU8(comp_ctl);\n\n    comp_ctl >>= 4;\n\n    // \"Fill\" compression type.\n    if (comp_ctl == tightFill) {\n      if (server.pf().is888())\n        os.copyBytes(is, 3);\n      else\n        os.copyBytes(is, server.pf().bpp/8);\n      return;\n    }\n\n    // \"JPEG\" compression type.\n    if (comp_ctl == tightJpeg) {\n      int len;\n\n      len = readCompact(is);\n      os.writeOpaque32(len);\n      os.copyBytes(is, len);\n      return;\n    }\n\n    // Quit on unsupported compression type.\n    if (comp_ctl > tightMaxSubencoding)\n      throw new Exception(\"TightDecoder: bad subencoding value received\");\n\n    // \"Basic\" compression type.\n\n    int palSize = 0;\n\n    if (r.width() > TIGHT_MAX_WIDTH)\n      throw new Exception(\"TightDecoder: too large rectangle (\"+r.width()+\" pixels)\");\n\n    // Possible palette\n    if ((comp_ctl & tightExplicitFilter) != 0) {\n      int filterId;\n\n      filterId = is.readU8() & 0xff;\n      os.writeU8(filterId);\n\n      switch (filterId) {\n      case tightFilterPalette:\n        palSize = is.readU8() + 1;\n        os.writeU32(palSize - 1);\n\n        if (server.pf().is888())\n          os.copyBytes(is, palSize * 3);\n        else\n          os.copyBytes(is, palSize * server.pf().bpp/8);\n        break;\n      case tightFilterGradient:\n        if (server.pf().bpp == 8)\n          throw new Exception(\"TightDecoder: invalid BPP for gradient filter\");\n        break;\n      case tightFilterCopy:\n        break;\n      default:\n        throw new Exception(\"TightDecoder: unknown filter code received\");\n      }\n    }\n\n    int rowSize, dataSize;\n\n    if (palSize != 0) {\n      if (palSize <= 2)\n        rowSize = (r.width() + 7) / 8;\n      else\n        rowSize = r.width();\n    } else if (server.pf().is888()) {\n      rowSize = r.width() * 3;\n    } else {\n      rowSize = r.width() * server.pf().bpp/8;\n    }\n\n    dataSize = r.height() * rowSize;\n\n    if (dataSize < TIGHT_MIN_TO_COMPRESS) {\n      os.copyBytes(is, dataSize);\n    } else {\n      int len;\n\n      len = readCompact(is);\n      os.writeOpaque32(len);\n      os.copyBytes(is, len);\n    }\n  }\n\n  public boolean doRectsConflict(Rect rectA,\n                                 Object bufferA,\n                                 int buflenA,\n                                 Rect rectB,\n                                 Object bufferB,\n                                 int buflenB,\n                                 ServerParams server)\n  {\n    byte comp_ctl_a, comp_ctl_b;\n\n    assert(buflenA >= 1);\n    assert(buflenB >= 1);\n\n    comp_ctl_a = ((byte[])bufferA)[0];\n    comp_ctl_b = ((byte[])bufferB)[0];\n\n    // Resets or use of zlib pose the same problem, so merge them\n    if ((comp_ctl_a & 0x80) == 0x00)\n      comp_ctl_a |= 1 << ((comp_ctl_a >> 4) & 0x03);\n    if ((comp_ctl_b & 0x80) == 0x00)\n      comp_ctl_b |= 1 << ((comp_ctl_b >> 4) & 0x03);\n\n    if (((comp_ctl_a & 0x0f) & (comp_ctl_b & 0x0f)) != 0)\n      return true;\n\n    return false;\n  }\n\n  public void decodeRect(Rect r, Object buffer,\n                         int buflen, ServerParams server,\n                         ModifiablePixelBuffer pb)\n  {\n    ByteBuffer bufptr;\n    PixelFormat pf = server.pf();\n\n    int comp_ctl;\n\n    bufptr = ByteBuffer.wrap((byte[])buffer);\n\n    assert(buflen >= 1);\n\n    comp_ctl = bufptr.get() & 0xff;\n    buflen -= 1;\n\n    // Reset zlib streams if we are told by the server to do so.\n    for (int i = 0; i < 4; i++) {\n      if ((comp_ctl & 1) != 0) {\n        zis[i].reset();\n      }\n      comp_ctl >>= 1;\n    }\n\n    // \"Fill\" compression type.\n    if (comp_ctl == tightFill) {\n      if (pf.is888()) {\n        ByteBuffer pix = ByteBuffer.allocate(4);\n\n        assert(buflen >= 3);\n\n        pf.bufferFromRGB(pix.duplicate(), bufptr, 1);\n        pb.fillRect(pf, r, pix.array());\n      } else {\n        assert(buflen >= pf.bpp/8);\n        byte[] pix = new byte[pf.bpp/8];\n        bufptr.get(pix);\n        pb.fillRect(pf, r, pix);\n      }\n      return;\n    }\n\n    // \"JPEG\" compression type.\n    if (comp_ctl == tightJpeg) {\n      int len;\n\n      WritableRaster buf;\n\n      JpegDecompressor jd = new JpegDecompressor();\n\n      assert(buflen >= 4);\n\n      len = bufptr.getInt();\n      buflen -= 4;\n\n      // We always use direct decoding with JPEG images\n      jd.decompress(bufptr, len, pb, r, pb.getPF());\n      pb.commitBufferRW(r);\n      return;\n    }\n\n    // Quit on unsupported compression type.\n    if (comp_ctl > tightMaxSubencoding)\n      throw new Exception(\"TightDecoder: bad subencoding value received\");\n\n    // \"Basic\" compression type.\n    int palSize = 0;\n    ByteBuffer palette = ByteBuffer.allocate(256 * 4);\n    boolean useGradient = false;\n\n    if ((comp_ctl & tightExplicitFilter) != 0) {\n      int filterId;\n\n      assert(buflen >= 1);\n\n      filterId = bufptr.get();\n\n      switch (filterId) {\n      case tightFilterPalette:\n        assert(buflen >= 1);\n\n        palSize = bufptr.getInt() + 1;\n        buflen -= 4;\n\n        if (pf.is888()) {\n          ByteBuffer tightPalette = ByteBuffer.allocate(palSize * 3);\n\n          assert(buflen >= tightPalette.capacity());\n\n          bufptr.get(tightPalette.array(), 0, tightPalette.capacity());\n          buflen -= tightPalette.capacity();\n\n          pf.bufferFromRGB(palette.duplicate(), tightPalette, palSize);\n        } else {\n          int len;\n\n          len = palSize * pf.bpp/8;\n\n          assert(buflen >= len);\n\n          bufptr.get(palette.array(), 0, len);\n          buflen -= len;\n        }\n        break;\n      case tightFilterGradient:\n        useGradient = true;\n        break;\n      case tightFilterCopy:\n        break;\n      default:\n        assert(false);\n      }\n    }\n\n    // Determine if the data should be decompressed or just copied.\n    int rowSize, dataSize;\n    ByteBuffer netbuf;\n\n    if (palSize != 0) {\n      if (palSize <= 2)\n        rowSize = (r.width() + 7) / 8;\n      else\n        rowSize = r.width();\n    } else if (pf.is888()) {\n      rowSize = r.width() * 3;\n    } else {\n      rowSize = r.width() * pf.bpp/8;\n    }\n\n    dataSize = r.height() * rowSize;\n\n    if (dataSize < TIGHT_MIN_TO_COMPRESS) {\n      assert(buflen >= dataSize);\n    } else {\n      int len;\n      int streamId;\n      MemInStream ms;\n\n      assert(buflen >= 4);\n\n      len = bufptr.getInt();\n      buflen -= 4;\n\n      assert(buflen >= len);\n\n      streamId = comp_ctl & 0x03;\n      ms = new MemInStream(bufptr.array(), bufptr.position(), len);\n      zis[streamId].setUnderlying(ms, len);\n\n      // Allocate netbuf and read in data\n      netbuf = ByteBuffer.allocate(dataSize);\n\n      zis[streamId].readBytes(netbuf, dataSize);\n\n      zis[streamId].flushUnderlying();\n      zis[streamId].setUnderlying(null, 0);\n      ms = null;\n\n      bufptr = (ByteBuffer)netbuf.flip();\n      buflen = dataSize;\n    }\n\n    ByteBuffer outbuf = ByteBuffer.allocate(r.area() * pf.bpp/8);\n    int stride = r.width();\n\n    if (palSize == 0) {\n      // Truecolor data.\n      if (useGradient) {\n        if (pf.is888()) {\n          FilterGradient24(bufptr, pf, outbuf, stride, r);\n        } else {\n          switch (pf.bpp) {\n          case 8:\n            assert(false);\n            break;\n          case 16:\n            FilterGradient(bufptr, pf, outbuf, stride, r);\n            break;\n          case 32:\n            FilterGradient(bufptr, pf, outbuf, stride, r);\n            break;\n          }\n        }\n      } else {\n        // Copy\n        ByteBuffer ptr = (ByteBuffer)outbuf.duplicate().mark();\n        ByteBuffer srcPtr = bufptr.duplicate();\n        int w = r.width();\n        int h = r.height();\n        if (pf.is888()) {\n          while (h > 0) {\n            pf.bufferFromRGB(ptr.duplicate(), srcPtr.duplicate(), w);\n            ptr.position(ptr.position() + stride * pf.bpp/8);\n            srcPtr.position(srcPtr.position() + w * 3);\n            h--;\n          }\n        } else {\n          while (h > 0) {\n            ptr.put(srcPtr.array(), srcPtr.position(), w * pf.bpp/8);\n            ptr.reset().position(ptr.position() + stride * pf.bpp/8).mark();\n            srcPtr.position(srcPtr.position() + w * pf.bpp/8);\n            h--;\n          }\n        }\n      }\n    } else {\n      // Indexed color\n      switch (pf.bpp) {\n      case 8:\n        FilterPalette8(palette, palSize,\n                       bufptr, outbuf, stride, r);\n        break;\n      case 16:\n        FilterPalette16(palette.asShortBuffer(), palSize,\n                        bufptr, outbuf.asShortBuffer(), stride, r);\n        break;\n      case 32:\n        FilterPalette32(palette.asIntBuffer(), palSize,\n                        bufptr, outbuf.asIntBuffer(), stride, r);\n        break;\n      }\n    }\n\n    pb.imageRect(pf, r, outbuf.array());\n\n  }\n\n  final private void FilterGradient24(ByteBuffer inbuf,\n                                      PixelFormat pf, ByteBuffer outbuf,\n                                      int stride, Rect r)\n  {\n    int x, y, c;\n    byte[] prevRow = new byte[TIGHT_MAX_WIDTH*3];\n    byte[] thisRow = new byte[TIGHT_MAX_WIDTH*3];\n    ByteBuffer pix = ByteBuffer.allocate(3);\n    int[] est = new int[3];\n\n    // Set up shortcut variables\n    int rectHeight = r.height();\n    int rectWidth = r.width();\n\n    for (y = 0; y < rectHeight; y++) {\n      for (x = 0; x < rectWidth; x++) {\n        /* First pixel in a row */\n        if (x == 0) {\n          for (c = 0; c < 3; c++) {\n            pix.put(c, (byte)(inbuf.get(y*rectWidth*3+c) + prevRow[c]));\n            thisRow[c] = pix.get(c);\n          }\n          pf.bufferFromRGB((ByteBuffer)outbuf.duplicate().position(y*stride), pix, 1);\n          continue;\n        }\n\n        for (c = 0; c < 3; c++) {\n          est[c] = prevRow[x*3+c] + pix.get(c) - prevRow[(x-1)*3+c];\n          if (est[c] > 0xff) {\n            est[c] = 0xff;\n          } else if (est[c] < 0) {\n            est[c] = 0;\n          }\n          pix.put(c, (byte)(inbuf.get((y*rectWidth+x)*3+c) + est[c]));\n          thisRow[x*3+c] = pix.get(c);\n        }\n        pf.bufferFromRGB((ByteBuffer)outbuf.duplicate().position(y*stride+x), pix, 1);\n      }\n\n      System.arraycopy(thisRow, 0, prevRow, 0, prevRow.length);\n    }\n  }\n\n  final private void FilterGradient(ByteBuffer inbuf,\n                                    PixelFormat pf, ByteBuffer outbuf,\n                                    int stride, Rect r)\n  {\n    int x, y, c;\n    byte[] prevRow = new byte[TIGHT_MAX_WIDTH*3];\n    byte[] thisRow = new byte[TIGHT_MAX_WIDTH*3];\n    ByteBuffer pix = ByteBuffer.allocate(3);\n    int[] est = new int[3];\n\n    // Set up shortcut variables\n    int rectHeight = r.height();\n    int rectWidth = r.width();\n\n    for (y = 0; y < rectHeight; y++) {\n      for (x = 0; x < rectWidth; x++) {\n        /* First pixel in a row */\n        if (x == 0) {\n          pf.rgbFromBuffer(pix.duplicate(), (ByteBuffer)inbuf.position(y*rectWidth), 1);\n          for (c = 0; c < 3; c++)\n            pix.put(c, (byte)(pix.get(c) + prevRow[c]));\n\n          System.arraycopy(pix.array(), 0, thisRow, 0, pix.capacity());\n          pf.bufferFromRGB((ByteBuffer)outbuf.duplicate().position(y*stride), pix, 1);\n          continue;\n        }\n\n        for (c = 0; c < 3; c++) {\n          est[c] = prevRow[x*3+c] + pix.get(c) - prevRow[(x-1)*3+c];\n          if (est[c] > 0xff) {\n            est[c] = 0xff;\n          } else if (est[c] < 0) {\n            est[c] = 0;\n          }\n        }\n\n        pf.rgbFromBuffer(pix.duplicate(), (ByteBuffer)inbuf.position(y*rectWidth+x), 1);\n        for (c = 0; c < 3; c++)\n          pix.put(c, (byte)(pix.get(c) + est[c]));\n\n        System.arraycopy(pix.array(), 0, thisRow, x*3, pix.capacity());\n\n        pf.bufferFromRGB((ByteBuffer)outbuf.duplicate().position(y*stride+x), pix, 1);\n      }\n\n      System.arraycopy(thisRow, 0, prevRow, 0, prevRow.length);\n    }\n  }\n\n  private void FilterPalette8(ByteBuffer palette, int palSize,\n                              ByteBuffer inbuf, ByteBuffer outbuf,\n                              int stride, Rect r)\n  {\n    // Indexed color\n    int x, h = r.height(), w = r.width(), b, pad = stride - w;\n    ByteBuffer ptr = outbuf.duplicate();\n    byte bits;\n    ByteBuffer srcPtr = inbuf.duplicate();\n    if (palSize <= 2) {\n      // 2-color palette\n      while (h > 0) {\n        for (x = 0; x < w / 8; x++) {\n          bits = srcPtr.get();\n          for (b = 7; b >= 0; b--) {\n            ptr.put(palette.get(bits >> b & 1));\n          }\n        }\n        if (w % 8 != 0) {\n          bits = srcPtr.get();\n          for (b = 7; b >= 8 - w % 8; b--) {\n            ptr.put(palette.get(bits >> b & 1));\n          }\n        }\n        ptr.position(ptr.position() + pad);\n        h--;\n      }\n    } else {\n      // 256-color palette\n      while (h > 0) {\n        int endOfRow = ptr.position() + w;\n        while (ptr.position() < endOfRow) {\n          ptr.put(palette.get(srcPtr.get()));\n        }\n        ptr.position(ptr.position() + pad);\n        h--;\n      }\n    }\n  }\n\n  private void FilterPalette16(ShortBuffer palette, int palSize,\n                               ByteBuffer inbuf, ShortBuffer outbuf,\n                               int stride, Rect r)\n  {\n    // Indexed color\n    int x, h = r.height(), w = r.width(), b, pad = stride - w;\n    ShortBuffer ptr = outbuf.duplicate();\n    byte bits;\n    ByteBuffer srcPtr = inbuf.duplicate();\n    if (palSize <= 2) {\n      // 2-color palette\n      while (h > 0) {\n        for (x = 0; x < w / 8; x++) {\n          bits = srcPtr.get();\n          for (b = 7; b >= 0; b--) {\n            ptr.put(palette.get(bits >> b & 1));\n          }\n        }\n        if (w % 8 != 0) {\n          bits = srcPtr.get();\n          for (b = 7; b >= 8 - w % 8; b--) {\n            ptr.put(palette.get(bits >> b & 1));\n          }\n        }\n        ptr.position(ptr.position() + pad);\n        h--;\n      }\n    } else {\n      // 256-color palette\n      while (h > 0) {\n        int endOfRow = ptr.position() + w;\n        while (ptr.position() < endOfRow) {\n          ptr.put(palette.get(srcPtr.get()));\n        }\n        ptr.position(ptr.position() + pad);\n        h--;\n      }\n    }\n  }\n\n  private void FilterPalette32(IntBuffer palette, int palSize,\n                               ByteBuffer inbuf, IntBuffer outbuf,\n                               int stride, Rect r)\n  {\n    // Indexed color\n    int x, h = r.height(), w = r.width(), b, pad = stride - w;\n    IntBuffer ptr = outbuf.duplicate();\n    byte bits;\n    ByteBuffer srcPtr = inbuf.duplicate();\n    if (palSize <= 2) {\n      // 2-color palette\n      while (h > 0) {\n        for (x = 0; x < w / 8; x++) {\n          bits = srcPtr.get();\n          for (b = 7; b >= 0; b--) {\n            ptr.put(palette.get(bits >> b & 1));\n          }\n        }\n        if (w % 8 != 0) {\n          bits = srcPtr.get();\n          for (b = 7; b >= 8 - w % 8; b--) {\n            ptr.put(palette.get(bits >> b & 1));\n          }\n        }\n        ptr.position(ptr.position() + pad);\n        h--;\n      }\n    } else {\n      // 256-color palette\n      while (h > 0) {\n        int endOfRow = ptr.position() + w;\n        while (ptr.position() < endOfRow) {\n          ptr.put(palette.get(srcPtr.get() & 0xff));\n        }\n        ptr.position(ptr.position() + pad);\n        h--;\n      }\n    }\n  }\n\n  public final int readCompact(InStream is) {\n    byte b;\n    int result;\n\n    b = (byte)is.readU8();\n    result = (int)b & 0x7F;\n    if ((b & 0x80) != 0) {\n      b = (byte)is.readU8();\n      result |= ((int)b & 0x7F) << 7;\n      if ((b & 0x80) != 0) {\n        b = (byte)is.readU8();\n        result |= ((int)b & 0xFF) << 14;\n      }\n    }\n    return result;\n  }\n\n  private ZlibInStream[] zis;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/UserMsgBox.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n// getUserPasswd() gets the username and password.  This might involve a\n// dialog, getpass(), etc.  The user buffer pointer can be null, in which case\n// no user name will be retrieved.\n\npackage com.tigervnc.rfb;\n\npublic interface UserMsgBox {\n  public boolean showMsgBox(int flags,String title, String text);\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/UserPasswdGetter.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n// getUserPasswd() gets the username and password.  This might involve a\n// dialog, getpass(), etc.  The user buffer pointer can be null, in which case\n// no user name will be retrieved.\n\npackage com.tigervnc.rfb;\n\npublic interface UserPasswdGetter {\n  public void getUserPasswd(boolean secure, StringBuffer user, StringBuffer password);\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/VncAuth.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class VncAuth {\n\n  public static final int ok = 0;\n  public static final int failed = 1;\n  public static final int tooMany = 2; // deprecated\n\n  public static final int challengeSize = 16;\n\n  public static void encryptChallenge(byte[] challenge, String passwd) {\n    byte[] key = new byte[8];\n    for (int i = 0; i < 8 && i < passwd.length(); i++) {\n      key[i] = (byte)passwd.charAt(i);\n    }\n\n    DesCipher des = new DesCipher(key);\n\n    for (int j = 0; j < challengeSize; j += 8)\n      des.encrypt(challenge,j,challenge,j);\n  }\n\n  void obfuscatePasswd(String passwd, byte[] obfuscated) {\n    for (int i = 0; i < 8; i++) {\n      if (i < passwd.length())\n        obfuscated[i] = (byte)passwd.charAt(i);\n      else\n        obfuscated[i] = 0;\n    }\n    DesCipher des = new DesCipher(obfuscationKey);\n    des.encrypt(obfuscated,0,obfuscated,0);\n  }\n\n  public static String unobfuscatePasswd(byte[] obfuscated) {\n    DesCipher des = new DesCipher(obfuscationKey);\n    des.decrypt(obfuscated,0,obfuscated,0);\n    int len;\n    for (len = 0; len < 8; len++) {\n      if (obfuscated[len] == 0) break;\n    }\n    char[] plain = new char[len];\n    for (int i = 0; i < len; i++) {\n      plain[i] = (char)obfuscated[i];\n    }\n    return new String(plain);\n  }\n\n  static byte[] obfuscationKey = {23,82,107,6,35,78,88,7};\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/VoidParameter.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2004-2005 Cendio AB.\n * Copyright 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nabstract public class VoidParameter {\n  public VoidParameter(String name_, String desc_,\n                       Configuration.ConfigurationObject co)\n  {\n    immutable = false; _hasBeenSet = false; name = name_; description = desc_;\n\n    Configuration conf = null;\n\n    switch (co) {\n    case ConfGlobal:\n      conf = Configuration.global();\n      break;\n    case ConfServer:\n      conf = Configuration.server();\n      break;\n    case ConfViewer:\n      conf = Configuration.viewer();\n      break;\n    }\n    _next = conf.head;\n    conf.head = this;\n  }\n\n  public VoidParameter(String name_, String desc_) {\n    this(name_, desc_, Configuration.ConfigurationObject.ConfGlobal);\n  }\n\n  final public String getName() {\n    return name;\n  }\n\n  final public String getDescription() {\n    return description;\n  }\n\n  abstract public boolean setParam(String value);\n  public boolean setParam() { return false; }\n  abstract public String getDefaultStr();\n  abstract public String getValueStr();\n  public boolean isBool() { return false; }\n  public void setImmutable() {\n    vlog.debug(\"Set immutable \"+getName());\n    immutable = true;\n  }\n\n  public void setHasBeenSet() {\n    _hasBeenSet = true;\n  }\n\n  public boolean hasBeenSet() {\n    return _hasBeenSet;\n  }\n\n  protected String name;\n  protected String description;\n  public VoidParameter _next;\n  protected boolean immutable;\n  protected boolean _hasBeenSet;\n  static LogWriter vlog = new LogWriter(\"VoidParameter\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/ZRLEDecoder.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\nimport java.awt.image.*;\nimport java.nio.*;\nimport java.util.*;\n\nimport com.tigervnc.rdr.*;\n\npublic class ZRLEDecoder extends Decoder {\n\n  private static ByteBuffer readOpaque24A(InStream is)\n  {\n    is.check(3);\n    ByteBuffer r = ByteBuffer.allocate(4);\n    r.put(0, (byte)is.readU8());\n    r.put(1, (byte)is.readU8());\n    r.put(2, (byte)is.readU8());\n    return r;\n  }\n\n  private static ByteBuffer readOpaque24B(InStream is)\n  {\n    is.check(3);\n    ByteBuffer r = ByteBuffer.allocate(4);\n    r.put(1, (byte)is.readU8());\n    r.put(2, (byte)is.readU8());\n    r.put(3, (byte)is.readU8());\n    return r;\n  }\n\n  public ZRLEDecoder() {\n    super(DecoderFlags.DecoderOrdered);\n    zis = new ZlibInStream();\n  }\n\n  public void readRect(Rect r, InStream is,\n                      ServerParams server, OutStream os)\n  {\n    int len;\n\n    len = is.readU32();\n    os.writeU32(len);\n    os.copyBytes(is, len);\n  }\n\n  public void decodeRect(Rect r, Object buffer,\n                         int buflen, ServerParams server,\n                         ModifiablePixelBuffer pb)\n  {\n    MemInStream is = new MemInStream((byte[])buffer, 0, buflen);\n    PixelFormat pf = server.pf();\n    switch (pf.bpp) {\n    case 8:  zrleDecode8(r, is, zis, pf, pb); break;\n    case 16: zrleDecode16(r, is, zis, pf, pb); break;\n    case 32:\n      {\n        if (pf.depth <= 24) {\n          int maxPixel = pf.pixelFromRGB(-1, -1, -1, pf.getColorModel());\n          boolean fitsInLS3Bytes = maxPixel < (1<<24);\n          boolean fitsInMS3Bytes = (maxPixel & 0xff) == 0;\n\n          if ((fitsInLS3Bytes && pf.isLittleEndian()) ||\n              (fitsInMS3Bytes && pf.isBigEndian()))\n          {\n            zrleDecode24A(r, is, zis, pf, pb);\n            break;\n          }\n\n          if ((fitsInLS3Bytes && pf.isBigEndian()) ||\n              (fitsInMS3Bytes && pf.isLittleEndian()))\n          {\n            zrleDecode24B(r, is, zis, pf, pb);\n            break;\n          }\n        }\n\n        zrleDecode32(r, is, zis, pf, pb);\n        break;\n      }\n    }\n  }\n\n  private static enum PIXEL_T { U8, U16, U24A, U24B, U32 };\n\n  private static ByteBuffer READ_PIXEL(InStream is, PIXEL_T type) {\n    switch (type) {\n    case U8:\n      return ByteBuffer.allocate(1).put(0, (byte)is.readOpaque8());\n    case U16:\n      return ByteBuffer.allocate(2).putShort(0, (short)is.readOpaque16());\n    case U24A:\n      return readOpaque24A(is);\n    case U24B:\n      return readOpaque24B(is);\n    default:\n      return ByteBuffer.allocate(4).putInt(0, is.readOpaque32());\n    }\n  }\n\n  private void zrleDecode8(Rect r, InStream is,\n                           ZlibInStream zis,\n                           PixelFormat pf, ModifiablePixelBuffer pb)\n  {\n    ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U8);\n  }\n\n  private void zrleDecode16(Rect r, InStream is,\n                            ZlibInStream zis,\n                            PixelFormat pf, ModifiablePixelBuffer pb)\n  {\n    ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U16);\n  }\n\n  private void zrleDecode24A(Rect r, InStream is,\n                             ZlibInStream zis,\n                             PixelFormat pf, ModifiablePixelBuffer pb)\n  {\n    ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U24A);\n  }\n\n  private void zrleDecode24B(Rect r, InStream is,\n                             ZlibInStream zis,\n                             PixelFormat pf, ModifiablePixelBuffer pb)\n  {\n    ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U24B);\n  }\n\n  private void zrleDecode32(Rect r, InStream is,\n                            ZlibInStream zis,\n                            PixelFormat pf, ModifiablePixelBuffer pb)\n  {\n    ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U32);\n  }\n\n  private void ZRLE_DECODE(Rect r, InStream is,\n                           ZlibInStream zis,\n                           PixelFormat pf, ModifiablePixelBuffer pb,\n                           PIXEL_T pix_t)\n  {\n    int length = is.readU32();\n    zis.setUnderlying(is, length);\n    Rect t = new Rect();\n    ByteBuffer buf = ByteBuffer.allocate(64 * 64 * pf.bpp/8);\n\n    for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) {\n\n      t.br.y = Math.min(r.br.y, t.tl.y + 64);\n\n      for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) {\n\n        t.br.x = Math.min(r.br.x, t.tl.x + 64);\n\n        int mode = zis.readU8();\n        boolean rle = (mode & 128) != 0;\n        int palSize = mode & 127;\n        ByteBuffer palette = ByteBuffer.allocate(128 * pf.bpp/8);\n\n        for (int i = 0; i < palSize; i++) {\n          palette.put(READ_PIXEL(zis, pix_t));\n        }\n        palette.flip();\n\n        if (palSize == 1) {\n          byte[] pix = new byte[pf.bpp/8];\n          palette.get(pix);\n          pb.fillRect(pf, t, pix);\n          continue;\n        }\n\n        if (!rle) {\n          if (palSize == 0) {\n\n            // raw\n            switch (pix_t) {\n            case U24A:\n            case U24B:\n              ByteBuffer ptr = buf.duplicate();\n              for (int i=0; i < t.area(); i++) {\n                ptr.put(READ_PIXEL(zis, pix_t));\n              }\n              break;\n            default:\n              zis.readBytes(buf.duplicate(), t.area() * (pf.bpp/8));\n            }\n\n          } else {\n\n            // packed pixels\n            int bppp = ((palSize > 16) ? 8 :\n                        ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1)));\n\n            ByteBuffer ptr = buf.duplicate();\n\n            for (int i = 0; i < t.height(); i++) {\n              int eol = ptr.position() + t.width()*pf.bpp/8;\n              int b = 0;\n              int nbits = 0;\n\n              while (ptr.position() < eol) {\n                if (nbits == 0) {\n                  b = zis.readU8();\n                  nbits = 8;\n                }\n                nbits -= bppp;\n                int index = (b >> nbits) & ((1 << bppp) - 1) & 127;\n                ptr.put(palette.array(), index*pf.bpp/8, pf.bpp/8);\n              }\n            }\n          }\n\n        } else {\n\n          if (palSize == 0) {\n\n            // plain RLE\n\n            ByteBuffer ptr = buf.duplicate();\n            int end = ptr.position() + t.area()*pf.bpp/8;\n            while (ptr.position() < end) {\n              ByteBuffer pix = READ_PIXEL(zis, pix_t);\n              int len = 1;\n              int b;\n              do {\n                b = zis.readU8();\n                len += b;\n              } while (b == 255);\n\n              if (end - ptr.position() < len*pf.bpp/8) {\n                System.err.println(\"ZRLE decode error\\n\");\n                throw new Exception(\"ZRLE decode error\");\n              }\n\n              while (len-- > 0) ptr.put(pix.array());\n\n            }\n          } else {\n\n            // palette RLE\n\n            ByteBuffer ptr = buf.duplicate();\n            int end = ptr.position() + t.area()*pf.bpp/8;\n            while (ptr.position() < end) {\n              int index = zis.readU8();\n              int len = 1;\n              if ((index & 128) != 0) {\n                int b;\n                do {\n                  b = zis.readU8();\n                  len += b;\n                } while (b == 255);\n\n                if (end - ptr.position() < len*pf.bpp/8) {\n                  System.err.println(\"ZRLE decode error\\n\");\n                  throw new Exception(\"ZRLE decode error\");\n                }\n              }\n\n              index &= 127;\n\n              ByteBuffer pix = ByteBuffer.allocate(pf.bpp/8);\n              pix.put(palette.array(), index*pf.bpp/8, pf.bpp/8);\n\n              while (len-- > 0) ptr.put(pix.array());\n            }\n          }\n        }\n\n        pb.imageRect(pf, t, buf.array());\n      }\n    }\n\n    zis.flushUnderlying();\n    zis.setUnderlying(null, 0);\n  }\n\n  private ZlibInStream zis;\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/fenceTypes.java",
    "content": "/* Copyright 2011 Pierre Ossman for Cendio AB\n * Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\npackage com.tigervnc.rfb;\n\npublic class fenceTypes {\n  public static final int fenceFlagBlockBefore = 1<<0;\n  public static final int fenceFlagBlockAfter  = 1<<1;\n  public static final int fenceFlagSyncNext    = 1<<2;\n\n  public static final int fenceFlagRequest     = 1<<31;\n\n  public static final int fenceFlagsSupported  = (fenceFlagBlockBefore |\n                                                  fenceFlagBlockAfter |\n                                                  fenceFlagSyncNext |\n                                                  fenceFlagRequest);\n}\n"
  },
  {
    "path": "java/com/tigervnc/rfb/screenTypes.java",
    "content": "/* Copyright 2009 Pierre Ossman for Cendio AB\n * Copyright (C) 2011 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.rfb;\n\npublic class screenTypes {\n\n  // Reasons\n  public static final int reasonServer = 0;\n  public static final int reasonClient = 1;\n  public static final int reasonOtherClient = 2;\n\n  // Result codes\n  public static final int resultSuccess = 0;\n  public static final int resultProhibited = 1;\n  public static final int resultNoResources = 2;\n  public static final int resultInvalid = 3;\n\n  public static final int resultUnsolicited = 0xffff; // internal code used for server changes\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/CConn.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2013 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * Copyright (C) 2011-2013 D. R. Commander.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// CConn\n//\n// Methods on CConn are called from both the GUI thread and the thread which\n// processes incoming RFB messages (\"the RFB thread\").  This means we need to\n// be careful with synchronization here.\n//\n// Any access to writer() must not only be synchronized, but we must also make\n// sure that the connection is in RFBSTATE_NORMAL.  We are guaranteed this for\n// any code called after serverInit() has been called.  Since the DesktopWindow\n// isn't created until then, any methods called only from DesktopWindow can\n// assume that we are in RFBSTATE_NORMAL.\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.datatransfer.StringSelection;\nimport java.awt.event.*;\nimport java.awt.Toolkit;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.util.jar.Attributes;\nimport java.util.jar.Manifest;\nimport javax.swing.*;\nimport javax.swing.ImageIcon;\nimport java.net.InetSocketAddress;\nimport java.net.SocketException;\nimport java.util.*;\nimport java.util.prefs.*;\n\nimport com.tigervnc.rdr.*;\nimport com.tigervnc.rfb.*;\nimport com.tigervnc.rfb.Point;\nimport com.tigervnc.rfb.Exception;\nimport com.tigervnc.network.Socket;\nimport com.tigervnc.network.TcpSocket;\n\nimport static com.tigervnc.vncviewer.Parameters.*;\n\npublic class CConn extends CConnection implements \n  FdInStreamBlockCallback, ActionListener {\n\n  // 8 colours (1 bit per component)\n  static final PixelFormat verylowColorPF =\n    new PixelFormat(8, 3, false, true, 1, 1, 1, 2, 1, 0);\n\n  // 64 colours (2 bits per component)\n  static final PixelFormat lowColorPF =\n    new PixelFormat(8, 6, false, true, 3, 3, 3, 4, 2, 0);\n\n  // 256 colours (2-3 bits per component)\n  static final PixelFormat mediumColorPF =\n    new PixelFormat(8, 8, false, true, 7, 7, 3, 5, 2, 0);\n\n  ////////////////////////////////////////////////////////////////////\n  // The following methods are all called from the RFB thread\n\n  public CConn(String vncServerName, Socket socket)\n  {\n    serverHost = null; serverPort = 0; desktop = null;\n    updateCount = 0; pixelCount = 0;\n    lastServerEncoding = -1;\n\n    setShared(shared.getValue());\n    sock = socket;\n\n    server.supportsLocalCursor = true;\n    server.supportsDesktopResize = true;\n    server.supportsClientRedirect = true;\n\n    if (customCompressLevel.getValue())\n      setCompressLevel(compressLevel.getValue());\n\n    if (!noJpeg.getValue())\n      setQualityLevel(qualityLevel.getValue());\n\n    if (sock == null) {\n      setServerName(Hostname.getHost(vncServerName));\n      setServerPort(Hostname.getPort(vncServerName));\n      try {\n        if (tunnel.getValue() || !via.getValue().isEmpty()) {\n          int localPort = TcpSocket.findFreeTcpPort();\n          if (localPort == 0)\n            throw new Exception(\"Could not obtain free TCP port\");\n          String gatewayHost = Tunnel.getSshHost();\n          if (gatewayHost.isEmpty())\n            gatewayHost = getServerName();\n          Tunnel.createTunnel(gatewayHost, getServerName(),\n                              getServerPort(), localPort);\n          sock = new TcpSocket(\"localhost\", localPort);\n          vlog.info(\"Connected to localhost port \"+localPort);\n        } else {\n          sock = new TcpSocket(getServerName(), getServerPort());\n          vlog.info(\"Connected to host \"+getServerName()+\" port \"+getServerPort());\n        }\n      } catch (java.lang.Exception e) {\n        throw new Exception(e.getMessage());\n      }\n    } else {\n      String name = sock.getPeerEndpoint();\n      if (listenMode.getValue())\n        vlog.info(\"Accepted connection from \" + name);\n      else\n        vlog.info(\"Connected to host \"+Hostname.getHost(name)+\" port \"+Hostname.getPort(name));\n    }\n\n    // See callback below\n    sock.inStream().setBlockCallback(this);\n\n    setStreams(sock.inStream(), sock.outStream());\n\n    initialiseProtocol();\n\n    OptionsDialog.addCallback(\"handleOptions\", this);\n  }\n\n  public String connectionInfo() {\n    String info = new String(\"Desktop name: %s%n\"+\n                             \"Host: %s:%d%n\"+\n                             \"Size: %dx%d%n\"+\n                             \"Pixel format: %s%n\"+\n                             \"  (server default: %s)%n\"+\n                             \"Requested encoding: %s%n\"+\n                             \"Last used encoding: %s%n\"+\n                             \"Line speed estimate: %d kbit/s%n\"+\n                             \"Protocol version: %d.%d%n\"+\n                             \"Security method: %s [%s]%n\");\n    String infoText =\n      String.format(info, server.name(),\n                    sock.getPeerName(), sock.getPeerPort(),\n                    server.width(), server.height(),\n                    server.pf().print(),\n                    serverPF.print(),\n                    Encodings.encodingName(getPreferredEncoding()),\n                    Encodings.encodingName(lastServerEncoding),\n                    sock.inStream().kbitsPerSecond(),\n                    server.majorVersion, server.minorVersion,\n                    Security.secTypeName(csecurity.getType()),\n                    csecurity.description());\n\n    return infoText;\n  }\n\n  public int getUpdateCount()\n  {\n    return updateCount;\n  }\n\n  public int getPixelCount()\n  {\n    return pixelCount;\n  }\n\n  // The RFB core is not properly asynchronous, so it calls this callback\n  // whenever it needs to block to wait for more data. Since FLTK is\n  // monitoring the socket, we just make sure FLTK gets to run.\n\n  public void blockCallback() {\n    try {\n      synchronized(this) {\n        wait(1);\n      }\n    } catch (java.lang.InterruptedException e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n\n  ////////////////////// CConnection callback methods //////////////////////\n\n  // serverInit() is called when the serverInit message has been received.  At\n  // this point we create the desktop window and display it.  We also tell the\n  // server the pixel format and encodings to use and request the first update.\n  public void initDone()\n  {\n    // If using AutoSelect with old servers, start in FullColor\n    // mode. See comment in autoSelectFormatAndEncoding.\n    if (server.beforeVersion(3, 8) && autoSelect.getValue())\n      fullColor.setParam(true);\n\n    serverPF = server.pf();\n\n    desktop = new DesktopWindow(server.width(), server.height(),\n                                server.name(), serverPF, this);\n    fullColorPF = desktop.getPreferredPF();\n\n    // Force a switch to the format and encoding we'd like\n    updatePixelFormat();\n    int encNum = Encodings.encodingNum(preferredEncoding.getValue());\n    if (encNum != -1)\n      setPreferredEncoding(encNum);\n  }\n\n  // setDesktopSize() is called when the desktop size changes (including when\n  // it is set initially).\n  public void setDesktopSize(int w, int h)\n  {\n    super.setDesktopSize(w, h);\n    resizeFramebuffer();\n  }\n\n  // setExtendedDesktopSize() is a more advanced version of setDesktopSize()\n  public void setExtendedDesktopSize(int reason, int result,\n                                     int w, int h, ScreenSet layout)\n  {\n    super.setExtendedDesktopSize(reason, result, w, h, layout);\n\n    if ((reason == screenTypes.reasonClient) &&\n        (result != screenTypes.resultSuccess)) {\n      vlog.error(\"SetDesktopSize failed: \" + result);\n      return;\n    }\n\n    resizeFramebuffer();\n  }\n\n  // clientRedirect() migrates the client to another host/port\n  public void clientRedirect(int port, String host, String x509subject)\n  {\n    try {\n      sock.close();\n      sock = new TcpSocket(host, port);\n      vlog.info(\"Redirected to \"+host+\":\"+port);\n      setServerName(host);\n      setServerPort(port);\n      sock.inStream().setBlockCallback(this);\n      setStreams(sock.inStream(), sock.outStream());\n      if (desktop != null)\n        desktop.dispose();\n      initialiseProtocol();\n    } catch (java.lang.Exception e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n\n  // setName() is called when the desktop name changes\n  public void setName(String name)\n  {\n    super.setName(name);\n    if (desktop != null)\n      desktop.setName(name);\n  }\n\n  // framebufferUpdateStart() is called at the beginning of an update.\n  // Here we try to send out a new framebuffer update request so that the\n  // next update can be sent out in parallel with us decoding the current\n  // one.\n  public void framebufferUpdateStart()\n  {\n\n    super.framebufferUpdateStart();\n\n  }\n\n  // framebufferUpdateEnd() is called at the end of an update.\n  // For each rectangle, the FdInStream will have timed the speed\n  // of the connection, allowing us to select format and encoding\n  // appropriately, and then request another incremental update.\n  public void framebufferUpdateEnd()\n  {\n    super.framebufferUpdateEnd();\n\n    updateCount++;\n\n    desktop.updateWindow();\n\n    // Compute new settings based on updated bandwidth values\n    if (autoSelect.getValue())\n      autoSelectFormatAndEncoding();\n  }\n\n  // The rest of the callbacks are fairly self-explanatory...\n\n  public void setColourMapEntries(int firstColor, int nColors, int[] rgbs)\n  {\n    vlog.error(\"Invalid SetColourMapEntries from server!\");\n  }\n\n  public void bell()\n  {\n    if (acceptBell.getValue())\n      desktop.getToolkit().beep();\n  }\n\n  public void serverCutText(String str, int len)\n  {\n    StringSelection buffer;\n\n    if (!acceptClipboard.getValue())\n      return;\n\n    ClipboardDialog.serverCutText(str);\n  }\n\n  public void dataRect(Rect r, int encoding)\n  {\n    sock.inStream().startTiming();\n\n    if (encoding != Encodings.encodingCopyRect)\n      lastServerEncoding = encoding;\n\n    super.dataRect(r, encoding);\n\n    sock.inStream().stopTiming();\n\n    pixelCount += r.area();\n  }\n\n  public void setCursor(int width, int height, Point hotspot,\n                        byte[] data)\n  {\n    desktop.setCursor(width, height, hotspot, data);\n  }\n\n  public void fence(int flags, int len, byte[] data)\n  {\n    // can't call super.super.fence(flags, len, data);\n    server.supportsFence = true;\n\n    if ((flags & fenceTypes.fenceFlagRequest) != 0) {\n      // We handle everything synchronously so we trivially honor these modes\n      flags = flags & (fenceTypes.fenceFlagBlockBefore | fenceTypes.fenceFlagBlockAfter);\n\n      writer().writeFence(flags, len, data);\n      return;\n    }\n  }\n\n  ////////////////////// Internal methods //////////////////////\n  public void resizeFramebuffer()\n  {\n    if (desktop == null)\n      return;\n\n    desktop.resizeFramebuffer(server.width(), server.height());\n  }\n\n  // autoSelectFormatAndEncoding() chooses the format and encoding appropriate\n  // to the connection speed:\n  //\n  //   First we wait for at least one second of bandwidth measurement.\n  //\n  //   Above 16Mbps (i.e. LAN), we choose the second highest JPEG quality,\n  //   which should be perceptually lossless.\n  //\n  //   If the bandwidth is below that, we choose a more lossy JPEG quality.\n  //\n  //   If the bandwidth drops below 256 Kbps, we switch to palette mode.\n  //\n  //   Note: The system here is fairly arbitrary and should be replaced\n  //         with something more intelligent at the server end.\n  //\n  private void autoSelectFormatAndEncoding()\n  {\n    long kbitsPerSecond = sock.inStream().kbitsPerSecond();\n    long timeWaited = sock.inStream().timeWaited();\n    boolean newFullColour = fullColor.getValue();\n    int newQualityLevel = qualityLevel.getValue();\n\n    // Always use Tight\n    setPreferredEncoding(Encodings.encodingTight);\n\n    // Check that we have a decent bandwidth measurement\n    if ((kbitsPerSecond == 0) || (timeWaited < 100))\n      return;\n\n    // Select appropriate quality level\n    if (!noJpeg.getValue()) {\n      if (kbitsPerSecond > 16000)\n        newQualityLevel = 8;\n      else\n        newQualityLevel = 6;\n\n      if (newQualityLevel != qualityLevel.getValue()) {\n        vlog.info(\"Throughput \"+kbitsPerSecond+\n                  \" kbit/s - changing to quality \"+newQualityLevel);\n        qualityLevel.setParam(newQualityLevel);\n        setQualityLevel(newQualityLevel);\n      }\n    }\n\n    if (server.beforeVersion(3, 8)) {\n      // Xvnc from TightVNC 1.2.9 sends out FramebufferUpdates with\n      // cursors \"asynchronously\". If this happens in the middle of a\n      // pixel format change, the server will encode the cursor with\n      // the old format, but the client will try to decode it\n      // according to the new format. This will lead to a\n      // crash. Therefore, we do not allow automatic format change for\n      // old servers.\n      return;\n    }\n\n    // Select best color level\n    newFullColour = (kbitsPerSecond > 256);\n    if (newFullColour != fullColor.getValue()) {\n      if (newFullColour)\n        vlog.info(\"Throughput \"+kbitsPerSecond+ \" kbit/s - full color is now enabled\");\n      else\n        vlog.info(\"Throughput \"+kbitsPerSecond+ \" kbit/s - full color is now disabled\");\n      fullColor.setParam(newFullColour);\n      updatePixelFormat();\n    }\n  }\n\n  // updatePixelFormat() requests an update from the server, having set the\n  // format and encoding appropriately.\n  private void updatePixelFormat()\n  {\n    PixelFormat pf;\n\n    if (fullColor.getValue()) {\n      pf = fullColorPF;\n    } else {\n      if (lowColorLevel.getValue() == 0) {\n        pf = verylowColorPF;\n      } else if (lowColorLevel.getValue() == 1) {\n        pf = lowColorPF;\n      } else {\n        pf = mediumColorPF;\n      }\n    }\n\n    String str = pf.print();\n    vlog.info(\"Using pixel format \" + str);\n    setPF(pf);\n  }\n\n  public void handleOptions()\n  {\n\n    // Checking all the details of the current set of encodings is just\n    // a pain. Assume something has changed, as resending the encoding\n    // list is cheap. Avoid overriding what the auto logic has selected\n    // though.\n    if (!autoSelect.getValue()) {\n      int encNum = Encodings.encodingNum(preferredEncoding.getValue());\n\n      if (encNum != -1)\n        this.setPreferredEncoding(encNum);\n    }\n\n    if (customCompressLevel.getValue())\n      this.setCompressLevel(compressLevel.getValue());\n    else\n      this.setCompressLevel(-1);\n\n    if (!noJpeg.getValue() && !autoSelect.getValue())\n      this.setQualityLevel(qualityLevel.getValue());\n    else\n      this.setQualityLevel(-1);\n\n    this.updatePixelFormat();\n  }\n\n  ////////////////////////////////////////////////////////////////////\n  // The following methods are all called from the GUI thread\n\n  // close() shuts down the socket, thus waking up the RFB thread.\n  public void close() {\n    if (closeListener != null) {\n      JFrame f =\n        (JFrame)SwingUtilities.getAncestorOfClass(JFrame.class, desktop);\n      if (f != null)\n        f.dispatchEvent(new WindowEvent(f, WindowEvent.WINDOW_CLOSING));\n    }\n    shuttingDown = true;\n    try {\n      if (sock != null)\n        sock.shutdown();\n    } catch (java.lang.Exception e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n\n  // writeClientCutText() is called from the clipboard dialog\n  public void writeClientCutText(String str, int len) {\n    if ((state() != stateEnum.RFBSTATE_NORMAL) || shuttingDown)\n      return;\n    writer().writeClientCutText(str, len);\n  }\n\n  public void actionPerformed(ActionEvent e) {}\n\n  public Socket getSocket() {\n    return sock;\n  }\n\n  ////////////////////////////////////////////////////////////////////\n  // The following methods are called from both RFB and GUI threads\n\n  // the following never change so need no synchronization:\n\n  // access to desktop by different threads is specified in DesktopWindow\n\n  // the following need no synchronization:\n\n  // shuttingDown is set by the GUI thread and only ever tested by the RFB\n  // thread after the window has been destroyed.\n  boolean shuttingDown = false;\n\n  // reading and writing int and boolean is atomic in java, so no\n  // synchronization of the following flags is needed:\n\n\n  // All menu, options, about and info stuff is done in the GUI thread (apart\n  // from when constructed).\n\n  // the following are only ever accessed by the GUI thread:\n  private String serverHost;\n  private int serverPort;\n  private Socket sock;\n\n  protected DesktopWindow desktop;\n\n  private int updateCount;\n  private int pixelCount;\n\n  private PixelFormat serverPF;\n  private PixelFormat fullColorPF;\n\n  private int lastServerEncoding;\n\n  public ActionListener closeListener = null;\n\n  static LogWriter vlog = new LogWriter(\"CConn\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/ClipboardDialog.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2014 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.event.*;\nimport java.awt.datatransfer.*;\nimport java.io.*;\nimport java.nio.*;\nimport javax.swing.*;\nimport javax.swing.border.*;\nimport javax.swing.event.*;\nimport javax.swing.text.*;\n\nimport com.tigervnc.rfb.LogWriter;\n\nimport static com.tigervnc.vncviewer.Parameters.*;\n\nclass ClipboardDialog extends Dialog {\n\n  protected static class MyJTextArea extends JTextArea {\n\n\t  private class VncTransferHandler extends TransferHandler {\n\t    // Custom TransferHandler designed to limit the size of outbound\n\t    // clipboard transfers to VncViewer.maxCutText.getValue() bytes.\n\t    private LogWriter vlog = new LogWriter(\"VncTransferHandler\");\n      private long start;\n\n\t    public void exportToClipboard(JComponent comp, Clipboard clip, int action)\n\t        throws IllegalStateException {\n        if (action != TransferHandler.COPY) return;\n        if (start == 0)\n          start = System.currentTimeMillis();\n\t      StringSelection selection = new StringSelection(((JTextArea)comp).getText());\n        try {\n\t        clip.setContents(selection, selection);\n        } catch(IllegalStateException e) {\n          // something else has the clipboard, keep trying for at most 50ms\n          if ((System.currentTimeMillis() - start) < 50)\n            exportToClipboard(comp, clip, action);\n          else\n            vlog.info(\"Couldn't access system clipboard for > 50ms\");\n        }\n        start = 0;\n\t    }\n\n\t    public boolean importData(JComponent c, Transferable t) {\n\t      if (canImport(c, t.getTransferDataFlavors())) {\n\t        try {\n\t          DataFlavor VncFlavor = null;\n\t          for (DataFlavor f : t.getTransferDataFlavors()) {\n\t            if (f.isMimeTypeEqual(\"text/plain\") &&\n                  f.isRepresentationClassInputStream()) {\n\t              VncFlavor = f;\n                break;\n              }\n            }\n\t          if (VncFlavor == null) return false;\n\t          CharBuffer cbuf =\n\t            CharBuffer.allocate(maxCutText.getValue());\n\t          Reader reader = (Reader)VncFlavor.getReaderForText(t);\n            int n = reader.read(cbuf.array(), 0, cbuf.length());\n\t          reader.close();\n            // reader returns -1 (EOF) for empty clipboard\n            cbuf.limit(n < 0 ? 0 : n);\n\t          if (c instanceof JTextComponent)\n              if (!cbuf.toString().equals(((JTextComponent)c).getText()))\n\t              ((JTextComponent)c).setText(cbuf.toString());\n\t          return true;\n\t        } catch (OutOfMemoryError e) {\n\t          vlog.error(\"ERROR: Too much data on local clipboard!\");\n\t        } catch (UnsupportedFlavorException e) {\n\t          // Skip import\n\t          vlog.info(e.toString());\n\t        } catch (IOException e) {\n\t          // Skip import\n\t          vlog.info(e.toString());\n\t        }\n\t      }\n\t      return false;\n\t    }\n\n\t    public boolean canImport(JComponent c, DataFlavor[] flavors) {\n\t      for (DataFlavor f : flavors)\n\t        if (f.isMimeTypeEqual(\"text/plain\") &&\n              f.isRepresentationClassReader())\n\t          return true;\n\t      return false;\n\t    }\n\t  }\n\n\t  private class MyTextListener implements DocumentListener {\n\t    public MyTextListener() { }\n\n\t    public void changedUpdate(DocumentEvent e) { } \n\n\t    public void insertUpdate(DocumentEvent e) {\n        if (!listen) return;\n\t      String text = textArea.getText();\n\t      if (sendClipboard.getValue())\n\t        VncViewer.cc.writeClientCutText(text, text.length());\n\t    }\n\n\t    public void removeUpdate(DocumentEvent e) { }\n\t  }\n\n    public MyJTextArea() {\n      super();\n      setTransferHandler(new VncTransferHandler());\n      getDocument().addDocumentListener(new MyTextListener());\n      // If the textArea can receive the focus, then text within the textArea\n      // can be selected.  On platforms that don't support separate selection\n      // and clipboard buffers, this triggers a replacement of the textAra's\n      // contents with the selected text.\n      setFocusable(false);\n      setLineWrap(false);\n      setWrapStyleWord(true);\n    }\n  }\n\n  public ClipboardDialog() {\n    super(false);\n    setTitle(\"VNC Clipboard Viewer\");\n    setPreferredSize(new Dimension(640, 480));\n    addWindowFocusListener(new WindowFocusListener() {\n      // Necessary to ensure that updates from the system clipboard\n      // are propagated to the textArea when the dialog is visible.\n      public void windowGainedFocus(WindowEvent e) {\n        clientCutText();\n      }\n      public void windowLostFocus(WindowEvent e) { }\n    });\n    JScrollPane sp = new JScrollPane(textArea);\n    getContentPane().add(sp, BorderLayout.CENTER);\n    // button panel placed below the scrollpane\n    JPanel pb = new JPanel();\n    clearButton = new JButton(\"Clear\");\n    pb.add(clearButton);\n    sendButton = new JButton(\"Send to VNC server\");\n    pb.add(sendButton);\n    cancelButton = new JButton(\"Cancel\");\n    pb.add(cancelButton);\n    getContentPane().add(\"South\", pb);\n    addListeners(this);\n    pack();\n  }\n\n  public static void showDialog(Container c) {\n    if (dialog == null)\n      dialog = new ClipboardDialog();\n    dialog.show(c);\n  }\n\n  public void show(Container c) {\n    super.showDialog(c);\n  }\n\n  public void endDialog() {\n    super.endDialog();\n    dialog.dispose();\n  }\n\n  public static void serverCutText(String str) {\n    if (textArea.getText().equals(str))\n      return;\n    // Update the text area with incoming serverCutText.  We need to diable\n    // the DocumentListener temporarily to prevent an clientCutText msg from\n    // being sent back to the server when the textArea is updated.\n    listen = false;\n    textArea.setText(str);\n    textArea.copy();\n    listen = true;\n  }\n\n  public static void clientCutText() {\n    // Update the textArea with the current contents of the system clipboard.\n    // The TransferHandler ensures that the textArea's contents are only \n    // changed when they differ from the clipboard's.  If the textArea is\n    // updated, the DocumentListener will trigger an RFB clientCutText msg.\n    textArea.paste();\n    textArea.setCaretPosition(0);\n  }\n\n  public void setSendingEnabled(boolean b) {\n    sendButton.setEnabled(b);\n  }\n\n  public void actionPerformed(ActionEvent e) {\n    Object s = e.getSource();\n    if (s instanceof JButton && (JButton)s == clearButton) {\n      serverCutText(new String(\"\"));\n    } else if (s instanceof JButton && (JButton)s == sendButton) {\n      String text = textArea.getText();\n      VncViewer.cc.writeClientCutText(text, text.length());\n      endDialog();\n    } else if (s instanceof JButton && (JButton)s == cancelButton) {\n      endDialog();\n    }\n  }\n\n  private JButton clearButton, sendButton, cancelButton;\n  private static boolean listen = true;\n  static ClipboardDialog dialog;\n  static MyJTextArea textArea = new MyJTextArea();\n  static LogWriter vlog = new LogWriter(\"ClipboardDialog\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/DesktopWindow.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n * Copyright (C) 2012-2013 D. R. Commander.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.event.*;\nimport java.lang.reflect.*;\nimport java.util.*;\nimport javax.swing.*;\nimport javax.swing.Timer;\nimport javax.swing.border.*;\n\nimport com.tigervnc.rfb.*;\nimport com.tigervnc.rfb.Point;\nimport java.lang.Exception;\n\nimport static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER;\nimport static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER;\nimport static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;\nimport static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;\nimport static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;\nimport static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;\n\nimport static com.tigervnc.vncviewer.Parameters.*;\n\npublic class DesktopWindow extends JFrame\n{\n\n  static LogWriter vlog = new LogWriter(\"DesktopWindow\");\n\n  public DesktopWindow(int w, int h, String name,\n                       PixelFormat serverPF, CConn cc_)\n  {\n    cc = cc_;\n    firstUpdate = true;\n    delayedFullscreen = false; delayedDesktopSize = false;\n\n    setFocusable(false);\n    setFocusTraversalKeysEnabled(false);\n    getToolkit().setDynamicLayout(false);\n    if (!VncViewer.os.startsWith(\"mac os x\"))\n      setIconImage(VncViewer.frameIcon);\n    UIManager.getDefaults().put(\"ScrollPane.ancestorInputMap\",\n      new UIDefaults.LazyInputMap(new Object[]{}));\n    scroll = new JScrollPane(new Viewport(w, h, serverPF, cc));\n    viewport = (Viewport)scroll.getViewport().getView();\n    scroll.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));\n    if (disableArrowScroll.getValue()) {\n      InputMap im = scroll.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);\n      if (im != null) {\n        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), \"none\");\n        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), \"none\");\n        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), \"none\");\n        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), \"none\");\n        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0), \"none\");\n        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0), \"none\");\n        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), \"none\");\n        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), \"none\");\n      }\n    }\n    getContentPane().add(scroll);\n\n    setName(name);\n\n    lastScaleFactor = scalingFactor.getValue();\n    if (VncViewer.os.startsWith(\"mac os x\"))\n      if (!noLionFS.getValue())\n        enableLionFS();\n\n    OptionsDialog.addCallback(\"handleOptions\", this);\n\n    addWindowFocusListener(new WindowAdapter() {\n      public void windowGainedFocus(WindowEvent e) {\n        if (isVisible())\n          if (scroll.getViewport() != null)\n            scroll.getViewport().getView().requestFocusInWindow();\n      }\n      public void windowLostFocus(WindowEvent e) {\n        viewport.releaseDownKeys();\n      }\n    });\n\n    addWindowListener(new WindowAdapter() {\n      public void windowClosing(WindowEvent e) {\n        cc.close();\n      }\n      public void windowDeiconified(WindowEvent e) {\n        // ViewportBorder sometimes lost when window is shaded or de-iconified\n        repositionViewport();\n      }\n    });\n\n    addWindowStateListener(new WindowAdapter() {\n      public void windowStateChanged(WindowEvent e) {\n        int state = e.getNewState();\n        if ((state & JFrame.MAXIMIZED_BOTH) != JFrame.MAXIMIZED_BOTH) {\n          Rectangle b = getGraphicsConfiguration().getBounds();\n          if (!b.contains(getLocationOnScreen()))\n            setLocation((int)b.getX(), (int)b.getY());\n        }\n        // ViewportBorder sometimes lost when restoring on Windows\n        repositionViewport();\n      }\n    });\n\n    // Window resize events\n    timer = new Timer(500, new AbstractAction() {\n      public void actionPerformed(ActionEvent e) {\n        handleResizeTimeout();\n      }\n    });\n    timer.setRepeats(false);\n    addComponentListener(new ComponentAdapter() {\n      public void componentResized(ComponentEvent e) {\n        if (remoteResize.getValue()) {\n          if (timer.isRunning())\n            timer.restart();\n          else\n            // Try to get the remote size to match our window size, provided\n            // the following conditions are true:\n            //\n            // a) The user has this feature turned on\n            // b) The server supports it\n            // c) We're not still waiting for a chance to handle DesktopSize\n            // d) We're not still waiting for startup fullscreen to kick in\n            if (!firstUpdate && !delayedFullscreen &&\n                remoteResize.getValue() && cc.server.supportsSetDesktopSize)\n              timer.start();\n        } else {\n          String scaleString = scalingFactor.getValue();\n          if (!scaleString.matches(\"^[0-9]+$\")) {\n            Dimension maxSize = getContentPane().getSize();\n            if ((maxSize.width != viewport.scaledWidth) ||\n                (maxSize.height != viewport.scaledHeight))\n              viewport.setScaledSize(maxSize.width, maxSize.height);\n            if (!scaleString.equals(\"Auto\")) {\n              if (!isMaximized() && !fullscreen_active()) {\n                int dx = getInsets().left + getInsets().right;\n                int dy = getInsets().top + getInsets().bottom;\n                setSize(viewport.scaledWidth+dx, viewport.scaledHeight+dy);\n              }\n            }\n          }\n          repositionViewport();\n        }\n      }\n    });\n\n  }\n\n  // Remove resize listener in order to prevent recursion when resizing\n  @Override\n  public void setSize(Dimension d)\n  {\n    ComponentListener[] listeners = getListeners(ComponentListener.class);\n    for (ComponentListener l : listeners)\n      removeComponentListener(l);\n    super.setSize(d);\n    for (ComponentListener l : listeners)\n      addComponentListener(l);\n  }\n\n  @Override\n  public void setSize(int width, int height)\n  {\n    ComponentListener[] listeners = getListeners(ComponentListener.class);\n    for (ComponentListener l : listeners)\n      removeComponentListener(l);\n    super.setSize(width, height);\n    for (ComponentListener l : listeners)\n      addComponentListener(l);\n  }\n\n  @Override\n  public void setBounds(Rectangle r)\n  {\n    ComponentListener[] listeners = getListeners(ComponentListener.class);\n    for (ComponentListener l : listeners)\n      removeComponentListener(l);\n    super.setBounds(r);\n    for (ComponentListener l : listeners)\n      addComponentListener(l);\n  }\n\n  private void repositionViewport()\n  {\n    scroll.revalidate();\n    Rectangle r = scroll.getViewportBorderBounds();\n    int dx = r.width - viewport.scaledWidth;\n    int dy = r.height - viewport.scaledHeight;\n    int top = (int)Math.max(Math.floor(dy/2), 0);\n    int left = (int)Math.max(Math.floor(dx/2), 0);\n    int bottom = (int)Math.max(dy - top, 0);\n    int right = (int)Math.max(dx - left, 0);\n    Insets insets = new Insets(top, left, bottom, right);\n    scroll.setViewportBorder(new MatteBorder(insets, Color.BLACK));\n    scroll.revalidate();\n  }\n\n  public PixelFormat getPreferredPF()\n  {\n    return viewport.getPreferredPF();\n  }\n\n  public void setName(String name)\n  {\n    setTitle(name);\n  }\n\n  // Copy the areas of the framebuffer that have been changed (damaged)\n  // to the displayed window.\n\n  public void updateWindow()\n  {\n    if (firstUpdate) {\n      pack();\n      if (fullScreen.getValue())\n        fullscreen_on();\n      else\n        setVisible(true);\n\n      if (maximize.getValue())\n        setExtendedState(JFrame.MAXIMIZED_BOTH);\n\n      if (cc.server.supportsSetDesktopSize && !desktopSize.getValue().equals(\"\")) {\n        // Hack: Wait until we're in the proper mode and position until\n        // resizing things, otherwise we might send the wrong thing.\n        if (delayedFullscreen)\n          delayedDesktopSize = true;\n        else\n          handleDesktopSize();\n      }\n      firstUpdate = false;\n    }\n\n    viewport.updateWindow();\n  }\n\n  public void resizeFramebuffer(int new_w, int new_h)\n  {\n    if ((new_w == viewport.scaledWidth) && (new_h == viewport.scaledHeight))\n      return;\n\n    // If we're letting the viewport match the window perfectly, then\n    // keep things that way for the new size, otherwise just keep things\n    // like they are.\n    int dx = getInsets().left + getInsets().right;\n    int dy = getInsets().top + getInsets().bottom;\n    if (!fullscreen_active()) {\n      if ((w() == viewport.scaledWidth) && (h() == viewport.scaledHeight))\n        setSize(new_w+dx, new_h+dy);\n      else {\n        // Make sure the window isn't too big. We do this manually because\n        // we have to disable the window size restriction (and it isn't\n        // entirely trustworthy to begin with).\n        if ((w() > new_w) || (h() > new_h))\n          setSize(Math.min(w(), new_w)+dx, Math.min(h(), new_h)+dy);\n      }\n    }\n\n    viewport.resize(0, 0, new_w, new_h);\n\n    // We might not resize the main window, so we need to manually call this\n    // to make sure the viewport is centered.\n    repositionViewport();\n\n    // repositionViewport() makes sure the scroll widget notices any changes\n    // in position, but it might be just the size that changes so we also\n    // need a poke here as well.\n    validate();\n  }\n\n  public void setCursor(int width, int height, Point hotspot,\n                        byte[] data)\n  {\n    viewport.setCursor(width, height, hotspot, data);\n  }\n\n  public void fullscreen_on()\n  {\n    fullScreen.setParam(true);\n    lastState = getExtendedState();\n    lastBounds = getBounds();\n    dispose();\n    // Screen bounds calculation affected by maximized window?\n    setExtendedState(JFrame.NORMAL);\n    setUndecorated(true);\n    setVisible(true);\n    setBounds(getScreenBounds());\n  }\n\n  public void fullscreen_off()\n  {\n    fullScreen.setParam(false);\n    dispose();\n    setUndecorated(false);\n    setExtendedState(lastState);\n    setBounds(lastBounds);\n    setVisible(true);\n  }\n\n  public boolean fullscreen_active()\n  {\n    return isUndecorated();\n  }\n\n  private void handleDesktopSize()\n  {\n    if (!desktopSize.getValue().equals(\"\")) {\n      int width, height;\n\n      // An explicit size has been requested\n\n      if (desktopSize.getValue().split(\"x\").length != 2)\n        return;\n\n      width = Integer.parseInt(desktopSize.getValue().split(\"x\")[0]);\n      height = Integer.parseInt(desktopSize.getValue().split(\"x\")[1]);\n      remoteResize(width, height);\n    } else if (remoteResize.getValue()) {\n      // No explicit size, but remote resizing is on so make sure it\n      // matches whatever size the window ended up being\n      remoteResize(w(), h());\n    }\n  }\n\n  public void handleResizeTimeout()\n  {\n    DesktopWindow self = (DesktopWindow)this;\n\n    assert(self != null);\n\n    self.remoteResize(self.w(), self.h());\n  }\n\n  private void remoteResize(int width, int height)\n  {\n    ScreenSet layout;\n    ListIterator<Screen> iter;\n\n    if (!fullscreen_active() || (width > w()) || (height > h())) {\n      // In windowed mode (or the framebuffer is so large that we need\n      // to scroll) we just report a single virtual screen that covers\n      // the entire framebuffer.\n\n      layout = cc.server.screenLayout();\n\n      // Not sure why we have no screens, but adding a new one should be\n      // safe as there is nothing to conflict with...\n      if (layout.num_screens() == 0)\n        layout.add_screen(new Screen());\n      else if (layout.num_screens() != 1) {\n        // More than one screen. Remove all but the first (which we\n        // assume is the \"primary\").\n\n        while (true) {\n          iter = layout.begin();\n          Screen screen = iter.next();\n\n          if (iter == layout.end())\n            break;\n\n          layout.remove_screen(screen.id);\n        }\n      }\n\n      // Resize the remaining single screen to the complete framebuffer\n      ((Screen)layout.begin().next()).dimensions.tl.x = 0;\n      ((Screen)layout.begin().next()).dimensions.tl.y = 0;\n      ((Screen)layout.begin().next()).dimensions.br.x = width;\n      ((Screen)layout.begin().next()).dimensions.br.y = height;\n    } else {\n      layout = new ScreenSet();\n      int id;\n      int sx, sy, sw, sh;\n      Rect viewport_rect = new Rect();\n      Rect screen_rect = new Rect();\n\n      // In full screen we report all screens that are fully covered.\n\n      viewport_rect.setXYWH(x() + (w() - width)/2, y() + (h() - height)/2,\n                            width, height);\n\n      // If we can find a matching screen in the existing set, we use\n      // that, otherwise we create a brand new screen.\n      //\n      // FIXME: We should really track screens better so we can handle\n      //        a resized one.\n      //\n      GraphicsEnvironment ge =\n        GraphicsEnvironment.getLocalGraphicsEnvironment();\n      for (GraphicsDevice gd : ge.getScreenDevices()) {\n        for (GraphicsConfiguration gc : gd.getConfigurations()) {\n          Rectangle bounds = gc.getBounds();\n          sx = bounds.x;\n          sy = bounds.y;\n          sw = bounds.width;\n          sh = bounds.height;\n\n          // Check that the screen is fully inside the framebuffer\n          screen_rect.setXYWH(sx, sy, sw, sh);\n          if (!screen_rect.enclosed_by(viewport_rect))\n            continue;\n\n          // Adjust the coordinates so they are relative to our viewport\n          sx -= viewport_rect.tl.x;\n          sy -= viewport_rect.tl.y;\n\n          // Look for perfectly matching existing screen...\n          for (iter = cc.server.screenLayout().begin();\n              iter != cc.server.screenLayout().end(); iter.next()) {\n            Screen screen = iter.next(); iter.previous();\n            if ((screen.dimensions.tl.x == sx) &&\n                (screen.dimensions.tl.y == sy) &&\n                (screen.dimensions.width() == sw) &&\n                (screen.dimensions.height() == sh))\n              break;\n          }\n\n          // Found it?\n          if (iter != cc.server.screenLayout().end()) {\n            layout.add_screen(iter.next());\n            continue;\n          }\n\n          // Need to add a new one, which means we need to find an unused id\n          Random rng = new Random();\n          while (true) {\n            id = rng.nextInt();\n            for (iter = cc.server.screenLayout().begin();\n                iter != cc.server.screenLayout().end(); iter.next()) {\n              Screen screen = iter.next(); iter.previous();\n              if (screen.id == id)\n                break;\n            }\n\n            if (iter == cc.server.screenLayout().end())\n              break;\n          }\n\n          layout.add_screen(new Screen(id, sx, sy, sw, sh, 0));\n        }\n\n        // If the viewport doesn't match a physical screen, then we might\n        // end up with no screens in the layout. Add a fake one...\n        if (layout.num_screens() == 0)\n          layout.add_screen(new Screen(0, 0, 0, width, height, 0));\n      }\n    }\n\n    // Do we actually change anything?\n    if ((width == cc.server.width()) &&\n        (height == cc.server.height()) &&\n        (layout == cc.server.screenLayout()))\n      return;\n\n    String buffer;\n    vlog.debug(String.format(\"Requesting framebuffer resize from %dx%d to %dx%d\",\n               cc.server.width(), cc.server.height(), width, height));\n    layout.debug_print();\n\n    if (!layout.validate(width, height)) {\n      vlog.error(\"Invalid screen layout computed for resize request!\");\n      return;\n    }\n\n    cc.writer().writeSetDesktopSize(width, height, layout);\n  }\n\n  boolean lionFSSupported() { return canDoLionFS; }\n\n  private int x() { return getContentPane().getX(); }\n  private int y() { return getContentPane().getY(); }\n  private int w() { return getContentPane().getWidth(); }\n  private int h() { return getContentPane().getHeight(); }\n\n  void enableLionFS() {\n    try {\n      String version = System.getProperty(\"os.version\");\n      int firstDot = version.indexOf('.');\n      int lastDot = version.lastIndexOf('.');\n      if (lastDot > firstDot && lastDot >= 0) {\n        version = version.substring(0, version.indexOf('.', firstDot + 1));\n      }\n      double v = Double.parseDouble(version);\n      if (v < 10.7)\n        throw new Exception(\"Operating system version is \" + v);\n\n      Class fsuClass = Class.forName(\"com.apple.eawt.FullScreenUtilities\");\n      Class argClasses[] = new Class[]{Window.class, Boolean.TYPE};\n      Method setWindowCanFullScreen =\n        fsuClass.getMethod(\"setWindowCanFullScreen\", argClasses);\n      setWindowCanFullScreen.invoke(fsuClass, this, true);\n\n      canDoLionFS = true;\n    } catch (Exception e) {\n      vlog.debug(\"Could not enable OS X 10.7+ full-screen mode: \" +\n                 e.getMessage());\n    }\n  }\n\n  public void toggleLionFS() {\n    try {\n      Class appClass = Class.forName(\"com.apple.eawt.Application\");\n      Method getApplication = appClass.getMethod(\"getApplication\",\n                                                 (Class[])null);\n      Object app = getApplication.invoke(appClass);\n      Method requestToggleFullScreen =\n        appClass.getMethod(\"requestToggleFullScreen\", Window.class);\n      requestToggleFullScreen.invoke(app, this);\n    } catch (Exception e) {\n      vlog.debug(\"Could not toggle OS X 10.7+ full-screen mode: \" +\n                 e.getMessage());\n    }\n  }\n\n\n  public boolean isMaximized()\n  {\n    int state = getExtendedState();\n    return ((state & JFrame.MAXIMIZED_BOTH) == JFrame.MAXIMIZED_BOTH);\n  }\n\n  public Dimension getScreenSize() {\n    return getScreenBounds().getSize();\n  }\n\n  public Rectangle getScreenBounds() {\n    GraphicsEnvironment ge =\n      GraphicsEnvironment.getLocalGraphicsEnvironment();\n    Rectangle r = new Rectangle();\n    if (fullScreenAllMonitors.getValue()) {\n      for (GraphicsDevice gd : ge.getScreenDevices())\n        for (GraphicsConfiguration gc : gd.getConfigurations())\n          r = r.union(gc.getBounds());\n    } else {\n      GraphicsConfiguration gc = getGraphicsConfiguration();\n      r = gc.getBounds();\n    }\n    return r;\n  }\n\n  public static Window getFullScreenWindow() {\n    GraphicsEnvironment ge =\n      GraphicsEnvironment.getLocalGraphicsEnvironment();\n    for (GraphicsDevice gd : ge.getScreenDevices()) {\n      Window fullScreenWindow = gd.getFullScreenWindow();\n      if (fullScreenWindow != null)\n        return fullScreenWindow;\n    }\n    return null;\n  }\n\n  public static void setFullScreenWindow(Window fullScreenWindow) {\n    GraphicsEnvironment ge =\n      GraphicsEnvironment.getLocalGraphicsEnvironment();\n    if (fullScreenAllMonitors.getValue()) {\n      for (GraphicsDevice gd : ge.getScreenDevices())\n        gd.setFullScreenWindow(fullScreenWindow);\n    } else {\n      GraphicsDevice gd = ge.getDefaultScreenDevice();\n      gd.setFullScreenWindow(fullScreenWindow);\n    }\n  }\n\n  public void handleOptions()\n  {\n\n    if (fullScreen.getValue() && !fullscreen_active())\n      fullscreen_on();\n    else if (!fullScreen.getValue() && fullscreen_active())\n      fullscreen_off();\n\n    if (remoteResize.getValue()) {\n      scroll.setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED);\n      scroll.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_AS_NEEDED);\n      remoteResize(w(), h());\n    } else {\n      String scaleString = scalingFactor.getValue();\n      if (!scaleString.equals(lastScaleFactor)) {\n        if (scaleString.matches(\"^[0-9]+$\")) {\n          scroll.setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED);\n          scroll.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_AS_NEEDED);\n          viewport.setScaledSize(cc.server.width(), cc.server.height());\n        } else {\n          scroll.setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_NEVER);\n          scroll.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_NEVER);\n          viewport.setScaledSize(w(), h());\n        }\n\n        if (isMaximized() || fullscreen_active()) {\n          repositionViewport();\n        } else {\n          int dx = getInsets().left + getInsets().right;\n          int dy = getInsets().top + getInsets().bottom;\n          setSize(viewport.scaledWidth+dx, viewport.scaledHeight+dy);\n        }\n\n        repositionViewport();\n        lastScaleFactor = scaleString;\n      }\n    }\n\n    if (isVisible()) {\n      toFront();\n      requestFocus();\n    }\n  }\n\n  // Compute current effective scale from the viewport ratio\n  public int getCurrentScalePercent()\n  {\n    return (int)Math.round(viewport.scaleRatioX * 100.0f);\n  }\n\n  public void setNumericScalePercent(int percent)\n  {\n    if (remoteResize.getValue())\n      return;\n\n    int clamped = Math.max(1, percent);\n    scalingFactor.setParam(Integer.toString(clamped));\n    handleOptions();\n  }\n\n  public void adjustRelativeScalePercent(int deltaPercent)\n  {\n    if (remoteResize.getValue())\n      return;\n\n    String scaleString = scalingFactor.getValue();\n    int current;\n    if (scaleString.matches(\"^[0-9]+$\")) {\n      current = Integer.parseInt(scaleString);\n    } else {\n      current = getCurrentScalePercent();\n    }\n    setNumericScalePercent(current + deltaPercent);\n  }\n\n  public void resetZoomToDefault()\n  {\n    if (remoteResize.getValue())\n      return;\n    setNumericScalePercent(100);\n  }\n\n  public void setZoomToFit()\n  {\n    if (remoteResize.getValue())\n      return;\n    scalingFactor.setParam(\"FixedRatio\");\n    handleOptions();\n  }\n\n  public void handleFullscreenTimeout()\n  {\n    DesktopWindow self = (DesktopWindow)this;\n\n    assert(self != null);\n\n    self.delayedFullscreen = false;\n\n    if (self.delayedDesktopSize) {\n      self.handleDesktopSize();\n      self.delayedDesktopSize = false;\n    }\n  }\n\n  private CConn cc;\n  private JScrollPane scroll;\n  public Viewport viewport;\n\n  private boolean firstUpdate;\n  private boolean delayedFullscreen;\n  private boolean delayedDesktopSize;\n  private boolean canDoLionFS;\n  private String lastScaleFactor;\n  private Rectangle lastBounds;\n  private int lastState;\n  private Timer timer;\n}\n\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/Dialog.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2016 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// This Dialog class implements a pop-up dialog.  This is needed because\n// apparently you can't use the standard AWT Dialog from within an applet.  The\n// dialog can be made visible by calling its showDialog() method.  Dialogs can\n// be modal or non-modal.  For a modal dialog box, the showDialog() method must\n// be called from a thread other than the GUI thread, and it only returns when\n// the dialog box has been dismissed.  For a non-modal dialog box, the\n// showDialog() method returns immediately.\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.Dialog.*;\nimport java.awt.event.*;\nimport java.io.File;\nimport javax.swing.*;\nimport javax.swing.border.*;\nimport javax.swing.filechooser.*;\nimport javax.swing.text.*;\n\nclass Dialog extends JDialog implements ActionListener,\n                                        ItemListener,\n                                        KeyListener {\n\n  // GridBag weights\n  static double HEAVY = 1.0;\n  static double LIGHT = 0.0;\n\n  public Dialog(boolean modal) {\n    setIconImage(VncViewer.frameIcon);\n    if (modal) {\n      setModalityType(ModalityType.APPLICATION_MODAL);\n    } else {\n      setModalityType(ModalityType.MODELESS);\n    }\n  }\n\n  public void showDialog(Component c) {\n    initDialog();\n    if (c != null) {\n      setLocationRelativeTo(c);\n    } else {\n      Dimension dpySize = getToolkit().getScreenSize();\n      Dimension mySize = getSize();\n      int x = (dpySize.width - mySize.width) / 2;\n      int y = (dpySize.height - mySize.height) / 2;\n      setLocation(x, y);\n    }\n\n    if (getModalityType() == ModalityType.APPLICATION_MODAL)\n      setAlwaysOnTop(true);\n    setVisible(true);\n  }\n\n  public void showDialog() {\n    showDialog(null);\n  }\n\n  public void endDialog() {\n    setVisible(false);\n    setAlwaysOnTop(false);\n  }\n\n  // initDialog() can be overridden in a derived class.  Typically it is used\n  // to make sure that checkboxes have the right state, etc.\n  public void initDialog() { }\n\n  public void actionPerformed(ActionEvent e) { }\n  public void itemStateChanged(ItemEvent e) { }\n  public void keyTyped(KeyEvent event) { }\n  public void keyReleased(KeyEvent event) { }\n  public void keyPressed(KeyEvent event) { }\n\n  protected void addListeners(Container c) {\n    for (Component ch : c.getComponents()) {\n      if (ch instanceof JCheckBox)\n        ((JCheckBox)ch).addItemListener(this);\n      else if (ch instanceof JRadioButton)\n        ((JRadioButton)ch).addActionListener(this);\n      else if (ch instanceof JButton)\n        ((JButton)ch).addActionListener(this);\n      else if (ch instanceof JComboBox)\n        ((JComboBox)ch).addActionListener(this);\n      else if (ch instanceof JTextField)\n        ((JTextField)ch).addKeyListener(this);\n      else if (ch instanceof Container)\n        addListeners((Container)ch);\n    }\n  }\n\n  public int getButtonLabelInset(AbstractButton b) {\n    // Aligning components vertically to the label of\n    // a JCheckbox is absurdly difficult.  JCheckBox's\n    // getIcon() method generally returns null, so we \n    // have to resort to querying the UIManager in \n    // order to determine the width of the checkbox.\n    // The default values are based on Nimbus.\n    int width = 18;\n    int gap = 4;\n\n    Icon ico = b.getIcon();\n    if (ico == null) {\n      if (b instanceof JCheckBox)\n        ico = (Icon)UIManager.get(\"CheckBox.icon\");\n      else if (b instanceof JRadioButton)\n        ico = (Icon)UIManager.get(\"RadioButton.icon\");\n    }\n    if (ico != null)\n      width = Math.max(width, ico.getIconWidth());\n    if (b != null)\n      gap = Math.max(gap, b.getIconTextGap());\n\n    return width + gap;\n  }\n\n  public static File showChooser(String title, File defFile,\n                                 Container c, FileNameExtensionFilter f) {\n    JFileChooser fc = new JFileChooser(defFile);\n    fc.setDialogTitle(title);\n    fc.setApproveButtonText(\"OK  \\u21B5\");\n    fc.setFileHidingEnabled(false);\n    if (f != null)\n      fc.setFileFilter(f);\n    if (fc.showOpenDialog(c) == JFileChooser.APPROVE_OPTION)\n      return fc.getSelectedFile();\n    else\n      return null;\n  }\n\n  public static File showChooser(String title, File defFile, Container c) {\n    return showChooser(title, defFile, c, null);\n  }\n\n  protected File showChooser(String title, File defFile,\n                             FileNameExtensionFilter f) {\n    return showChooser(title, defFile, this, f);\n  }\n\n  protected File showChooser(String title, File defFile) {\n    return showChooser(title, defFile, this);\n  }\n\n  protected class GroupedJRadioButton extends JRadioButton {\n    public GroupedJRadioButton(String l, ButtonGroup g, JComponent c) {\n      super(l);\n      c.add(this);\n      if (g != null)\n        g.add(this);\n    }\n  }\n\n  protected class MyJComboBox extends JComboBox {\n    public MyJComboBox(Object[] items) {\n      super(items);\n      // Hack to set the left inset on editable JComboBox\n      if (UIManager.getLookAndFeel().getID().equals(\"Windows\")) {\n        this.setBorder(BorderFactory.createCompoundBorder(this.getBorder(),\n          BorderFactory.createEmptyBorder(0,1,0,0)));\n      } else if (UIManager.getLookAndFeel().getID().equals(\"Metal\")) {\n        ComboBoxEditor editor = this.getEditor();\n        JTextField jtf = (JTextField)editor.getEditorComponent();\n        jtf.setBorder(new CompoundBorder(jtf.getBorder(), new EmptyBorder(0,2,0,0)));\n      }\n    }\n\n    public MyJComboBox() {\n      new MyJComboBox(null);\n    }\n\n    @Override\n    public void setPrototypeDisplayValue(Object prototypeDisplayValue) {\n      // Even with setPrototypeDisplayValue set JComboxBox resizes \n      // itself when setEditable(true) is called.\n      super.setPrototypeDisplayValue(prototypeDisplayValue);\n      boolean e = isEditable();\n      setEditable(false);\n      Dimension d = getPreferredSize();\n      setPreferredSize(d);\n      setEditable(e);\n    }\n\n    public void setDocument(PlainDocument doc) {\n      ComboBoxEditor editor = this.getEditor();\n      JTextField jtf = (JTextField)editor.getEditorComponent();\n      jtf.setDocument(doc);\n    }\n\n  }\n\n  private Window fullScreenWindow;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/ExtProcess.java",
    "content": "/*\n *  Copyright (C) 2016 Brian P. Hinz. All Rights Reserved.\n *\n *  This is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  This software is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with this software; if not, write to the Free Software\n *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n *  USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.util.*;\n\nimport com.tigervnc.rdr.*;\nimport com.tigervnc.rfb.*;\nimport com.tigervnc.rfb.Exception;\nimport com.tigervnc.network.*;\n\nimport static com.tigervnc.vncviewer.Parameters.*;\n\npublic class ExtProcess implements Runnable {\n\n  private String cmd = null;\n  private LogWriter vlog = null;\n  private boolean shutdown = false;\n  private Process pid = null;\n\n  private static class MyProcessLogger extends Thread {\n    private final BufferedReader err;\n    private final LogWriter vlog;\n\n    public MyProcessLogger(Process p, LogWriter vlog) {\n      InputStreamReader reader = \n        new InputStreamReader(p.getErrorStream());\n      err = new BufferedReader(reader);\n      this.vlog = vlog;\n    }\n\n    @Override\n    public void run() {\n      try {\n        while (true) {\n          String msg = err.readLine();\n          if (msg != null)\n            vlog.info(msg);\n        }\n      } catch(java.io.IOException e) {\n        vlog.info(e.getMessage());\n      } finally {\n        try {\n          if (err != null)\n            err.close();\n        } catch (java.io.IOException e ) { }\n      }\n    }\n  }\n\n  private static class MyShutdownHook extends Thread {\n\n    private Process proc = null;\n\n    public MyShutdownHook(Process p) {\n      proc = p;\n    }\n\n    @Override\n    public void run() {\n      try {\n        proc.exitValue();\n      } catch (IllegalThreadStateException e) {\n        try {\n          // wait for CConn to shutdown the socket\n          Thread.sleep(500);\n        } catch(InterruptedException ie) { }\n        proc.destroy();\n      }\n    }\n  }\n\n  public ExtProcess(String command, LogWriter vlog, boolean shutdown) {\n    cmd = command;  \n    this.vlog = vlog;\n    this.shutdown = shutdown;\n  }\n\n  public ExtProcess(String command, LogWriter vlog) {\n    this(command, vlog, false);\n  }\n\n  public ExtProcess(String command) {\n    this(command, null, false);\n  }\n\n  public void run() {\n    try {\n      Runtime runtime = Runtime.getRuntime();\n      pid = runtime.exec(cmd);\n      if (shutdown)\n        runtime.addShutdownHook(new MyShutdownHook(pid));\n      if (vlog != null)\n        new MyProcessLogger(pid, vlog).start();\n      pid.waitFor();\n    } catch(InterruptedException e) {\n      vlog.info(e.getMessage());\n    } catch(java.io.IOException e) {\n      vlog.info(e.getMessage());\n    }\n  }\n\n  //static LogWriter vlog = new LogWriter(\"ExtProcess\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/FileUtils.java",
    "content": "/* Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport javax.swing.filechooser.FileSystemView;\n\nimport com.tigervnc.rfb.LogWriter;\n\nimport java.io.File;\n\npublic class FileUtils {\n\n  public static String getHomeDir() {\n    String homeDir = null;\n    try {\n      String os = System.getProperty(\"os.name\");\n      try {\n        if (os.startsWith(\"Windows\")) {\n          homeDir = System.getenv(\"USERPROFILE\");\n        } else {\n          try {\n            homeDir = FileSystemView.getFileSystemView().\n              getDefaultDirectory().getCanonicalPath();\n          } catch(java.security.AccessControlException e) {\n            vlog.error(\"Cannot access system property:\"+e.getMessage());\n          }\n        }\n      } catch (java.lang.Exception e) {\n        e.printStackTrace();\n      }\n    } catch(java.security.AccessControlException e) {\n      vlog.error(\"Cannot access os.name system property:\"+e.getMessage());\n    }\n\n    return homeDir + getFileSeparator();\n  }\n\n  public static String getVncDir(String xdgEnv, String xdgDefault) {\n    File legacyDir = new File(getHomeDir() + \".vnc\" + getFileSeparator());\n    String os = System.getProperty(\"os.name\");\n\n    if (os.startsWith(\"Windows\")) {\n      File newDir = new File(System.getenv(\"APPDATA\") + getFileSeparator() + \"TigerVNC\" + getFileSeparator());\n      if (!newDir.exists()) {\n        newDir.mkdirs();\n      }\n      File[] existingFiles = legacyDir.listFiles();\n      if (existingFiles != null) {\n        for (File file : existingFiles) {\n          file.renameTo(new File(newDir.getPath() + file.getName()));\n        }\n        legacyDir.delete();\n      }\n      return newDir.getPath();\n    } else {\n      if (legacyDir.exists()) {\n        vlog.info(\"Warning: ~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\");\n        return legacyDir.getPath();\n      }\n      String xdgBaseDir = System.getenv(xdgEnv);\n      return (xdgBaseDir != null && xdgBaseDir.startsWith(\"/\"))\n        ? xdgBaseDir + getFileSeparator() + \"tigervnc\" + getFileSeparator()\n        : getHomeDir() + xdgDefault + getFileSeparator() + \"tigervnc\" + getFileSeparator();\n    }\n  }\n\n  public static String getVncConfigDir() {\n    return getVncDir(\"XDG_CONFIG_HOME\", \".config\");\n  }\n\n  public static String getVncDataDir() {\n    return getVncDir(\"XDG_DATA_HOME\", \".local\" + getFileSeparator() + \"share\");\n  }\n\n  public static String getVncStateDir() {\n    return getVncDir(\"XDG_STATE_HOME\", \".local\" + getFileSeparator() + \"state\");\n  }\n\n  public static String getFileSeparator() {\n    String separator = null;\n    try {\n      separator = Character.toString(java.io.File.separatorChar);\n    } catch(java.security.AccessControlException e) {\n      vlog.error(\"Cannot access file.separator system property:\"+e.getMessage());\n    }\n    return separator;\n  }\n\n  static LogWriter vlog = new LogWriter(\"FileUtils\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/JavaPixelBuffer.java",
    "content": "/* Copyright (C) 2012-2016 Brian P. Hinz\n * Copyright (C) 2012 D. R. Commander.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.image.*;\nimport java.nio.*;\n\nimport com.tigervnc.rfb.*;\nimport com.tigervnc.rfb.Point;\n\npublic class JavaPixelBuffer extends PlatformPixelBuffer \n{\n\n  public JavaPixelBuffer(int w, int h) {\n    super(getPreferredPF(), w, h,\n          getPreferredPF().getColorModel().createCompatibleWritableRaster(w,h));\n    ColorModel cm = format.getColorModel();\n    image = new BufferedImage(cm, data, cm.isAlphaPremultiplied(), null);\n    image.setAccelerationPriority(1);\n  }\n\n  public WritableRaster getBufferRW(Rect r)\n  {\n    synchronized(image) {\n      return ((BufferedImage)image)\n        .getSubimage(r.tl.x, r.tl.y, r.width(), r.height()).getRaster();\n    }\n  }\n\n  public Raster getBuffer(Rect r)\n  {\n    Rectangle rect =\n      new Rectangle(r.tl.x, r.tl.y, r.width(), r.height());\n    synchronized(image) {\n      return ((BufferedImage)image).getData(rect);\n    }\n  }\n\n  public void fillRect(Rect r, byte[] pix)\n  {\n    ColorModel cm = format.getColorModel();\n    int pixel =\n      ByteBuffer.wrap(pix).order(format.getByteOrder()).asIntBuffer().get(0);\n    Color c = new Color(cm.getRGB(pixel));\n    synchronized(image) {\n      Graphics2D g2 = (Graphics2D)image.getGraphics();\n      g2.setColor(c);\n      g2.fillRect(r.tl.x, r.tl.y, r.width(), r.height());\n      g2.dispose();\n    }\n\n    commitBufferRW(r);\n  }\n\n  public void copyRect(Rect rect, Point move_by_delta)\n  {\n    synchronized(image) {\n      Graphics2D g2 = (Graphics2D)image.getGraphics();\n      g2.copyArea(rect.tl.x - move_by_delta.x,\n                  rect.tl.y - move_by_delta.y,\n                  rect.width(), rect.height(),\n                  move_by_delta.x, move_by_delta.y);\n      g2.dispose();\n    }\n\n    commitBufferRW(rect);\n  }\n\n  private static PixelFormat getPreferredPF()\n  {\n    GraphicsEnvironment ge =\n      GraphicsEnvironment.getLocalGraphicsEnvironment();\n    GraphicsDevice gd = ge.getDefaultScreenDevice();\n    GraphicsConfiguration gc = gd.getDefaultConfiguration();\n    ColorModel cm = gc.getColorModel();\n    int depth = ((cm.getPixelSize() > 24) ? 24 : cm.getPixelSize());\n    int bpp = (depth > 16 ? 32 : (depth > 8 ? 16 : 8));\n    ByteOrder byteOrder = ByteOrder.nativeOrder();\n    boolean bigEndian = (byteOrder == ByteOrder.BIG_ENDIAN ? true : false);\n    boolean trueColour = true;\n    int redShift    = cm.getComponentSize()[0] + cm.getComponentSize()[1];\n    int greenShift  = cm.getComponentSize()[0];\n    int blueShift   = 0;\n    int redMask   = ((int)Math.pow(2, cm.getComponentSize()[2]) - 1);\n    int greenMask = ((int)Math.pow(2, cm.getComponentSize()[1]) - 1);\n    int blueMmask = ((int)Math.pow(2, cm.getComponentSize()[0]) - 1);\n    return new PixelFormat(bpp, depth, bigEndian, trueColour,\n                           redMask, greenMask, blueMmask,\n                           redShift, greenShift, blueShift);\n  }\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/KeyMap.java",
    "content": "/* Copyright (C) 2017 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.event.*;\nimport java.util.*;\nimport javax.swing.*;\n\nimport com.tigervnc.rfb.*;\n\nimport static java.awt.event.KeyEvent.*;\nimport static com.tigervnc.rfb.Keysymdef.*;\n\npublic class KeyMap {\n\n  public final static int NoSymbol = 0;\n\n  private static final HashMap<Integer, Character> code_map_java_to_char;\n  static {\n    // Certain KeyStrokes fail to produce a valid character (CTRL+ALT+...\n    // on Windows and Mac almost never does).  For these cases, the best\n    // we can try to do is to map to the ASCII symbol from the keyCode.\n    code_map_java_to_char = new HashMap<Integer, Character>();\n    for (int c=32; c<0x7f; c++) {\n      int keyCode = KeyEvent.getExtendedKeyCodeForChar(c);\n      if (keyCode != KeyEvent.VK_UNDEFINED)\n        // Not all ASCII characters have VK_ constants, see vk_to_ascii()\n        code_map_java_to_char.put(keyCode, (char)c);\n    }\n  }\n\n  private static int[][] vkey_map = {\n    /* KEYCODE                                                LOCATION                                      */\n    /*                          UNKNOWN       STANDARD                  LEFT          RIGHT         NUMPAD  */\n    { VK_BACK_SPACE,            NoSymbol,     XK_BackSpace,             NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_TAB,                   NoSymbol,     XK_Tab,                   NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_CANCEL,                NoSymbol,     XK_Cancel,                NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_ENTER,                 NoSymbol,     XK_Return,                NoSymbol,     NoSymbol,     XK_KP_Enter },\n    { VK_SHIFT,                 NoSymbol,     XK_Shift_L,               XK_Shift_L,   XK_Shift_R,   NoSymbol },\n    { VK_CONTROL,               NoSymbol,     XK_Control_L,             XK_Control_L, XK_Control_R, NoSymbol },\n    { VK_ALT,                   NoSymbol,     XK_Alt_L,                 XK_Alt_L,     XK_Alt_R,     NoSymbol },\n    /* VK_PAUSE left out on purpose because interpretation depends on state of CTRL. See further down. */\n    { VK_CAPS_LOCK,             NoSymbol,     XK_Caps_Lock,             NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_ESCAPE,                NoSymbol,     XK_Escape,                NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_END,                   NoSymbol,     XK_End,                   NoSymbol,     NoSymbol,     XK_KP_End },\n    { VK_HOME,                  NoSymbol,     XK_Home,                  NoSymbol,     NoSymbol,     XK_KP_Home },\n    { VK_LEFT,                  NoSymbol,     XK_Left,                  NoSymbol,     NoSymbol,     XK_KP_Left },\n    { VK_UP,                    NoSymbol,     XK_Up,                    NoSymbol,     NoSymbol,     XK_KP_Up },\n    { VK_RIGHT,                 NoSymbol,     XK_Right,                 NoSymbol,     NoSymbol,     XK_KP_Right },\n    { VK_DOWN,                  NoSymbol,     XK_Down,                  NoSymbol,     NoSymbol,     XK_KP_Down },\n    /* VK_PRINTSCREEN left out on purpose because interpretation depends on state of CTRL. See further down. */\n    { VK_PAGE_UP,               NoSymbol,     XK_Page_Up,               NoSymbol,     NoSymbol,     XK_KP_Page_Up },\n    { VK_PAGE_DOWN,             NoSymbol,     XK_Page_Down,             NoSymbol,     NoSymbol,     XK_KP_Page_Down },\n    { VK_BEGIN,                 NoSymbol,     XK_Begin,                 NoSymbol,     NoSymbol,     XK_KP_Begin },\n    { VK_KP_LEFT,               NoSymbol,     XK_KP_Left,               NoSymbol,     NoSymbol,     XK_KP_Left },\n    { VK_KP_UP,                 NoSymbol,     XK_KP_Up,                 NoSymbol,     NoSymbol,     XK_KP_Up },\n    { VK_KP_RIGHT,              NoSymbol,     XK_KP_Right,              NoSymbol,     NoSymbol,     XK_KP_Right },\n    { VK_KP_DOWN,               NoSymbol,     XK_KP_Down,               NoSymbol,     NoSymbol,     XK_KP_Down },\n    { VK_INSERT,                NoSymbol,     XK_Insert,                NoSymbol,     NoSymbol,     XK_KP_Insert },\n    { VK_DELETE,                NoSymbol,     XK_Delete,                NoSymbol,     NoSymbol,     XK_KP_Delete },\n    { VK_WINDOWS,               NoSymbol,     NoSymbol,                 XK_Super_L,   XK_Super_R,   NoSymbol },\n    { VK_CONTEXT_MENU,          NoSymbol,     XK_Menu,                  NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_NUMPAD0,               NoSymbol,     NoSymbol,                 NoSymbol,     NoSymbol,     XK_KP_0 },\n    { VK_NUMPAD1,               NoSymbol,     NoSymbol,                 NoSymbol,     NoSymbol,     XK_KP_1 },\n    { VK_NUMPAD2,               NoSymbol,     NoSymbol,                 NoSymbol,     NoSymbol,     XK_KP_2 },\n    { VK_NUMPAD3,               NoSymbol,     NoSymbol,                 NoSymbol,     NoSymbol,     XK_KP_3 },\n    { VK_NUMPAD4,               NoSymbol,     NoSymbol,                 NoSymbol,     NoSymbol,     XK_KP_4 },\n    { VK_NUMPAD5,               NoSymbol,     NoSymbol,                 NoSymbol,     NoSymbol,     XK_KP_5 },\n    { VK_NUMPAD6,               NoSymbol,     NoSymbol,                 NoSymbol,     NoSymbol,     XK_KP_6 },\n    { VK_NUMPAD7,               NoSymbol,     NoSymbol,                 NoSymbol,     NoSymbol,     XK_KP_7 },\n    { VK_NUMPAD8,               NoSymbol,     NoSymbol,                 NoSymbol,     NoSymbol,     XK_KP_8 },\n    { VK_NUMPAD9,               NoSymbol,     NoSymbol,                 NoSymbol,     NoSymbol,     XK_KP_9 },\n    { VK_MULTIPLY,              NoSymbol,     XK_KP_Multiply,           NoSymbol,     NoSymbol,     XK_KP_Multiply },\n    { VK_ADD,                   NoSymbol,     XK_KP_Add,                NoSymbol,     NoSymbol,     XK_KP_Add },\n    { VK_SUBTRACT,              NoSymbol,     XK_KP_Subtract,           NoSymbol,     NoSymbol,     XK_KP_Subtract },\n    { VK_DIVIDE,                NoSymbol,     XK_KP_Divide,             NoSymbol,     NoSymbol,     XK_KP_Divide },\n    { VK_SEPARATER,             NoSymbol,     XK_KP_Separator,          NoSymbol,     NoSymbol,     XK_KP_Separator },\n    { VK_DECIMAL,               NoSymbol,     XK_KP_Decimal,            NoSymbol,     NoSymbol,     XK_KP_Decimal },\n    { VK_F1,                    NoSymbol,     XK_F1,                    XK_L1,        XK_R1,        NoSymbol },\n    { VK_F2,                    NoSymbol,     XK_F2,                    XK_L2,        XK_R2,        NoSymbol },\n    { VK_F3,                    NoSymbol,     XK_F3,                    XK_L3,        XK_R3,        NoSymbol },\n    { VK_F4,                    NoSymbol,     XK_F4,                    XK_L4,        XK_R4,        NoSymbol },\n    { VK_F5,                    NoSymbol,     XK_F5,                    XK_L5,        XK_R5,        NoSymbol },\n    { VK_F6,                    NoSymbol,     XK_F6,                    XK_L6,        XK_R6,        NoSymbol },\n    { VK_F7,                    NoSymbol,     XK_F7,                    XK_L7,        XK_R7,        NoSymbol },\n    { VK_F8,                    NoSymbol,     XK_F8,                    XK_L8,        XK_R8,        NoSymbol },\n    { VK_F9,                    NoSymbol,     XK_F9,                    XK_L9,        XK_R9,        NoSymbol },\n    { VK_F10,                   NoSymbol,     XK_F10,                   XK_L10,       XK_R10,       NoSymbol },\n    { VK_F11,                   NoSymbol,     XK_F11,                   NoSymbol,     XK_R11,       NoSymbol },\n    { VK_F12,                   NoSymbol,     XK_F12,                   NoSymbol,     XK_R12,       NoSymbol },\n    { VK_F13,                   NoSymbol,     XK_F13,                   NoSymbol,     XK_R13,       NoSymbol },\n    { VK_F14,                   NoSymbol,     XK_F14,                   NoSymbol,     XK_R14,       NoSymbol },\n    { VK_F15,                   NoSymbol,     XK_F15,                   NoSymbol,     XK_R15,       NoSymbol },\n    { VK_F16,                   NoSymbol,     XK_F16,                   NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_F17,                   NoSymbol,     XK_F17,                   NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_F18,                   NoSymbol,     XK_F18,                   NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_F19,                   NoSymbol,     XK_F19,                   NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_F20,                   NoSymbol,     XK_F20,                   NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_F21,                   NoSymbol,     XK_F21,                   NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_F22,                   NoSymbol,     XK_F22,                   NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_F23,                   NoSymbol,     XK_F23,                   NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_F24,                   NoSymbol,     XK_F24,                   NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_NUM_LOCK,              NoSymbol,     XK_Num_Lock,              NoSymbol,     NoSymbol,     XK_Num_Lock },\n    { VK_SCROLL_LOCK,           NoSymbol,     XK_Scroll_Lock,           NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_ALT_GRAPH,             NoSymbol,     XK_ISO_Level3_Shift,      NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_META,                  NoSymbol,     NoSymbol,                 XK_Meta_L,    XK_Meta_R,    NoSymbol },\n    { VK_MODECHANGE,            NoSymbol,     XK_Mode_switch,           NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_CLEAR,                 NoSymbol,     XK_Clear,                 NoSymbol,     NoSymbol,     XK_KP_Begin },\n    { VK_AGAIN,                 NoSymbol,     XK_Redo,                  NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_UNDO,                  NoSymbol,     XK_Undo,                  NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_FIND,                  NoSymbol,     XK_Find,                  NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_STOP,                  NoSymbol,     XK_Cancel,                NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_HELP,                  NoSymbol,     XK_Help,                  NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_KANJI,                 NoSymbol,     XK_Kanji,                 NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_KATAKANA,              NoSymbol,     XK_Katakana,              NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_HIRAGANA,              NoSymbol,     XK_Hiragana,              NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_PREVIOUS_CANDIDATE,    NoSymbol,     XK_PreviousCandidate,     NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_CODE_INPUT,            NoSymbol,     XK_Codeinput,             NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_JAPANESE_ROMAN,        NoSymbol,     XK_Romaji,                NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_KANA_LOCK,             NoSymbol,     XK_Kana_Lock,             NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_ABOVEDOT,         NoSymbol,     XK_dead_abovedot,         NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_ABOVERING,        NoSymbol,     XK_dead_abovering,        NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_ACUTE,            NoSymbol,     XK_dead_acute,            NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_BREVE,            NoSymbol,     XK_dead_breve,            NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_CARON,            NoSymbol,     XK_dead_caron,            NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_CEDILLA,          NoSymbol,     XK_dead_cedilla,          NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_CIRCUMFLEX,       NoSymbol,     XK_dead_circumflex,       NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_DIAERESIS,        NoSymbol,     XK_dead_diaeresis,        NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_DOUBLEACUTE,      NoSymbol,     XK_dead_doubleacute,      NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_GRAVE,            NoSymbol,     XK_dead_grave,            NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_IOTA,             NoSymbol,     XK_dead_iota,             NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_MACRON,           NoSymbol,     XK_dead_macron,           NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_OGONEK,           NoSymbol,     XK_dead_ogonek,           NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_SEMIVOICED_SOUND, NoSymbol,     XK_dead_semivoiced_sound, NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_TILDE,            NoSymbol,     XK_dead_tilde,            NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_DEAD_VOICED_SOUND,     NoSymbol,     XK_dead_voiced_sound,     NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_ALPHANUMERIC,          NoSymbol,     XK_Eisu_Shift,            NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_ALL_CANDIDATES,        NoSymbol,     XK_MultipleCandidate,     NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_KANA,                  NoSymbol,     XK_Kana_Shift,            NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_JAPANESE_KATAKANA,     NoSymbol,     XK_Katakana,              NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_JAPANESE_HIRAGANA,     NoSymbol,     XK_Hiragana,              NoSymbol,     NoSymbol,     NoSymbol },\n    { VK_COMPOSE,               NoSymbol,     XK_Multi_key,             NoSymbol,     NoSymbol,     NoSymbol },\n  };\n\n  public static int vkey_to_keysym(KeyEvent ev)\n  {\n    int keyCode = get_keycode_fallback_extended(ev);\n\n    // Start with keys that either don't generate a symbol, or\n    // generate the same symbol as some other key.\n    if (keyCode == KeyEvent.VK_PAUSE)\n      return (ev.isControlDown() ? XK_Break : XK_Pause);\n    else if (keyCode == KeyEvent.VK_PRINTSCREEN)\n      return (ev.isControlDown() ? XK_Sys_Req : XK_Print);\n    else\n      for(int i = 0; i < vkey_map.length; i++)\n        if (keyCode == vkey_map[i][0])\n          return vkey_map[i][ev.getKeyLocation()+1];\n\n    // Unknown special key?\n    if (KeyEvent.getKeyText(keyCode).isEmpty()) {\n      vlog.error(\"Unknown key code: 0x%04x\", keyCode);\n      return NoSymbol;\n    }\n\n    // Pressing Ctrl wreaks havoc with the symbol lookup...\n    int ucs = (int)ev.getKeyChar();\n    if (ev.isControlDown()) {\n      // For CTRL-<letter>, CTRL is sent separately, so just send <letter>.\n      if ((ucs >= 1 && ucs <= 26 && !ev.isShiftDown()) ||\n          // CTRL-{, CTRL-|, CTRL-} also map to ASCII 96-127\n          (ucs >= 27 && ucs <= 29 && ev.isShiftDown()))\n        ucs += 96;\n      // For CTRL-SHIFT-<letter>, send capital <letter> to emulate behavior\n      // of Linux.  For CTRL-@, send @.  For CTRL-_, send _.  For CTRL-^,\n      // send ^.\n      else if (ucs < 32)\n        ucs += 64;\n      // If it's still undefined, map the keyCode to ASCII symbol\n      else if (keyCode >= 0 && keyCode <= 127)\n        if (ucs == CHAR_UNDEFINED || ev.isAltDown())\n          ucs = vk_to_ascii(keyCode, ev.isShiftDown());\n        else if (VncViewer.os.startsWith(\"mac os x\") && ev.isMetaDown()) \n        // Alt on OS X behaves more like AltGr on other systems, and to get\n        // sane behaviour we should translate things in that manner for the\n        // remote VNC server. However that means we lose the ability to use\n        // Alt as a shortcut modifier. Do what RealVNC does and hijack the\n        // left command key as an Alt replacement.\n          ucs = vk_to_ascii(keyCode, ev.isShiftDown());\n    }\n\n    // Dead keys are represented by their spacing equivalent\n    // (or something similar depending on the layout)\n    if (Character.getType(ucs) == Character.COMBINING_SPACING_MARK)\n      return Keysym2ucs.ucs2keysym(Keysym2ucs.ucs2combining(ucs));\n\n    if (Character.isDefined(ucs))\n      return Keysym2ucs.ucs2keysym(ucs);\n\n    return NoSymbol;\n  }\n\n  public static int get_keycode_fallback_extended(final KeyEvent ev) {\n    final int keyCode = ev.getKeyCode();\n    return (keyCode == 0) ? ev.getExtendedKeyCode() : keyCode;\n  }\n\n  private static int vk_to_ascii(int vk, boolean shift) {\n    char c = 0;\n    if (code_map_java_to_char.containsKey(vk))\n      c = code_map_java_to_char.get(vk);\n    // 0x25 (%) and 0x3F (?) do not have VK_ constants\n    if (vk == VK_5)\n      c = shift ? '%' : c;\n    else if (vk == VK_SLASH)\n      c = shift ? '?' : c;\n    if (Character.isLetter(c))\n      c = shift ? Character.toUpperCase(c) : Character.toLowerCase(c);\n    return (int)c;\n  }\n\n  static LogWriter vlog = new LogWriter(\"KeyMap\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/LICENCE.TXT",
    "content": "\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 2, June 1991\n\n\t  Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n\t 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\t\t\t    Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Library General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\f\n\t\t    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\f\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\f\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\f\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n\t\t\t    NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n\t\t     END OF TERMS AND CONDITIONS\n\f\n\tAppendix: How to apply these terms to your new programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) 19yy  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n    USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) 19yy name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Library General\nPublic License instead of this License.\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/MANIFEST.MF",
    "content": "Manifest-Version: 1.0\nMain-Class: com.tigervnc.vncviewer.VncViewer\nApplication-Name: TigerVNC\nPermissions: all-permissions\nCodebase: *\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/MenuKey.java",
    "content": "/* Copyright 2011 Martin Koegler <mkoegler@auto.tuwien.ac.at>\n * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * Copyright 2012-2017 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.event.KeyEvent;\n\nimport com.tigervnc.rfb.*;\n\nimport static java.awt.event.KeyEvent.*;\nimport static com.tigervnc.rfb.Keysymdef.*;\n\npublic class MenuKey\n{\n  static class MenuKeySymbol {\n    public MenuKeySymbol(String name_, int javacode_,\n                         int keycode_, int keysym_) {\n      name = name_;\n      javacode = javacode_;\n      keycode = keycode_;\n      keysym = keysym_;\n    }\n    String name;\n    int javacode;\n    int keycode;\n    int keysym;\n  }\n\n  private static final MenuKeySymbol[] menuSymbols = {\n    new MenuKeySymbol(\"F1\", VK_F1, 0x3b, XK_F1),\n    new MenuKeySymbol(\"F2\", VK_F2, 0x3c, XK_F2),\n    new MenuKeySymbol(\"F3\", VK_F3, 0x3d, XK_F3),\n    new MenuKeySymbol(\"F4\", VK_F4, 0x3e, XK_F4),\n    new MenuKeySymbol(\"F5\", VK_F5, 0x3f, XK_F5),\n    new MenuKeySymbol(\"F6\", VK_F6, 0x40, XK_F6),\n    new MenuKeySymbol(\"F7\", VK_F7, 0x41, XK_F7),\n    new MenuKeySymbol(\"F8\", VK_F8, 0x42, XK_F8),\n    new MenuKeySymbol(\"F9\", VK_F9, 0x43, XK_F9),\n    new MenuKeySymbol(\"F10\", VK_F10, 0x44, XK_F10),\n    new MenuKeySymbol(\"F11\", VK_F11, 0x57, XK_F11),\n    new MenuKeySymbol(\"F12\", VK_F12, 0x58, XK_F12),\n    new MenuKeySymbol(\"Pause\", VK_PAUSE, 0xc6, XK_Pause),\n    new MenuKeySymbol(\"Scroll_Lock\", VK_SCROLL_LOCK,\n                      0x46, XK_Scroll_Lock),\n    new MenuKeySymbol(\"Escape\", VK_ESCAPE, 0x01, XK_Escape),\n    new MenuKeySymbol(\"Insert\", VK_INSERT, 0xd2, XK_Insert),\n    new MenuKeySymbol(\"Delete\", VK_DELETE, 0xd3, XK_Delete),\n    new MenuKeySymbol(\"Home\", VK_HOME, 0xc7, XK_Home),\n    new MenuKeySymbol(\"Page_Up\", VK_PAGE_UP, 0xc9, XK_Page_Up),\n    new MenuKeySymbol(\"Page_Down\", VK_PAGE_DOWN, 0xd1, XK_Page_Down)\n  };\n\n  static int getMenuKeySymbolCount() {\n    return menuSymbols.length;\n  }\n\n  public static MenuKeySymbol[] getMenuKeySymbols() {\n    return menuSymbols;\n  }\n\n  public static String getKeyText(MenuKeySymbol sym) {\n    if (VncViewer.os.startsWith(\"mac os x\"))\n      return sym.name.replace(\"_\", \" \");\n    else\n      return KeyEvent.getKeyText(sym.javacode);\n  }\n\n  public static String getMenuKeyValueStr() {\n    String s = \"\";\n    for (int i = 0; i < getMenuKeySymbolCount(); i++) {\n      s += menuSymbols[i].name;\n      if (i < getMenuKeySymbolCount() - 1)\n        s += \", \";\n    }\n    return s;\n  }\n\n  static int getMenuKeyJavaCode() {\n    int menuKeyCode = VK_F8;\n\n    @SuppressWarnings({\"static\"})\n    String menuKeyStr =\n      Configuration.global().getParam(\"menuKey\").getValueStr();\n    for(int i = 0; i < getMenuKeySymbolCount(); i++)\n      if (menuSymbols[i].name.equals(menuKeyStr))\n        menuKeyCode = menuSymbols[i].javacode;\n\n    return menuKeyCode;\n  }\n\n  static int getMenuKeyCode() {\n    int menuKeyCode = 0x42;\n\n    @SuppressWarnings({\"static\"})\n    String menuKeyStr =\n      Configuration.global().getParam(\"menuKey\").getValueStr();\n    for(int i = 0; i < getMenuKeySymbolCount(); i++)\n      if (menuSymbols[i].name.equals(menuKeyStr))\n        menuKeyCode = menuSymbols[i].keycode;\n\n    return menuKeyCode;\n  }\n\n  static int getMenuKeySym() {\n    int menuKeySym = XK_F8;\n\n    @SuppressWarnings({\"static\"})\n    String menuKeyStr =\n      Configuration.global().getParam(\"menuKey\").getValueStr();\n    for(int i = 0; i < getMenuKeySymbolCount(); i++)\n      if (menuSymbols[i].name.equals(menuKeyStr))\n        menuKeySym = menuSymbols[i].keysym;\n\n    return menuKeySym;\n  }\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/OptionsDialog.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.event.*;\nimport java.io.File;\nimport java.lang.reflect.*;\nimport java.text.Format;\nimport java.text.NumberFormat;\nimport javax.swing.*;\nimport javax.swing.border.*;\nimport javax.swing.filechooser.*;\nimport javax.swing.UIManager.*;\nimport javax.swing.text.*;\nimport java.util.*;\nimport java.util.List;\nimport java.util.Map.Entry;\nimport java.util.prefs.*;\n\nimport com.tigervnc.rfb.*;\n\nimport static java.awt.GridBagConstraints.BOTH;\nimport static java.awt.GridBagConstraints.CENTER;\nimport static java.awt.GridBagConstraints.HORIZONTAL;\nimport static java.awt.GridBagConstraints.LINE_END;\nimport static java.awt.GridBagConstraints.LINE_START;\nimport static java.awt.GridBagConstraints.PAGE_START;\nimport static java.awt.GridBagConstraints.NONE;\nimport static java.awt.GridBagConstraints.RELATIVE;\nimport static java.awt.GridBagConstraints.REMAINDER;\nimport static java.awt.GridBagConstraints.VERTICAL;\n\nimport static com.tigervnc.vncviewer.Parameters.*;\n\nclass OptionsDialog extends Dialog {\n\n  private class IntegerDocument extends PlainDocument {\n    private int limit;\n\n    public IntegerDocument(int max) {\n      super();\n      limit = max;\n    }\n\n    public void insertString(int offset, String str, AttributeSet a)\n          throws BadLocationException {\n      if (str == null || !str.matches(\"^[0-9]+$\")) return;\n      if ((getLength() + str.length()) > limit)\n        Toolkit.getDefaultToolkit().beep();\n      else\n        super.insertString(offset, str, a);\n    }\n  }\n\n  private class IntegerTextField extends JFormattedTextField {\n    public IntegerTextField(int digits) {\n      super();\n      setDocument(new IntegerDocument(digits));\n      Font f = getFont();\n      String template = String.format(\"%0\"+digits+\"d\", 0);\n      int w = getFontMetrics(f).stringWidth(template) +\n              getMargin().left + getMargin().right +\n              getInsets().left + getInsets().right;\n      int h = getPreferredSize().height;\n      setPreferredSize(new Dimension(w, h));\n    }\n\n    @Override\n    protected void processFocusEvent(final FocusEvent e) {\n      if (e.isTemporary())\n        return;\n      if (e.getID() == FocusEvent.FOCUS_LOST)\n        if (getText() == null || getText().isEmpty())\n          setValue(null);\n      super.processFocusEvent(e);\n    }\n  }\n\n  private static Map<Object, String> callbacks = new HashMap<Object, String>();\n  /* Compression */\n  JCheckBox autoselectCheckbox;\n\n  ButtonGroup encodingGroup;\n  JRadioButton tightButton;\n  JRadioButton zrleButton;\n  JRadioButton hextileButton;\n  JRadioButton rawButton;\n\n  ButtonGroup colorlevelGroup;\n  JRadioButton fullcolorButton;\n  JRadioButton mediumcolorButton;\n  JRadioButton lowcolorButton;\n  JRadioButton verylowcolorButton;\n\n  JCheckBox compressionCheckbox;\n  JCheckBox jpegCheckbox;\n  JComboBox compressionInput;\n  JComboBox jpegInput;\n\n  /* Security */\n  JCheckBox encNoneCheckbox;\n  JCheckBox encTLSCheckbox;\n  JCheckBox encX509Checkbox;\n  JCheckBox encRSAAESCheckbox;\n  JTextField caInput;\n  JTextField crlInput;\n  JButton caChooser;\n  JButton crlChooser;\n\n  JCheckBox authNoneCheckbox;\n  JCheckBox authVncCheckbox;\n  JCheckBox authPlainCheckbox;\n  JCheckBox authIdentCheckbox;\n  JCheckBox sendLocalUsernameCheckbox;\n\n  /* Input */\n  JCheckBox viewOnlyCheckbox;\n  JCheckBox acceptClipboardCheckbox;\n  JCheckBox sendClipboardCheckbox;\n  JCheckBox disableArrowScrollCheckbox;\n  JComboBox menuKeyChoice;\n\n  /* Screen */\n  JCheckBox desktopSizeCheckbox;\n  JTextField desktopWidthInput;\n  JTextField desktopHeightInput;\n\n  ButtonGroup sizingGroup;\n  JRadioButton remoteResizeButton;\n  JRadioButton remoteScaleButton;\n  JComboBox scalingFactorInput;\n\n  JCheckBox fullScreenCheckbox;\n  JCheckBox fullScreenAllMonitorsCheckbox;\n\n  /* Misc. */\n  JCheckBox sharedCheckbox;\n  JCheckBox alwaysCursorCheckbox;\n  JCheckBox acceptBellCheckbox;\n\n  JComboBox cursorTypeChoice;\n\n  /* SSH */\n  JCheckBox tunnelCheckbox;\n  JCheckBox viaCheckbox;\n  JTextField viaUserInput;\n  JTextField viaHostInput;\n  JTextField viaPortInput;\n  JCheckBox extSSHCheckbox;\n  JTextField sshClientInput;\n  JButton sshClientChooser;\n  JRadioButton sshArgsDefaultButton;\n  JRadioButton sshArgsCustomButton;\n  JTextField sshArgsInput;\n  JTextField sshConfigInput;\n  JTextField sshKeyFileInput;\n  JButton sshConfigChooser;\n  JButton sshKeyFileChooser;\n\n  @SuppressWarnings({\"rawtypes\",\"unchecked\"})\n  public OptionsDialog() {\n    super(true);\n    setTitle(\"TigerVNC options\");\n    setResizable(false);\n\n    getContentPane().setLayout(\n      new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));\n\n    JTabbedPane tabPane = new JTabbedPane();\n    tabPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);\n\n    encodingGroup = new ButtonGroup();\n    colorlevelGroup = new ButtonGroup();\n\n    // tabPane\n    tabPane.addTab(\"Compression\", createCompressionPanel());\n    tabPane.addTab(\"Security\", createSecurityPanel());\n    tabPane.addTab(\"Input\", createInputPanel());\n    tabPane.addTab(\"Screen\", createScreenPanel());\n    tabPane.addTab(\"Misc\", createMiscPanel());\n    tabPane.addTab(\"SSH\", createSshPanel());\n    tabPane.setBorder(BorderFactory.createEmptyBorder());\n    // Resize the tabPane if necessary to prevent scrolling\n    int minWidth = 0;\n    Object tpi = UIManager.get(\"TabbedPane:TabbedPaneTabArea.contentMargins\");\n    if (tpi != null)\n      minWidth += ((Insets)tpi).left + ((Insets)tpi).right;\n    for (int i = 0; i < tabPane.getTabCount(); i++)\n      minWidth += tabPane.getBoundsAt(i).width;\n    int minHeight = tabPane.getPreferredSize().height;\n    if (tabPane.getPreferredSize().width < minWidth)\n      tabPane.setPreferredSize(new Dimension(minWidth, minHeight));\n\n    // button pane\n    JButton okButton = new JButton(\"OK  \\u21B5\");\n    okButton.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        storeOptions();\n        endDialog();\n      }\n    });\n    JButton cancelButton = new JButton(\"Cancel\");\n    cancelButton.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        endDialog();\n      }\n    });\n\n    JPanel buttonPane = new JPanel(new GridLayout(1, 5, 10, 10));\n    buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 5));\n    buttonPane.add(Box.createRigidArea(new Dimension()));\n    buttonPane.add(Box.createRigidArea(new Dimension()));\n    buttonPane.add(Box.createRigidArea(new Dimension()));\n    buttonPane.add(cancelButton);\n    buttonPane.add(okButton);\n\n    this.add(tabPane);\n    this.add(buttonPane);\n    addListeners(this);\n    pack();\n  }\n\n  public static void showDialog(Container c) {\n    OptionsDialog dialog = new OptionsDialog();\n    dialog.show(c);\n  }\n\n  public void show(Container c) {\n    loadOptions();\n    super.showDialog(c);\n  }\n\n  public static void addCallback(String cb, Object obj)\n  {\n    callbacks.put(obj, cb);\n  }\n\n  public static void removeCallback(Object obj)\n  {\n    callbacks.remove(obj);\n  }\n\n  public void endDialog() {\n    super.endDialog();\n    // Making a new dialog is so cheap that it's not worth keeping\n    this.dispose();\n  }\n\n  private void loadOptions()\n  {\n    /* Compression */\n    autoselectCheckbox.setSelected(autoSelect.getValue());\n\n    int encNum = Encodings.encodingNum(preferredEncoding.getValueStr());\n\n    switch (encNum) {\n    case Encodings.encodingTight:\n      tightButton.setSelected(true);\n      break;\n    case Encodings.encodingZRLE:\n      zrleButton.setSelected(true);\n      break;\n    case Encodings.encodingHextile:\n      hextileButton.setSelected(true);\n      break;\n    case Encodings.encodingRaw:\n      rawButton.setSelected(true);\n      break;\n    }\n\n    if (fullColor.getValue())\n      fullcolorButton.setSelected(true);\n    else {\n      switch (lowColorLevel.getValue()) {\n      case 0:\n        verylowcolorButton.setSelected(true);\n        break;\n      case 1:\n        lowcolorButton.setSelected(true);\n        break;\n      case 2:\n        mediumcolorButton.setSelected(true);\n        break;\n      }\n    }\n\n    int digit = 0;\n\n    compressionCheckbox.setSelected(customCompressLevel.getValue());\n    jpegCheckbox.setSelected(!noJpeg.getValue());\n    digit = 0 + compressLevel.getValue();\n    compressionInput.setSelectedItem(digit);\n    digit = 0 + qualityLevel.getValue();\n    jpegInput.setSelectedItem(digit);\n\n    handleAutoselect();\n    handleCompression();\n    handleJpeg();\n    handleAlwaysCursor();\n\n    /* Security */\n    Security security = new Security(SecurityClient.secTypes);\n\n    List<Integer> secTypes;\n    Iterator<Integer> iter;\n\n    List<Integer> secTypesExt;\n    Iterator<Integer> iterExt;\n\n    encNoneCheckbox.setSelected(false);\n    encTLSCheckbox.setSelected(false);\n    encX509Checkbox.setSelected(false);\n    encRSAAESCheckbox.setSelected(false);\n\n    authNoneCheckbox.setSelected(false);\n    authVncCheckbox.setSelected(false);\n    authPlainCheckbox.setSelected(false);\n    authIdentCheckbox.setSelected(false);\n    sendLocalUsernameCheckbox.setSelected(sendLocalUsername.getValue());\n\n    secTypes = security.GetEnabledSecTypes();\n    for (iter = secTypes.iterator(); iter.hasNext(); ) {\n      switch ((Integer)iter.next()) {\n      case Security.secTypeNone:\n        encNoneCheckbox.setSelected(true);\n        authNoneCheckbox.setSelected(true);\n        break;\n      case Security.secTypeVncAuth:\n        encNoneCheckbox.setSelected(true);\n        authVncCheckbox.setSelected(true);\n        break;\n      }\n    }\n\n    secTypesExt = security.GetEnabledExtSecTypes();\n    for (iterExt = secTypesExt.iterator(); iterExt.hasNext(); ) {\n      switch ((Integer)iterExt.next()) {\n      case Security.secTypePlain:\n        encNoneCheckbox.setSelected(true);\n        authPlainCheckbox.setSelected(true);\n        break;\n      case Security.secTypeIdent:\n        encNoneCheckbox.setSelected(true);\n        authIdentCheckbox.setSelected(true);\n        break;\n      case Security.secTypeTLSNone:\n        encTLSCheckbox.setSelected(true);\n        authNoneCheckbox.setSelected(true);\n        break;\n      case Security.secTypeTLSVnc:\n        encTLSCheckbox.setSelected(true);\n        authVncCheckbox.setSelected(true);\n        break;\n      case Security.secTypeTLSPlain:\n        encTLSCheckbox.setSelected(true);\n        authPlainCheckbox.setSelected(true);\n        break;\n      case Security.secTypeTLSIdent:\n        encTLSCheckbox.setSelected(true);\n        authIdentCheckbox.setSelected(true);\n        break;\n      case Security.secTypeX509None:\n        encX509Checkbox.setSelected(true);\n        authNoneCheckbox.setSelected(true);\n        break;\n      case Security.secTypeX509Vnc:\n        encX509Checkbox.setSelected(true);\n        authVncCheckbox.setSelected(true);\n        break;\n      case Security.secTypeX509Plain:\n        encX509Checkbox.setSelected(true);\n        authPlainCheckbox.setSelected(true);\n        break;\n      case Security.secTypeX509Ident:\n        encX509Checkbox.setSelected(true);\n        authIdentCheckbox.setSelected(true);\n        break;\n      case Security.secTypeRA2:\n      case Security.secTypeRA256:\n        encRSAAESCheckbox.setSelected(true);\n      case Security.secTypeRA2ne:\n      case Security.secTypeRAne256:\n        authVncCheckbox.setSelected(true);\n        authPlainCheckbox.setSelected(true);\n        break;\n      }\n    }\n\n    File caFile = new File(CSecurityTLS.X509CA.getValueStr());\n    if (caFile.exists() && caFile.canRead())\n      caInput.setText(caFile.getAbsolutePath());\n    File crlFile = new File(CSecurityTLS.X509CRL.getValueStr());\n    if (crlFile.exists() && crlFile.canRead())\n      crlInput.setText(crlFile.getAbsolutePath());\n\n    handleX509();\n    handleSendLocalUsername();\n\n    /* Input */\n    viewOnlyCheckbox.setSelected(viewOnly.getValue());\n    acceptClipboardCheckbox.setSelected(acceptClipboard.getValue());\n    sendClipboardCheckbox.setSelected(sendClipboard.getValue());\n    disableArrowScrollCheckbox.setSelected(disableArrowScroll.getValue());\n\n    menuKeyChoice.setSelectedIndex(0);\n\n    String menuKeyStr = menuKey.getValueStr();\n    for (int i = 0; i < menuKeyChoice.getItemCount(); i++)\n      if (menuKeyStr.equals(menuKeyChoice.getItemAt(i)))\n        menuKeyChoice.setSelectedIndex(i);\n\n    /* Screen */\n    String width, height;\n\n    if (desktopSize.getValueStr().isEmpty() ||\n        desktopSize.getValueStr().split(\"x\").length != 2) {\n      desktopSizeCheckbox.setSelected(false);\n      desktopWidthInput.setText(\"1024\");\n      desktopHeightInput.setText(\"768\");\n    } else {\n      desktopSizeCheckbox.setSelected(true);\n      width = desktopSize.getValueStr().split(\"x\")[0];\n      desktopWidthInput.setText(width);\n      height = desktopSize.getValueStr().split(\"x\")[1];\n      desktopHeightInput.setText(height);\n    }\n    if (remoteResize.getValue())\n      remoteResizeButton.setSelected(true);\n    else\n      remoteScaleButton.setSelected(true);\n    fullScreenCheckbox.setSelected(fullScreen.getValue());\n    fullScreenAllMonitorsCheckbox.setSelected(fullScreenAllMonitors.getValue());\n\n    scalingFactorInput.setSelectedItem(\"100%\");\n    String scaleStr = scalingFactor.getValueStr();\n    if (scaleStr.matches(\"^[0-9]+$\"))\n      scaleStr = scaleStr.concat(\"%\");\n    if (scaleStr.matches(\"^FixedRatio$\"))\n      scaleStr = new String(\"Fixed Aspect Ratio\");\n    for (int i = 0; i < scalingFactorInput.getItemCount(); i++)\n      if (scaleStr.equals(scalingFactorInput.getItemAt(i)))\n        scalingFactorInput.setSelectedIndex(i);\n\n    handleDesktopSize();\n\n    /* Misc. */\n    sharedCheckbox.setSelected(shared.getValue());\n    alwaysCursorCheckbox.setSelected(alwaysCursor.getValue());\n    String cursorTypeStr = cursorType.getValueStr();\n    cursorTypeChoice.setSelectedItem(cursorTypeStr);\n    acceptBellCheckbox.setSelected(acceptBell.getValue());\n\n    /* SSH */\n    File f;\n    tunnelCheckbox.setSelected(tunnel.getValue() || !via.getValueStr().isEmpty());\n    viaCheckbox.setSelected(!via.getValueStr().isEmpty());\n    if (viaCheckbox.isSelected()) {\n      viaUserInput.setText(Tunnel.getSshUser());\n      viaHostInput.setText(Tunnel.getSshHost());\n      viaPortInput.setText(Integer.toString(Tunnel.getSshPort()));\n    }\n    extSSHCheckbox.setSelected(extSSH.getValue());\n    f = new File(extSSHClient.getValueStr());\n    if (f.exists() && f.isFile() && f.canExecute())\n      sshClientInput.setText(f.getAbsolutePath());\n    if (extSSHArgs.getValueStr().isEmpty()) {\n      sshArgsDefaultButton.setSelected(true);\n    } else {\n      sshArgsCustomButton.setSelected(true);\n      sshArgsInput.setText(extSSHArgs.getValueStr());\n    }\n    f = new File(sshKeyFile.getValueStr());\n    if (f.exists() && f.isFile() && f.canRead())\n      sshKeyFileInput.setText(f.getAbsolutePath());\n    f = new File(sshConfig.getValueStr());\n    if (f.exists() && f.isFile() && f.canRead())\n      sshConfigInput.setText(f.getAbsolutePath());\n\n    handleTunnel();\n    handleVia();\n    handleExtSSH();\n    handleRfbState();\n  }\n\n  private void storeOptions() {\n    /* Compression */\n    autoSelect.setParam(autoselectCheckbox.isSelected());\n\n    if (tightButton.isSelected())\n      preferredEncoding.setParam(Encodings.encodingName(Encodings.encodingTight));\n    else if (zrleButton.isSelected())\n      preferredEncoding.setParam(Encodings.encodingName(Encodings.encodingZRLE));\n    else if (hextileButton.isSelected())\n      preferredEncoding.setParam(Encodings.encodingName(Encodings.encodingHextile));\n    else if (rawButton.isSelected())\n      preferredEncoding.setParam(Encodings.encodingName(Encodings.encodingRaw));\n\n    fullColor.setParam(fullcolorButton.isSelected());\n    if (verylowcolorButton.isSelected())\n      lowColorLevel.setParam(0);\n    else if (lowcolorButton.isSelected())\n      lowColorLevel.setParam(1);\n    else if (mediumcolorButton.isSelected())\n      lowColorLevel.setParam(2);\n\n    customCompressLevel.setParam(compressionCheckbox.isSelected());\n    noJpeg.setParam(!jpegCheckbox.isSelected());\n    compressLevel.setParam((Integer)compressionInput.getSelectedItem());\n    qualityLevel.setParam((Integer)jpegInput.getSelectedItem());\n\n    /* Security */\n    Security security = new Security();\n\n    /* Process security types which don't use encryption */\n    if (encNoneCheckbox.isSelected()) {\n      if (authNoneCheckbox.isSelected())\n        security.EnableSecType(Security.secTypeNone);\n      if (authVncCheckbox.isSelected()) {\n        security.EnableSecType(Security.secTypeVncAuth);\n        security.EnableSecType(Security.secTypeRA2ne);\n        security.EnableSecType(Security.secTypeRAne256);\n      }\n      if (authPlainCheckbox.isSelected()) {\n        security.EnableSecType(Security.secTypePlain);\n        security.EnableSecType(Security.secTypeRA2ne);\n        security.EnableSecType(Security.secTypeRAne256);\n      }\n      if (authIdentCheckbox.isSelected())\n        security.EnableSecType(Security.secTypeIdent);\n    }\n\n    /* Process security types which use TLS encryption */\n    if (encTLSCheckbox.isSelected()) {\n      if (authNoneCheckbox.isSelected())\n        security.EnableSecType(Security.secTypeTLSNone);\n      if (authVncCheckbox.isSelected())\n        security.EnableSecType(Security.secTypeTLSVnc);\n      if (authPlainCheckbox.isSelected())\n        security.EnableSecType(Security.secTypeTLSPlain);\n      if (authIdentCheckbox.isSelected())\n        security.EnableSecType(Security.secTypeTLSIdent);\n    }\n\n    /* Process security types which use X509 encryption */\n    if (encX509Checkbox.isSelected()) {\n      if (authNoneCheckbox.isSelected())\n        security.EnableSecType(Security.secTypeX509None);\n      if (authVncCheckbox.isSelected())\n        security.EnableSecType(Security.secTypeX509Vnc);\n      if (authPlainCheckbox.isSelected())\n        security.EnableSecType(Security.secTypeX509Plain);\n      if (authIdentCheckbox.isSelected())\n        security.EnableSecType(Security.secTypeX509Ident);\n    }\n\n    if (encRSAAESCheckbox.isSelected()) {\n      security.EnableSecType(Security.secTypeRA2);\n      security.EnableSecType(Security.secTypeRA256);\n    }\n\n    if (authIdentCheckbox.isSelected() ||\n        authPlainCheckbox.isSelected()) {\n      sendLocalUsername.setParam(sendLocalUsernameCheckbox.isSelected());\n    }\n\n    SecurityClient.secTypes.setParam(security.ToString());\n\n    File caFile = new File(caInput.getText());\n    if (caFile.exists() && caFile.canRead())\n      CSecurityTLS.X509CA.setParam(caFile.getAbsolutePath());\n    File crlFile = new File(crlInput.getText());\n    if (crlFile.exists() && crlFile.canRead())\n      CSecurityTLS.X509CRL.setParam(crlFile.getAbsolutePath());\n\n    /* Input */\n    viewOnly.setParam(viewOnlyCheckbox.isSelected());\n    acceptClipboard.setParam(acceptClipboardCheckbox.isSelected());\n    sendClipboard.setParam(sendClipboardCheckbox.isSelected());\n    disableArrowScroll.setParam(disableArrowScrollCheckbox.isSelected());\n\n    String menuKeyStr =\n      MenuKey.getMenuKeySymbols()[menuKeyChoice.getSelectedIndex()].name;\n    menuKey.setParam(menuKeyStr);\n\n    /* Screen */\n    if (desktopSizeCheckbox.isSelected() &&\n        !desktopWidthInput.getText().isEmpty() &&\n        !desktopHeightInput.getText().isEmpty()) {\n      String width = desktopWidthInput.getText();\n      String height = desktopHeightInput.getText();\n      desktopSize.setParam(width.concat(\"x\").concat(height));\n    } else {\n      desktopSize.setParam(\"\");\n    }\n    remoteResize.setParam(remoteResizeButton.isSelected());\n    fullScreen.setParam(fullScreenCheckbox.isSelected());\n    fullScreenAllMonitors.setParam(fullScreenAllMonitorsCheckbox.isSelected());\n\n    String scaleStr =\n      ((String)scalingFactorInput.getSelectedItem()).replace(\"%\", \"\");\n    scaleStr = scaleStr.replace(\"Fixed Aspect Ratio\", \"FixedRatio\");\n    scalingFactor.setParam(scaleStr);\n\n    /* Misc. */\n    shared.setParam(sharedCheckbox.isSelected());\n    alwaysCursor.setParam(alwaysCursorCheckbox.isSelected());\n    acceptBell.setParam(acceptBellCheckbox.isSelected());\n    cursorType.setParam((String)cursorTypeChoice.getSelectedItem());\n\n    /* SSH */\n    tunnel.setParam(tunnelCheckbox.isSelected());\n    if (viaCheckbox.isSelected() &&\n        !viaUserInput.getText().isEmpty() &&\n        !viaHostInput.getText().isEmpty() &&\n        !viaPortInput.getText().isEmpty()) {\n      String sshUser = viaUserInput.getText();\n      String sshHost = viaHostInput.getText();\n      String sshPort = viaPortInput.getText();\n      String viaStr = sshUser.concat(\"@\").concat(sshHost).concat(\":\").concat(sshPort);\n      via.setParam(viaStr);\n    } else {\n      via.setParam(\"\");\n    }\n    extSSH.setParam(extSSHCheckbox.isSelected());\n    if (!sshClientInput.getText().isEmpty())\n      extSSHClient.setParam(sshClientInput.getText());\n    if (sshArgsCustomButton.isSelected() &&\n        !sshArgsInput.getText().isEmpty()) {\n        extSSHArgs.setParam(sshArgsInput.getText());\n    } else {\n      extSSHArgs.setParam(new String());\n    }\n    if (!sshConfigInput.getText().isEmpty())\n      sshConfig.setParam(sshConfigInput.getText());\n    if (!sshKeyFileInput.getText().isEmpty())\n      sshKeyFile.setParam(sshKeyFileInput.getText());\n\n    try {\n      for (Map.Entry<Object, String> iter : callbacks.entrySet()) {\n        Object obj = iter.getKey();\n        Method cb = obj.getClass().getMethod(iter.getValue(), new Class[]{});\n        if (cb == null)\n          vlog.info(obj.getClass().getName());\n        cb.invoke(obj);\n      }\n    } catch (NoSuchMethodException e) {\n      vlog.error(\"NoSuchMethodException: \"+e.getMessage());\n    } catch (IllegalAccessException e) {\n      vlog.error(\"IllegalAccessException: \"+e.getMessage());\n    } catch (InvocationTargetException e) {\n      vlog.error(\"InvocationTargetException: \"+e.getMessage());\n    }\n  }\n\n  private JPanel createCompressionPanel() {\n    JPanel FormatPanel = new JPanel();\n    FormatPanel.setLayout(new BoxLayout(FormatPanel,\n                                        BoxLayout.PAGE_AXIS));\n    FormatPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));\n\n    JPanel autoSelectPane = new JPanel();\n    autoSelectPane.setLayout(new BoxLayout(autoSelectPane,\n                                           BoxLayout.LINE_AXIS));\n    autoSelectPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));\n    autoselectCheckbox = new JCheckBox(\"Auto Select\");\n    autoselectCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleAutoselect();\n      }\n    });\n    autoSelectPane.add(autoselectCheckbox);\n    autoSelectPane.add(Box.createHorizontalGlue());\n\n    JPanel encodingPanel = new JPanel(new GridLayout(4, 1));\n    encodingPanel.setBorder(BorderFactory.createTitledBorder(\"Preferred encoding\"));\n    tightButton = new GroupedJRadioButton(\"Tight\", encodingGroup, encodingPanel);\n    zrleButton = new GroupedJRadioButton(\"ZRLE\", encodingGroup, encodingPanel);\n    hextileButton = new GroupedJRadioButton(\"Hextile\", encodingGroup, encodingPanel);\n    rawButton = new GroupedJRadioButton(\"Raw\", encodingGroup, encodingPanel);\n\n    JPanel colorPanel = new JPanel(new GridLayout(4, 1));\n    colorPanel.setBorder(BorderFactory.createTitledBorder(\"Color level\"));\n    fullcolorButton = new GroupedJRadioButton(\"Full\", colorlevelGroup, colorPanel);\n    mediumcolorButton = new GroupedJRadioButton(\"Medium\", colorlevelGroup, colorPanel);\n    lowcolorButton = new GroupedJRadioButton(\"Low\", colorlevelGroup, colorPanel);\n    verylowcolorButton = new GroupedJRadioButton(\"Very low\", colorlevelGroup, colorPanel);\n\n    JPanel encodingPane = new JPanel(new GridLayout(1, 2, 5, 0));\n    encodingPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));\n    encodingPane.add(encodingPanel);\n    encodingPane.add(colorPanel);\n\n    JPanel tightPanel = new JPanel(new GridBagLayout());\n    compressionCheckbox = new JCheckBox(\"Custom Compression Level\");\n    compressionCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleCompression();\n      }\n    });\n    Object[] compressionLevels = { 1, 2, 3, 4, 5, 6 };\n    compressionInput = new MyJComboBox(compressionLevels);\n    ((MyJComboBox)compressionInput).setDocument(new IntegerDocument(1));\n    compressionInput.setPrototypeDisplayValue(\"0.\");\n    compressionInput.setEditable(true);\n    JLabel compressionLabel =\n      new JLabel(\"Level (0=fast, 9=best)\");\n    jpegCheckbox = new JCheckBox(\"Allow JPEG Compression\");\n    jpegCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleJpeg();\n      }\n    });\n    Object[] qualityLevels = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n    jpegInput = new MyJComboBox(qualityLevels);\n    jpegInput.setPrototypeDisplayValue(\"0.\");\n    JLabel qualityLabel = new JLabel(\"Quality (0=poor, 9=best)\");\n\n    tightPanel.add(compressionCheckbox,\n                   new GridBagConstraints(0, 0,\n                                          REMAINDER, 1,\n                                          LIGHT, LIGHT,\n                                          LINE_START, NONE,\n                                          new Insets(0, 0, 0, 0),\n                                          NONE, NONE));\n    int indent = getButtonLabelInset(compressionCheckbox);\n    tightPanel.add(compressionInput,\n                   new GridBagConstraints(0, 1,\n                                          1, 1,\n                                          LIGHT, LIGHT,\n                                          LINE_START, NONE,\n                                          new Insets(0, indent, 0, 0),\n                                          NONE, NONE));\n    tightPanel.add(compressionLabel,\n                   new GridBagConstraints(1, 1,\n                                          1, 1,\n                                          HEAVY, LIGHT,\n                                          LINE_START, HORIZONTAL,\n                                          new Insets(0, 5, 0, 0),\n                                          NONE, NONE));\n    tightPanel.add(jpegCheckbox,\n                   new GridBagConstraints(0, 2,\n                                          REMAINDER, 1,\n                                          LIGHT, LIGHT, \n                                          LINE_START, NONE,\n                                          new Insets(5, 0, 0, 0),\n                                          NONE, NONE));\n    indent = getButtonLabelInset(jpegCheckbox);\n    tightPanel.add(jpegInput,\n                   new GridBagConstraints(0, 3,\n                                          1, 1,\n                                          LIGHT, LIGHT,\n                                          LINE_START, NONE,\n                                          new Insets(0, indent, 0, 0),\n                                          NONE, NONE));\n    tightPanel.add(qualityLabel,\n                   new GridBagConstraints(1, 3,\n                                          1, 1,\n                                          HEAVY, NONE,\n                                          LINE_START, HORIZONTAL,\n                                          new Insets(0, 5, 0, 0),\n                                          NONE, NONE));\n    tightPanel.add(Box.createRigidArea(new Dimension(5,0)),\n                   new GridBagConstraints(0, 4,\n                                          REMAINDER, REMAINDER,\n                                          HEAVY, HEAVY,\n                                          LINE_START, BOTH,\n                                          new Insets(0, 0, 0, 0),\n                                          NONE, NONE));\n    FormatPanel.add(autoSelectPane);\n    FormatPanel.add(encodingPane);\n    FormatPanel.add(tightPanel);\n    return FormatPanel;\n  }\n\n  private JPanel createSecurityPanel() {\n    JPanel SecPanel = new JPanel();\n    SecPanel.setLayout(new BoxLayout(SecPanel,\n                                     BoxLayout.PAGE_AXIS));\n    SecPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));\n\n    JPanel vencryptPane = new JPanel();\n    vencryptPane.setLayout(new BoxLayout(vencryptPane,\n                                         BoxLayout.LINE_AXIS));\n    vencryptPane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));\n\n    JPanel encrPanel = new JPanel(new GridBagLayout());\n    encrPanel.setBorder(BorderFactory.createTitledBorder(\"Encryption\"));\n    encNoneCheckbox = new JCheckBox(\"None\");\n    encTLSCheckbox = new JCheckBox(\"Anonymous TLS\");\n    encX509Checkbox = new JCheckBox(\"TLS with X.509 certificates\");\n    encX509Checkbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleX509();\n      }\n    });\n    JLabel caLabel = new JLabel(\"X.509 CA Certificate\");\n    caInput = new JTextField();\n    caChooser = new JButton(\"Browse\");\n    caChooser.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        JComponent c = ((JButton)e.getSource()).getRootPane();\n        File dflt = new File(CSecurityTLS.X509CA.getValueStr());\n        FileNameExtensionFilter filter =\n          new FileNameExtensionFilter(\"X.509 certificate\", \"crt\", \"cer\", \"pem\");\n        File f = showChooser(\"Path to X509 CA certificate\", dflt, c, filter);\n        if (f != null && f.exists() && f.canRead())\n          caInput.setText(f.getAbsolutePath());\n      }\n    });\n    JLabel crlLabel = new JLabel(\"X.509 CRL file\");\n    crlInput = new JTextField();\n    crlChooser = new JButton(\"Browse\");\n    crlChooser.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        JComponent c = ((JButton)e.getSource()).getRootPane();\n        File dflt = new File(CSecurityTLS.X509CRL.getValueStr());\n        FileNameExtensionFilter filter =\n          new FileNameExtensionFilter(\"X.509 CRL\", \"crl\");\n        File f = showChooser(\"Path to X509 CRL file\", dflt, c, filter);\n        if (f != null && f.exists() && f.canRead())\n          crlInput.setText(f.getAbsolutePath());\n      }\n    });\n    encRSAAESCheckbox = new JCheckBox(\"RSA-AES\");\n    encRSAAESCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleRSAAES();\n      }\n    });\n    encrPanel.add(encNoneCheckbox,\n                  new GridBagConstraints(0, 0,\n                                         REMAINDER, 1,\n                                         HEAVY, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 4, 0),\n                                         NONE, NONE));\n    encrPanel.add(encTLSCheckbox,\n                  new GridBagConstraints(0, 1,\n                                         REMAINDER, 1,\n                                         HEAVY, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 4, 0),\n                                         NONE, NONE));\n    encrPanel.add(encX509Checkbox,\n                  new GridBagConstraints(0, 2,\n                                         3, 1,\n                                         HEAVY, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 0, 0),\n                                         NONE, NONE));\n    int indent = getButtonLabelInset(encX509Checkbox);\n    encrPanel.add(caLabel,\n                  new GridBagConstraints(0, 3,\n                                         1, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_END, NONE,\n                                         new Insets(0, indent, 5, 0),\n                                         0, 0));\n    encrPanel.add(caInput,\n                  new GridBagConstraints(1, 3,\n                                         1, 1,\n                                         HEAVY, LIGHT,\n                                         LINE_START, HORIZONTAL,\n                                         new Insets(0, 5, 5, 0),\n                                         0, 0));\n    encrPanel.add(caChooser,\n                  new GridBagConstraints(2, 3,\n                                         1, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, VERTICAL,\n                                         new Insets(0, 5, 5, 0),\n                                         0, 0));\n    encrPanel.add(crlLabel,\n                  new GridBagConstraints(0, 4,\n                                         1, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_END, NONE,\n                                         new Insets(0, indent, 0, 0),\n                                         0, 0));\n    encrPanel.add(crlInput,\n                  new GridBagConstraints(1, 4,\n                                         1, 1,\n                                         HEAVY, LIGHT,\n                                         LINE_START, HORIZONTAL,\n                                         new Insets(0, 5, 0, 0),\n                                         0, 0));\n    encrPanel.add(crlChooser,\n                  new GridBagConstraints(2, 4,\n                                         1, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, VERTICAL,\n                                         new Insets(0, 5, 0, 0),\n                                         0, 0));\n    encrPanel.add(encRSAAESCheckbox,\n                  new GridBagConstraints(0, 5,\n                                         REMAINDER, 1,\n                                         HEAVY, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 4, 0),\n                                         NONE, NONE));\n\n    JPanel authPanel = new JPanel(new GridBagLayout());\n    authPanel.setBorder(BorderFactory.createTitledBorder(\"Authentication\"));\n\n    authNoneCheckbox = new JCheckBox(\"None\");\n    authVncCheckbox = new JCheckBox(\"Standard VNC\");\n    authPlainCheckbox = new JCheckBox(\"Plaintext\");\n    authPlainCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleSendLocalUsername();\n      }\n    });\n    authIdentCheckbox = new JCheckBox(\"Ident\");\n    authIdentCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleSendLocalUsername();\n      }\n    });\n    sendLocalUsernameCheckbox = new JCheckBox(\"Send Local Username\");\n    authPanel.add(authNoneCheckbox,\n                  new GridBagConstraints(0, 0,\n                                         REMAINDER, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 4, 0),\n                                         NONE, NONE));\n    authPanel.add(authVncCheckbox,\n                  new GridBagConstraints(0, 1,\n                                         REMAINDER, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 4, 0),\n                                         NONE, NONE));\n    authPanel.add(authPlainCheckbox,\n                  new GridBagConstraints(0, 2,\n                                         1, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 2, 0),\n                                         NONE, NONE));\n    authPanel.add(authIdentCheckbox,\n                  new GridBagConstraints(0, 3,\n                                         1, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(2, 0, 0, 0),\n                                         NONE, NONE));\n    authPanel.add(sendLocalUsernameCheckbox,\n                  new GridBagConstraints(1, 2,\n                                         1, 2,\n                                         HEAVY, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(2, 20, 2, 0),\n                                         NONE, NONE));\n\n    SecPanel.add(vencryptPane,\n                 new GridBagConstraints(0, 0,\n                                        REMAINDER, 1,\n                                        LIGHT, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, 0, 4, 0),\n                                        NONE, NONE));\n    SecPanel.add(encrPanel,\n                 new GridBagConstraints(0, 1,\n                                        REMAINDER, 1,\n                                        LIGHT, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, 0, 4, 0),\n                                        NONE, NONE));\n    SecPanel.add(authPanel,\n                 new GridBagConstraints(0, 2,\n                                        REMAINDER, 1,\n                                        LIGHT, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, 0, 4, 0),\n                                        NONE, NONE));\n    SecPanel.add(Box.createRigidArea(new Dimension(0,0)),\n                 new GridBagConstraints(0, RELATIVE,\n                                        REMAINDER, REMAINDER,\n                                        HEAVY, HEAVY,\n                                        LINE_START, BOTH,\n                                        new Insets(0, 0, 0, 0),\n                                        NONE, NONE));\n    return SecPanel;\n  }\n\n  private JPanel createInputPanel() {\n    JPanel inputPanel = new JPanel(new GridBagLayout());\n    inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));\n\n    viewOnlyCheckbox = new JCheckBox(\"View only (ignore mouse and keyboard)\");\n    acceptClipboardCheckbox = new JCheckBox(\"Accept clipboard from server\");\n    sendClipboardCheckbox = new JCheckBox(\"Send clipboard to server\");\n    disableArrowScrollCheckbox = new JCheckBox(\"Disable arrow-key scrolling when scrollbars visible\");\n    JLabel menuKeyLabel = new JLabel(\"Menu key\");\n    String[] menuKeys = new String[MenuKey.getMenuKeySymbolCount()];\n    //menuKeys[0] = \"None\";\n    for (int i = 0; i < MenuKey.getMenuKeySymbolCount(); i++)\n      menuKeys[i] = MenuKey.getKeyText(MenuKey.getMenuKeySymbols()[i]);\n    menuKeyChoice = new JComboBox(menuKeys);\n\n    inputPanel.add(viewOnlyCheckbox,\n                   new GridBagConstraints(0, 0,\n                                          REMAINDER, 1,\n                                          HEAVY, LIGHT,\n                                          LINE_START, NONE,\n                                          new Insets(0, 0, 4, 0),\n                                          NONE, NONE));\n    inputPanel.add(acceptClipboardCheckbox,\n                   new GridBagConstraints(0, 1,\n                                          REMAINDER, 1,\n                                          HEAVY, LIGHT,\n                                          LINE_START, NONE,\n                                          new Insets(0, 0, 4, 0),\n                                          NONE, NONE));\n    inputPanel.add(sendClipboardCheckbox,\n                   new GridBagConstraints(0, 2,\n                                          REMAINDER, 1,\n                                          HEAVY, LIGHT,\n                                          LINE_START, NONE,\n                                          new Insets(0, 0, 4, 0),\n                                          NONE, NONE));\n    inputPanel.add(disableArrowScrollCheckbox,\n                   new GridBagConstraints(0, 3,\n                                          REMAINDER, 1,\n                                          HEAVY, LIGHT,\n                                          LINE_START, NONE,\n                                          new Insets(0, 0, 4, 0),\n                                          NONE, NONE));\n    inputPanel.add(menuKeyLabel,\n                   new GridBagConstraints(0, 4,\n                                          1, 1,\n                                          LIGHT, LIGHT,\n                                          LINE_START, NONE,\n                                          new Insets(0, 0, 0, 0),\n                                          NONE, NONE));\n    inputPanel.add(menuKeyChoice,\n                   new GridBagConstraints(1, 4,\n                                          1, 1,\n                                          HEAVY, LIGHT,\n                                          LINE_START, NONE,\n                                          new Insets(0, 5, 0, 0),\n                                          NONE, NONE));\n    inputPanel.add(Box.createRigidArea(new Dimension(5, 0)),\n                   new GridBagConstraints(0, 4,\n                                          REMAINDER, REMAINDER,\n                                          HEAVY, HEAVY,\n                                          LINE_START, BOTH,\n                                          new Insets(0, 0, 0, 0),\n                                          NONE, NONE));\n    return inputPanel;\n  }\n\n  private JPanel createScreenPanel() {\n    JPanel ScreenPanel = new JPanel(new GridBagLayout());\n    ScreenPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));\n\n    JPanel SizingPanel = new JPanel(new GridBagLayout());\n    SizingPanel.setBorder(BorderFactory.createTitledBorder(\"Desktop Sizing\"));\n    desktopSizeCheckbox = new JCheckBox(\"Resize remote session on connect\");\n    desktopSizeCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleDesktopSize();\n      }\n    });\n    desktopWidthInput = new IntegerTextField(5);\n    desktopHeightInput = new IntegerTextField(5);\n    JPanel desktopSizePanel =\n      new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));\n    desktopSizePanel.add(desktopWidthInput);\n    desktopSizePanel.add(new JLabel(\" x \"));\n    desktopSizePanel.add(desktopHeightInput);\n    sizingGroup = new ButtonGroup();\n    remoteResizeButton =\n      new JRadioButton(\"Resize remote session to the local window\");\n    sizingGroup.add(remoteResizeButton);\n    remoteScaleButton =\n      new JRadioButton(\"Scale remote session to the local window\");\n    sizingGroup.add(remoteScaleButton);\n    remoteResizeButton.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleRemoteResize();\n      }\n    });\n    JLabel scalingFactorLabel = new JLabel(\"Scaling Factor\");\n    Object[] scalingFactors = {\n      \"Auto\", \"Fixed Aspect Ratio\", \"50%\", \"75%\", \"95%\", \"100%\", \"105%\",\n      \"125%\", \"150%\", \"175%\", \"200%\", \"250%\", \"300%\", \"350%\", \"400%\" };\n    scalingFactorInput = new MyJComboBox(scalingFactors);\n    scalingFactorInput.setEditable(true);\n    fullScreenCheckbox = new JCheckBox(\"Full-screen mode\");\n    fullScreenAllMonitorsCheckbox =\n      new JCheckBox(\"Enable full-screen mode over all monitors\");\n    SizingPanel.add(desktopSizeCheckbox,\n                    new GridBagConstraints(0, 0,\n                                           REMAINDER, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 0, 0, 0),\n                                           NONE, NONE));\n    int indent = getButtonLabelInset(desktopSizeCheckbox);\n    SizingPanel.add(desktopSizePanel,\n                    new GridBagConstraints(0, 1,\n                                           REMAINDER, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, indent, 0, 0),\n                                           NONE, NONE));\n    SizingPanel.add(remoteResizeButton,\n                    new GridBagConstraints(0, 2,\n                                           REMAINDER, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 0, 4, 0),\n                                           NONE, NONE));\n    SizingPanel.add(remoteScaleButton,\n                    new GridBagConstraints(0, 3,\n                                           REMAINDER, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 0, 4, 0),\n                                           NONE, NONE));\n    indent = getButtonLabelInset(remoteScaleButton);\n    SizingPanel.add(scalingFactorLabel,\n                    new GridBagConstraints(0, 4,\n                                           1, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, indent, 4, 0),\n                                           NONE, NONE));\n    SizingPanel.add(scalingFactorInput,\n                    new GridBagConstraints(1, 4,\n                                           1, 1,\n                                           HEAVY, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 5, 4, 0),\n                                           NONE, NONE));\n    ScreenPanel.add(SizingPanel,\n                    new GridBagConstraints(0, 0,\n                                           REMAINDER, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, HORIZONTAL,\n                                           new Insets(0, 0, 4, 0),\n                                           NONE, NONE));\n    ScreenPanel.add(fullScreenCheckbox,\n                    new GridBagConstraints(0, 1,\n                                           REMAINDER, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 0, 4, 0),\n                                           NONE, NONE));\n    indent = getButtonLabelInset(fullScreenCheckbox);\n    ScreenPanel.add(fullScreenAllMonitorsCheckbox,\n                    new GridBagConstraints(0, 2,\n                                           REMAINDER, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, indent, 4, 0),\n                                           NONE, NONE));\n    ScreenPanel.add(Box.createRigidArea(new Dimension(5, 0)),\n                    new GridBagConstraints(0, 3,\n                                           REMAINDER, REMAINDER,\n                                           HEAVY, HEAVY,\n                                           LINE_START, BOTH,\n                                           new Insets(0, 0, 0, 0),\n                                           NONE, NONE));\n    return ScreenPanel;\n  }\n\n  private JPanel createMiscPanel() {\n    JPanel MiscPanel = new JPanel(new GridBagLayout());\n    MiscPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));\n    sharedCheckbox =\n      new JCheckBox(\"Shared (don't disconnect other viewers)\");\n    alwaysCursorCheckbox = new JCheckBox(\"Show local cursor when not provided by server\");\n    alwaysCursorCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleAlwaysCursor();\n      }\n    });\n    JLabel cursorTypeLabel = new JLabel(\"Cursor type:\");\n    String[] cursorTypes = {\"Dot\", \"System\"};\n    cursorTypeChoice = new MyJComboBox(cursorTypes);\n    cursorTypeChoice.setPrototypeDisplayValue(\"System.\");\n    acceptBellCheckbox = new JCheckBox(\"Beep when requested by the server\");\n    MiscPanel.add(sharedCheckbox,\n                  new GridBagConstraints(0, 0,\n                                         REMAINDER, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 4, 0),\n                                         NONE, NONE));\n    MiscPanel.add(alwaysCursorCheckbox,\n                  new GridBagConstraints(0, 1,\n                                         REMAINDER, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 4, 0),\n                                         NONE, NONE));\n    MiscPanel.add(cursorTypeLabel,\n                  new GridBagConstraints(0, 2,\n                                         1, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 4, 0),\n                                         NONE, NONE));\n    MiscPanel.add(cursorTypeChoice,\n                  new GridBagConstraints(1, 2,\n                                         1, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 5, 4, 0),\n                                         NONE, NONE));\n    MiscPanel.add(acceptBellCheckbox,\n                  new GridBagConstraints(0, 3,\n                                         REMAINDER, 1,\n                                         LIGHT, LIGHT,\n                                         LINE_START, NONE,\n                                         new Insets(0, 0, 4, 0),\n                                         NONE, NONE));\n    MiscPanel.add(Box.createRigidArea(new Dimension(5, 0)),\n                  new GridBagConstraints(0, 4,\n                                         REMAINDER, REMAINDER,\n                                         HEAVY, HEAVY,\n                                         LINE_START, BOTH,\n                                         new Insets(0, 0, 0, 0),\n                                         NONE, NONE));\n    return MiscPanel;\n  }\n\n  private JPanel createSshPanel() {\n    JPanel sshPanel = new JPanel(new GridBagLayout());\n    sshPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));\n    ButtonGroup sshArgsGroup = new ButtonGroup();\n    tunnelCheckbox = new JCheckBox(\"Tunnel VNC over SSH\");\n    tunnelCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleTunnel();\n      }\n    });\n\n    JPanel tunnelPanel = new JPanel(new GridBagLayout());\n\n    viaCheckbox = new JCheckBox(\"Use SSH gateway\");\n    viaCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleVia();\n      }\n    });\n    JLabel sshUserLabel = new JLabel(\"Username\");\n    viaUserInput = new JTextField();\n    JLabel sshUserAtLabel = new JLabel(\"@\");\n    JLabel sshHostLabel = new JLabel(\"Hostname (or IP address)\");\n    viaHostInput = new JTextField(\"\");\n    JLabel sshPortLabel = new JLabel(\"Port\");\n    viaPortInput = new IntegerTextField(5);\n\n    extSSHCheckbox = new JCheckBox(\"Use external SSH client\");\n    extSSHCheckbox.addItemListener(new ItemListener() {\n      public void itemStateChanged(ItemEvent e) {\n        handleExtSSH();\n      }\n    });\n    sshClientInput = new JTextField();\n    sshClientChooser = new JButton(\"Browse\");\n    sshClientChooser.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        JComponent c = ((JButton)e.getSource()).getRootPane();\n        File dflt = new File(extSSHClient.getValueStr());\n        File f = showChooser(\"Path to external SSH client\", dflt, c);\n        if (f != null && f.exists() && f.isFile() && f.canExecute())\n          sshClientInput.setText(f.getAbsolutePath());\n      }\n    });\n    JLabel sshConfigLabel = new JLabel(\"SSH config file\");\n    sshConfigInput = new JTextField();\n    sshConfigChooser = new JButton(\"Browse\");\n    sshConfigChooser.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        JComponent c = ((JButton)e.getSource()).getRootPane();\n        File dflt = new File(sshConfig.getValueStr());\n        File f = showChooser(\"Path to OpenSSH client config file\", dflt, c);\n        if (f != null && f.exists() && f.isFile() && f.canRead())\n          sshConfigInput.setText(f.getAbsolutePath());\n      }\n    });\n    JLabel sshKeyFileLabel = new JLabel(\"SSH identity file\");\n    sshKeyFileInput = new JTextField();\n    sshKeyFileChooser = new JButton(\"Browse\");\n    sshKeyFileChooser.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        JComponent c = ((JButton)e.getSource()).getRootPane();\n        File f = showChooser(\"Path to SSH key file\", null, c);\n        if (f != null && f.exists() && f.isFile() && f.canRead())\n          sshKeyFileInput.setText(f.getAbsolutePath());\n      }\n    });\n    JPanel sshArgsPanel = new JPanel(new GridBagLayout());\n    JLabel sshArgsLabel = new JLabel(\"Arguments:\");\n    sshArgsDefaultButton = new GroupedJRadioButton(\"Default\", sshArgsGroup, sshArgsPanel);\n    sshArgsDefaultButton.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        sshArgsInput.setEnabled(sshArgsCustomButton.isSelected());\n      }\n    });\n    sshArgsCustomButton = new GroupedJRadioButton(\"Custom\", sshArgsGroup, sshArgsPanel);\n    sshArgsCustomButton.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        sshArgsInput.setEnabled(sshArgsCustomButton.isSelected());\n      }\n    });\n    sshArgsInput = new JTextField();\n\n    JPanel gatewayPanel = new JPanel(new GridBagLayout());\n    gatewayPanel.add(viaCheckbox,\n                    new GridBagConstraints(0, 0,\n                                           REMAINDER, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 0, 4, 0),\n                                           NONE, NONE));\n    int indent = getButtonLabelInset(viaCheckbox);\n    gatewayPanel.add(sshUserLabel,\n                 new GridBagConstraints(0, 1,\n                                        1, 1,\n                                        LIGHT, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, indent, 4, 0),\n                                        NONE, NONE));\n    gatewayPanel.add(sshHostLabel,\n                 new GridBagConstraints(2, 1,\n                                        1, 1,\n                                        HEAVY, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, 0, 4, 0),\n                                        NONE, NONE));\n    gatewayPanel.add(sshPortLabel,\n                 new GridBagConstraints(3, 1,\n                                        1, 1,\n                                        LIGHT, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, 5, 4, 0),\n                                        NONE, NONE));\n    gatewayPanel.add(viaUserInput,\n                 new GridBagConstraints(0, 2,\n                                        1, 1,\n                                        LIGHT, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, indent, 0, 0),\n                                        NONE, NONE));\n    gatewayPanel.add(sshUserAtLabel,\n                 new GridBagConstraints(1, 2,\n                                        1, 1,\n                                        LIGHT, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, 2, 0, 2),\n                                        NONE, NONE));\n    gatewayPanel.add(viaHostInput,\n                 new GridBagConstraints(2, 2,\n                                        1, 1,\n                                        HEAVY, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, 0, 0, 0),\n                                        NONE, NONE));\n    gatewayPanel.add(viaPortInput,\n                 new GridBagConstraints(3, 2,\n                                        1, 1,\n                                        LIGHT, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, 5, 0, 0),\n                                        NONE, NONE));\n\n    JPanel clientPanel = new JPanel(new GridBagLayout());\n    clientPanel.add(extSSHCheckbox,\n                    new GridBagConstraints(0, 0,\n                                           1, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 0, 0, 0),\n                                           NONE, NONE));\n    clientPanel.add(sshClientInput,\n                    new GridBagConstraints(1, 0,\n                                           1, 1,\n                                           HEAVY, LIGHT,\n                                           LINE_START, HORIZONTAL,\n                                           new Insets(0, 5, 0, 0),\n                                           NONE, NONE));\n    clientPanel.add(sshClientChooser,\n                    new GridBagConstraints(2, 0,\n                                           1, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 5, 0, 0),\n                                           NONE, NONE));\n    sshArgsPanel.add(sshArgsLabel,\n                    new GridBagConstraints(0, 1,\n                                           1, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 0, 0, 0),\n                                           NONE, NONE));\n    sshArgsPanel.add(sshArgsDefaultButton,\n                    new GridBagConstraints(1, 1,\n                                           1, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 5, 0, 0),\n                                           NONE, NONE));\n    sshArgsPanel.add(sshArgsCustomButton,\n                    new GridBagConstraints(2, 1,\n                                           1, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(0, 5, 0, 0),\n                                           NONE, NONE));\n    sshArgsPanel.add(sshArgsInput,\n                    new GridBagConstraints(3, 1,\n                                           1, 1,\n                                           HEAVY, LIGHT,\n                                           LINE_START, HORIZONTAL,\n                                           new Insets(0, 5, 0, 0),\n                                           NONE, NONE));\n    indent = getButtonLabelInset(extSSHCheckbox);\n    clientPanel.add(sshArgsPanel,\n                    new GridBagConstraints(0, 1,\n                                           REMAINDER, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, HORIZONTAL,\n                                           new Insets(4, indent, 0, 0),\n                                           NONE, NONE));\n\n    JPanel opensshPanel = new JPanel(new GridBagLayout());\n    TitledBorder border =\n      BorderFactory.createTitledBorder(\"Embedded SSH client configuration\");\n    opensshPanel.setBorder(border);\n    opensshPanel.add(sshConfigLabel,\n                     new GridBagConstraints(0, 0,\n                                            1, 1,\n                                            LIGHT, LIGHT,\n                                            LINE_START, NONE,\n                                            new Insets(0, 0, 5, 0),\n                                            NONE, NONE));\n    opensshPanel.add(sshConfigInput,\n                     new GridBagConstraints(1, 0,\n                                            1, 1,\n                                            HEAVY, LIGHT,\n                                            LINE_START, HORIZONTAL,\n                                            new Insets(0, 5, 5, 0),\n                                            NONE, NONE));\n    opensshPanel.add(sshConfigChooser,\n                     new GridBagConstraints(2, 0,\n                                            1, 1,\n                                            LIGHT, LIGHT,\n                                            LINE_START, VERTICAL,\n                                            new Insets(0, 5, 5, 0),\n                                            NONE, NONE));\n    opensshPanel.add(sshKeyFileLabel,\n                     new GridBagConstraints(0, 1,\n                                            1, 1,\n                                            LIGHT, LIGHT,\n                                            LINE_START, NONE,\n                                            new Insets(0, 0, 0, 0),\n                                            NONE, NONE));\n    opensshPanel.add(sshKeyFileInput,\n                     new GridBagConstraints(1, 1,\n                                            1, 1,\n                                            HEAVY, LIGHT,\n                                            LINE_START, HORIZONTAL,\n                                            new Insets(0, 5, 0, 0),\n                                            NONE, NONE));\n    opensshPanel.add(sshKeyFileChooser,\n                     new GridBagConstraints(2, 1,\n                                            1, 1,\n                                            LIGHT, LIGHT,\n                                            LINE_START, VERTICAL,\n                                            new Insets(0, 5, 0, 0),\n                                            NONE, NONE));\n    tunnelPanel.add(gatewayPanel,\n                    new GridBagConstraints(0, 0,\n                                           REMAINDER, 1,\n                                           HEAVY, LIGHT,\n                                           LINE_START, HORIZONTAL,\n                                           new Insets(0, 0, 4, 0),\n                                           NONE, NONE));\n    tunnelPanel.add(clientPanel,\n                    new GridBagConstraints(0, 1,\n                                           REMAINDER, 1,\n                                           HEAVY, LIGHT,\n                                           LINE_START, HORIZONTAL,\n                                           new Insets(0, 0, 4, 0),\n                                           NONE, NONE));\n    tunnelPanel.add(opensshPanel,\n                    new GridBagConstraints(0, 2,\n                                           REMAINDER, 1,\n                                           HEAVY, LIGHT,\n                                           LINE_START, HORIZONTAL,\n                                           new Insets(0, 0, 0, 0),\n                                           NONE, NONE));\n\n    sshPanel.add(tunnelCheckbox,\n                 new GridBagConstraints(0, 0,\n                                        REMAINDER, 1,\n                                        LIGHT, LIGHT,\n                                        LINE_START, NONE,\n                                        new Insets(0, 0, 4, 0),\n                                        NONE, NONE));\n    indent = getButtonLabelInset(tunnelCheckbox);\n    sshPanel.add(tunnelPanel,\n                 new GridBagConstraints(0, 2,\n                                        REMAINDER, 1,\n                                        LIGHT, LIGHT,\n                                        LINE_START, HORIZONTAL,\n                                        new Insets(0, indent, 4, 0),\n                                        NONE, NONE));\n    sshPanel.add(Box.createRigidArea(new Dimension(5, 0)),\n                 new GridBagConstraints(0, RELATIVE,\n                                        REMAINDER, REMAINDER,\n                                        HEAVY, HEAVY,\n                                        LINE_START, BOTH,\n                                        new Insets(0, 0, 0, 0),\n                                        NONE, NONE));\n    return sshPanel;\n  }\n\n  private void handleAutoselect()\n  {\n    ButtonGroup[] groups = { encodingGroup, colorlevelGroup };\n    for (ButtonGroup grp : groups) {\n      Enumeration<AbstractButton> elems = grp.getElements();\n      while (elems.hasMoreElements())\n        elems.nextElement().setEnabled(!autoselectCheckbox.isSelected());\n    }\n\n    // JPEG setting is also affected by autoselection\n    jpegCheckbox.setEnabled(!autoselectCheckbox.isSelected());\n    handleJpeg();\n  }\n\n  private void handleCompression()\n  {\n    compressionInput.setEnabled(compressionCheckbox.isSelected());\n  }\n\n  private void handleJpeg()\n  {\n    if (jpegCheckbox.isSelected() &&\n        !autoselectCheckbox.isSelected())\n      jpegInput.setEnabled(true);\n    else\n      jpegInput.setEnabled(false);\n  }\n\n  private void handleX509()\n  {\n    caInput.setEnabled(encX509Checkbox.isSelected());\n    caChooser.setEnabled(encX509Checkbox.isSelected());\n    crlInput.setEnabled(encX509Checkbox.isSelected());\n    crlChooser.setEnabled(encX509Checkbox.isSelected());\n  }\n\n  private void handleRSAAES()\n  {\n    authVncCheckbox.setSelected(true);\n    authPlainCheckbox.setSelected(true);\n  }\n\n  private void handleSendLocalUsername()\n  {\n    boolean value = authIdentCheckbox.isSelected() ||\n                    authPlainCheckbox.isSelected();\n        sendLocalUsernameCheckbox.setEnabled(value);\n  }\n\n  private void handleDesktopSize()\n  {\n    desktopWidthInput.setEnabled(desktopSizeCheckbox.isSelected());\n    desktopHeightInput.setEnabled(desktopSizeCheckbox.isSelected());\n  }\n\n  private void handleRemoteResize()\n  {\n    scalingFactorInput.setEnabled(!remoteResizeButton.isSelected());\n  }\n\n  private void handleTunnel()\n  {\n    viaCheckbox.setEnabled(tunnelCheckbox.isSelected());\n    extSSHCheckbox.setEnabled(tunnelCheckbox.isSelected());\n    if (tunnelCheckbox.isSelected()) {\n      JComponent[] components = { viaUserInput, viaHostInput, viaPortInput };\n      for (JComponent c : components)\n        c.setEnabled(viaCheckbox.isSelected());\n      sshClientInput.setEnabled(extSSHCheckbox.isSelected());\n      sshClientChooser.setEnabled(extSSHCheckbox.isSelected());\n      sshArgsDefaultButton.setEnabled(extSSHCheckbox.isSelected());\n      sshArgsCustomButton.setEnabled(extSSHCheckbox.isSelected());\n      sshArgsInput.setEnabled(extSSHCheckbox.isSelected());\n      sshConfigInput.setEnabled(!extSSHCheckbox.isSelected());\n      sshConfigChooser.setEnabled(!extSSHCheckbox.isSelected());\n      sshKeyFileInput.setEnabled(!extSSHCheckbox.isSelected());\n      sshKeyFileChooser.setEnabled(!extSSHCheckbox.isSelected());\n    } else {\n      JComponent[] components = {\n        viaUserInput, viaHostInput, viaPortInput, sshClientInput,\n        sshClientChooser, sshArgsDefaultButton, sshArgsCustomButton,\n        sshArgsInput, sshConfigInput, sshConfigChooser, sshKeyFileInput,\n        sshKeyFileChooser, };\n      for (JComponent c : components)\n        c.setEnabled(false);\n    }\n  }\n\n  private void handleVia()\n  {\n    if (tunnelCheckbox.isSelected()) {\n      viaUserInput.setEnabled(viaCheckbox.isSelected());\n      viaHostInput.setEnabled(viaCheckbox.isSelected());\n      viaPortInput.setEnabled(viaCheckbox.isSelected());\n    }\n  }\n\n  private void handleExtSSH()\n  {\n    if (tunnelCheckbox.isSelected()) {\n      sshClientInput.setEnabled(extSSHCheckbox.isSelected());\n      sshClientChooser.setEnabled(extSSHCheckbox.isSelected());\n      sshArgsDefaultButton.setEnabled(extSSHCheckbox.isSelected());\n      sshArgsCustomButton.setEnabled(extSSHCheckbox.isSelected());\n      sshConfigInput.setEnabled(!extSSHCheckbox.isSelected());\n      sshConfigChooser.setEnabled(!extSSHCheckbox.isSelected());\n      sshKeyFileInput.setEnabled(!extSSHCheckbox.isSelected());\n      sshKeyFileChooser.setEnabled(!extSSHCheckbox.isSelected());\n      if (sshArgsCustomButton.isSelected())\n        sshArgsInput.setEnabled(extSSHCheckbox.isSelected());\n      else\n        sshArgsInput.setEnabled(false);\n    }\n  }\n\n  private void handleRfbState()\n  {\n    CConn cc = VncViewer.cc;\n    if (cc != null && cc.state() == CConnection.stateEnum.RFBSTATE_NORMAL) {\n      JComponent[] components = {\n          encNoneCheckbox, encTLSCheckbox, encX509Checkbox, authNoneCheckbox,\n          authVncCheckbox, authVncCheckbox, authIdentCheckbox, authPlainCheckbox,\n          sendLocalUsernameCheckbox, caInput, caChooser, crlInput, crlChooser,\n          sharedCheckbox, tunnelCheckbox, viaCheckbox, viaUserInput, viaHostInput,\n          viaPortInput, extSSHCheckbox, sshClientInput, sshClientChooser,\n          sshArgsDefaultButton, sshArgsCustomButton, sshArgsInput, sshConfigInput,\n          sshKeyFileInput, sshConfigChooser, sshKeyFileChooser,\n        };\n      for (JComponent c : components)\n        c.setEnabled(false);\n    }\n  }\n\n  private void handleAlwaysCursor()\n  {\n    cursorTypeChoice.setEnabled(alwaysCursorCheckbox.isSelected());\n  }\n\n  static LogWriter vlog = new LogWriter(\"OptionsDialog\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/Parameters.java",
    "content": "/* Copyright (C) 2016-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.io.LineNumberReader;\nimport java.io.PrintWriter;\nimport java.util.StringTokenizer;\n\nimport com.tigervnc.rfb.*;\nimport com.tigervnc.rfb.Exception;\n\npublic class Parameters {\n\n  public static BoolParameter noLionFS\n  = new BoolParameter(\"NoLionFS\",\n    \"On Mac systems, setting this parameter will force the use of the old \"+\n    \"(pre-Lion) full-screen mode, even if the viewer is running on OS X 10.7 \"+\n    \"Lion or later.\",\n    false);\n\n  public static BoolParameter dotWhenNoCursor\n  = new BoolParameter(\"DotWhenNoCursor\",\n    \"[DEPRECATED] Show the dot cursor when the server sends an invisible cursor\",\n    false);\n\n  public static BoolParameter alwaysCursor\n  = new BoolParameter(\"AlwaysCursor\",\n    \"Show the local cursor when the server sends an invisible cursor\",\n    false);\n\n  public static StringParameter cursorType\n  = new StringParameter(\"CursorType\",\n    \"Specify which cursor type the local cursor should be. Should be either Dot or System\",\n    \"Dot\");\n\n  public static BoolParameter sendLocalUsername\n  = new BoolParameter(\"SendLocalUsername\",\n    \"Send the local username for SecurityTypes \"+\n    \"such as Plain rather than prompting\",\n    true);\n\n  public static StringParameter passwordFile\n  = new StringParameter(\"PasswordFile\",\n    \"Password file for VNC authentication\",\n    \"\");\n\n  public static AliasParameter passwd\n  = new AliasParameter(\"passwd\",\n    \"Alias for PasswordFile\",\n    passwordFile);\n\n  public static BoolParameter autoSelect\n  = new BoolParameter(\"AutoSelect\",\n    \"Auto select pixel format and encoding\",\n    true);\n\n  public static BoolParameter fullColor\n  = new BoolParameter(\"FullColor\",\n    \"Use full color - otherwise 6-bit colour is used \"+\n    \"until AutoSelect decides the link is fast enough\",\n    true);\n\n  public static AliasParameter fullColorAlias\n  = new AliasParameter(\"FullColour\",\n    \"Alias for FullColor\",\n    Parameters.fullColor);\n\n  public static IntParameter lowColorLevel\n  = new IntParameter(\"LowColorLevel\",\n    \"Color level to use on slow connections. \"+\n    \"0 = Very Low, 1 = Low, 2 = Medium\",\n    2);\n\n  public static AliasParameter lowColorLevelAlias\n  = new AliasParameter(\"LowColourLevel\",\n    \"Alias for LowColorLevel\",\n    lowColorLevel);\n\n  public static StringParameter preferredEncoding\n  = new StringParameter(\"PreferredEncoding\",\n    \"Preferred encoding to use (Tight, ZRLE, \"+\n    \"hextile or raw) - implies AutoSelect=0\",\n    \"Tight\");\n\n  public static BoolParameter remoteResize\n  = new BoolParameter(\"RemoteResize\",\n    \"Dynamically resize the remote desktop size as \"+\n    \"the size of the local client window changes. \"+\n    \"(Does not work with all servers)\",\n    true);\n\n  public static BoolParameter viewOnly\n  = new BoolParameter(\"ViewOnly\",\n    \"Don't send any mouse or keyboard events to the server\",\n    false);\n\n  public static BoolParameter shared\n  = new BoolParameter(\"Shared\",\n    \"Don't disconnect other viewers upon \"+\n    \"connection - share the desktop instead\",\n    false);\n\n  public static BoolParameter maximize\n  = new BoolParameter(\"Maximize\",\n    \"Maximize viewer window\",\n    false);\n\n  public static BoolParameter fullScreen\n  = new BoolParameter(\"FullScreen\",\n    \"Enable full screen\",\n    false);\n\n  public static BoolParameter fullScreenAllMonitors\n  = new BoolParameter(\"FullScreenAllMonitors\",\n    \"Enable full screen over all monitors\",\n    true);\n\n  public static BoolParameter acceptClipboard\n  = new BoolParameter(\"AcceptClipboard\",\n    \"Accept clipboard changes from the server\",\n    true);\n\n  public static BoolParameter sendClipboard\n  = new BoolParameter(\"SendClipboard\",\n    \"Send clipboard changes to the server\",\n    true);\n\n  public static BoolParameter disableArrowScroll\n  = new BoolParameter(\"DisableArrowScroll\",\n    \"Disable arrow-key scrolling of the viewer when scrollbars are visible\",\n    false);\n\n  public static IntParameter maxCutText\n  = new IntParameter(\"MaxCutText\",\n    \"Maximum permitted length of an outgoing clipboard update\",\n    262144);\n\n  public static StringParameter menuKey\n  = new StringParameter(\"MenuKey\",\n    \"The key which brings up the popup menu\",\n    \"F8\");\n\n  public static StringParameter desktopSize\n  = new StringParameter(\"DesktopSize\",\n    \"Reconfigure desktop size on the server on connect (if possible)\",\n    \"\");\n\n  public static BoolParameter listenMode\n  = new BoolParameter(\"listen\",\n    \"Listen for connections from VNC servers\",\n    false);\n\n  public static StringParameter scalingFactor\n  = new StringParameter(\"ScalingFactor\",\n    \"Reduce or enlarge the remote desktop image. \"+\n    \"The value is interpreted as a scaling factor \"+\n    \"in percent. If the parameter is set to \"+\n    \"\\\"Auto\\\", then automatic scaling is \"+\n    \"performed. Auto-scaling tries to choose a \"+\n    \"scaling factor in such a way that the whole \"+\n    \"remote desktop will fit on the local screen. \"+\n    \"If the parameter is set to \\\"FixedRatio\\\", \"+\n    \"then automatic scaling is performed, but the \"+\n    \"original aspect ratio is preserved.\",\n    \"100\");\n\n  public static BoolParameter alwaysShowServerDialog\n  = new BoolParameter(\"AlwaysShowServerDialog\",\n    \"Always show the server dialog even if a server has been \"+\n    \"specified in an applet parameter or on the command line\",\n    false);\n\n  public static BoolParameter acceptBell\n  = new BoolParameter(\"AcceptBell\",\n    \"Produce a system beep when requested to by the server.\",\n    true);\n\n  public static StringParameter via\n  = new StringParameter(\"Via\",\n    \"Automatically create an encrypted TCP tunnel to \"+\n    \"the gateway machine, then connect to the VNC host \"+\n    \"through that tunnel. By default, this option invokes \"+\n    \"SSH local port forwarding using the embedded JSch \"+\n    \"client, however an external SSH client may be specified \"+\n    \"using the \\\"-extSSH\\\" parameter. Note that when using \"+\n    \"the -via option, the VNC host machine name should be \"+\n    \"specified from the point of view of the gateway machine, \"+\n    \"e.g. \\\"localhost\\\" denotes the gateway, \"+\n    \"not the machine on which the viewer was launched. \"+\n    \"See the System properties section below for \"+\n    \"information on configuring the -Via option.\", \"\");\n\n  public static BoolParameter tunnel\n  = new BoolParameter(\"Tunnel\",\n    \"The -Tunnel command is basically a shorthand for the \"+\n    \"-via command when the VNC server and SSH gateway are \"+\n    \"one and the same. -Tunnel creates an SSH connection \"+\n    \"to the server and forwards the VNC through the tunnel \"+\n    \"without the need to specify anything else.\", false);\n\n  public static BoolParameter extSSH\n  = new BoolParameter(\"extSSH\",\n    \"By default, SSH tunneling uses the embedded JSch client \"+\n    \"for tunnel creation. This option causes the client to \"+\n    \"invoke an external SSH client application for all tunneling \"+\n    \"operations. By default, \\\"/usr/bin/ssh\\\" is used, however \"+\n    \"the path to the external application may be specified using \"+\n    \"the -SSHClient option.\", false);\n\n  public static StringParameter extSSHClient\n  = new StringParameter(\"extSSHClient\",\n    \"Specifies the path to an external SSH client application \"+\n    \"that is to be used for tunneling operations when the -extSSH \"+\n    \"option is in effect.\", \"/usr/bin/ssh\");\n\n  public static StringParameter extSSHArgs\n  = new StringParameter(\"extSSHArgs\",\n    \"Specifies the arguments string or command template to be used \"+\n    \"by the external SSH client application when the -extSSH option \"+\n    \"is in effect. The string will be processed according to the same \"+\n    \"pattern substitution rules as the VNC_TUNNEL_CMD and VNC_VIA_CMD \"+\n    \"system properties, and can be used to override those in a more \"+\n    \"command-line friendly way. If not specified, then the appropriate \"+\n    \"VNC_TUNNEL_CMD or VNC_VIA_CMD command template will be used.\", \"\");\n\n  public static StringParameter sshConfig\n  = new StringParameter(\"SSHConfig\",\n    \"Specifies the path to an OpenSSH configuration file that to \"+\n    \"be parsed by the embedded JSch SSH client during tunneling \"+\n    \"operations.\", FileUtils.getHomeDir()+\".ssh/config\");\n\n  public static StringParameter sshKey\n  = new StringParameter(\"SSHKey\",\n    \"When using the Via or Tunnel options with the embedded SSH client, \"+\n    \"this parameter specifies the text of the SSH private key to use when \"+\n    \"authenticating with the SSH server. You can use \\\\n within the string \"+\n    \"to specify a new line.\", \"\");\n\n  public static StringParameter sshKeyFile\n  = new StringParameter(\"SSHKeyFile\",\n    \"When using the Via or Tunnel options with the embedded SSH client, \"+\n    \"this parameter specifies a file that contains an SSH private key \"+\n    \"(or keys) to use when authenticating with the SSH server. If not \"+\n    \"specified, ~/.ssh/id_dsa or ~/.ssh/id_rsa will be used (if they exist). \"+\n    \"Otherwise, the client will fallback to prompting for an SSH password.\",\n    \"\");\n\n  public static StringParameter sshKeyPass\n  = new StringParameter(\"SSHKeyPass\",\n    \"When using the Via or Tunnel options with the embedded SSH client, \"+\n    \"this parameter specifies the passphrase for the SSH key.\", \"\");\n\n  public static BoolParameter customCompressLevel\n  = new BoolParameter(\"CustomCompressLevel\",\n    \"Use custom compression level. Default if CompressLevel is specified.\",\n    false);\n\n  public static IntParameter compressLevel\n  = new IntParameter(\"CompressLevel\",\n    \"Use specified lossless compression level. 0 = Low, 9 = High. Default is 2.\",\n    2);\n\n  public static BoolParameter noJpeg\n  = new BoolParameter(\"NoJPEG\",\n    \"Disable lossy JPEG compression in Tight encoding.\",\n    false);\n\n  public static IntParameter qualityLevel\n  = new IntParameter(\"QualityLevel\",\n    \"JPEG quality level. 0 = Low, 9 = High\",\n    8);\n\n  private static final String IDENTIFIER_STRING\n  = \"TigerVNC Configuration file Version 1.0\";\n\n  static VoidParameter[] parameterArray = {\n    CSecurityTLS.X509CA,\n    CSecurityTLS.X509CRL,\n    SecurityClient.secTypes,\n    alwaysCursor,\n    cursorType,\n    autoSelect,\n    fullColor,\n    lowColorLevel,\n    preferredEncoding,\n    customCompressLevel,\n    compressLevel,\n    noJpeg,\n    qualityLevel,\n    maximize,\n    fullScreen,\n    fullScreenAllMonitors,\n    desktopSize,\n    remoteResize,\n    viewOnly,\n    shared,\n    acceptClipboard,\n    sendClipboard,\n    disableArrowScroll,\n    menuKey,\n    noLionFS,\n    sendLocalUsername,\n    maxCutText,\n    scalingFactor,\n    acceptBell,\n    via,\n    tunnel,\n    extSSH,\n    extSSHClient,\n    extSSHArgs,\n    sshConfig,\n    sshKeyFile,\n  };\n\n  static VoidParameter[] readOnlyParameterArray = {\n    dotWhenNoCursor\n  };\n\n\n  static LogWriter vlog = new LogWriter(\"Parameters\");\n\n\tpublic static void saveViewerParameters(String filename, String servername) {\n\n\t  // Write to the registry or a predefined file if no filename was specified.\n    String filepath;\n    if (filename == null || filename.isEmpty()) {\n      saveToReg(servername);\n      return;\n    } else {\n      filepath = filename;\n    }\n\n\t  /* Write parameters to file */\n    File f = new File(filepath);\n    if (f.exists() && !f.canWrite())\n\t    throw new Exception(String.format(\"Failed to write configuration file,\"+\n                                        \"can't open %s\", filepath)); \n\n    PrintWriter pw = null;\n    try {\n      pw = new PrintWriter(f, \"UTF-8\");\n    } catch (java.lang.Exception e)\t{\n      throw new Exception(e.getMessage());\n    }\n\n    pw.println(IDENTIFIER_STRING);\n    pw.println(\"\");\n\n\t  if (servername != null && !servername.isEmpty()) {\n\t    pw.println(String.format(\"ServerName=%s\\n\", servername));\n      updateConnHistory(servername);\n    }\n\n    for (int i = 0; i < parameterArray.length; i++) {\n      if (parameterArray[i] instanceof StringParameter) {\n        //if (line.substring(0,idx).trim().equalsIgnoreCase(parameterArray[i].getName()))\n          pw.println(String.format(\"%s=%s\",parameterArray[i].getName(),\n                                   parameterArray[i].getValueStr()));\n      } else if (parameterArray[i] instanceof IntParameter) {\n        //if (line.substring(0,idx).trim().equalsIgnoreCase(parameterArray[i].getName()))\n          pw.println(String.format(\"%s=%s\",parameterArray[i].getName(),\n                                   parameterArray[i].getValueStr()));\n      } else if (parameterArray[i] instanceof BoolParameter) {\n        //if (line.substring(0,idx).trim().equalsIgnoreCase(parameterArray[i].getName()))\n          pw.println(String.format(\"%s=%s\",parameterArray[i].getName(),\n                                   parameterArray[i].getValueStr()));\n      } else {\n        vlog.error(String.format(\"Unknown parameter type for parameter %s\",\n                   parameterArray[i].getName()));\n      }\n    }\n\n    pw.flush();\n    pw.close();\n\t}\n\n  public static String loadViewerParameters(String filename) throws Exception {\n    String servername = \"\";\n\n    String filepath;\n    if (filename == null) {\n      return loadFromReg();\n    } else {\n      filepath = filename;\n    }\n\n    /* Read parameters from file */\n    File f = new File(filepath);\n    if (!f.exists() || !f.canRead()) {\n      if (filename == null || filename.isEmpty())\n        return null;\n      throw new Exception(String.format(\"Failed to read configuration file, can't open %s\",\n                          filepath)); \n    }\n\n    String line = \"\";\n    LineNumberReader reader;\n    try {\n      reader = new LineNumberReader(new FileReader(f));\n    } catch (FileNotFoundException e) {\n      throw new Exception(e.getMessage());\n    }\n\n    int lineNr = 0;\n    while (line != null) {\n\n      // Read the next line\n      try {\n        line = reader.readLine();\n        lineNr = reader.getLineNumber();\n        if (line == null)\n          break;\n      } catch (IOException e) {\n        throw new Exception(String.format(\"Failed to read line %d in file %s: %s\",\n          lineNr, filepath, e.getMessage()));\n      }\n\n      // Make sure that the first line of the file has the file identifier string\n      if(lineNr == 1) {\n        if(line.equals(IDENTIFIER_STRING))\n          continue;\n        else\n          throw new Exception(String.format(\"Configuration file %s is in an invalid format\", filename));\n      }\n\n      // Skip empty lines and comments\n      if (line.trim().isEmpty() || line.trim().startsWith(\"#\"))\n        continue;\n\n      // Find the parameter value\n      int idx = line.indexOf(\"=\");\n      if (idx == -1) {\n        vlog.error(String.format(\"Failed to read line %d in file %s: %s\",\n                   lineNr, filename, \"Invalid format\"));\n        continue;\n      }\n      String value = line.substring(idx+1).trim();\n      boolean invalidParameterName = true; // Will be set to false below if \n                                           // the line contains a valid name.\n\n      if (line.substring(0,idx).trim().equalsIgnoreCase(\"ServerName\")) {\n        if (value.length() > 256) {\n          vlog.error(String.format(\"Failed to read line %d in file %s: %s\",\n                     lineNr, filepath, \"Invalid format or too large value\"));\n          continue;\n        }\n        servername = value;\n        invalidParameterName = false;\n      } else {\n        for (int i = 0; i < parameterArray.length; i++) {\n          VoidParameter parameter;\n          if (i < parameterArray.length) {\n            parameter = parameterArray[i];\n          } else {\n            parameter = readOnlyParameterArray[i - parameterArray.length];\n          }\n          if (parameter instanceof StringParameter) {\n            if (line.substring(0,idx).trim().equalsIgnoreCase(parameter.getName())) {\n              if (value.length() > 256) {\n                vlog.error(String.format(\"Failed to read line %d in file %s: %s\",\n                           lineNr, filepath, \"Invalid format or too large value\"));\n                continue;\n              }\n              ((StringParameter)parameter).setParam(value);\n              invalidParameterName = false;\n            }\n          } else if (parameter instanceof IntParameter) {\n            if (line.substring(0,idx).trim().equalsIgnoreCase(parameter.getName())) {\n              ((IntParameter)parameter).setParam(value);\n              invalidParameterName = false;\n            }\n          } else if (parameter instanceof BoolParameter) {\n            if (line.substring(0,idx).trim().equalsIgnoreCase(parameter.getName())) {\n              ((BoolParameter)parameter).setParam(value);\n              invalidParameterName = false;\n            }\n          } else {\n            vlog.error(String.format(\"Unknown parameter type for parameter %s\",\n                       parameter.getName()));\n\n          }\n        }\n      }\n\n      if (invalidParameterName)\n        vlog.info(String.format(\"Unknown parameter %s on line %d in file %s\",\n                  line, lineNr, filepath));\n    }\n    try {\n      reader.close();\n    } catch (IOException e) {\n      vlog.info(e.getMessage());\n    } finally {\n      try {\n        if (reader != null)\n          reader.close();\n        } catch (IOException e) { }\n    }\n\n    return servername;\n  }\n\n  public static void saveToReg(String servername) {\n    String hKey = \"global\";\n\n    if (servername != null && !servername.isEmpty()) {\n      UserPreferences.set(hKey, \"ServerName\", servername);\n      updateConnHistory(servername);\n    }\n\n    for (int i = 0; i < parameterArray.length; i++) {\n      if (parameterArray[i] instanceof StringParameter) {\n        UserPreferences.set(hKey, parameterArray[i].getName(),\n                                  parameterArray[i].getValueStr());\n      } else if (parameterArray[i] instanceof IntParameter) {\n        UserPreferences.set(hKey, parameterArray[i].getName(),\n                            ((IntParameter)parameterArray[i]).getValue());\n      } else if (parameterArray[i] instanceof BoolParameter) {\n        UserPreferences.set(hKey, parameterArray[i].getName(),\n                            ((BoolParameter)parameterArray[i]).getValue());\n      } else {\n        vlog.error(String.format(\"Unknown parameter type for parameter %s\",\n                   parameterArray[i].getName()));\n      }\n    }\n\n    for (int i = 0; i < readOnlyParameterArray.length; i++) {\n      UserPreferences.delete(hKey, readOnlyParameterArray[i].getName());\n    }\n\n    UserPreferences.save(hKey);\n  }\n\n  public static String loadFromReg() {\n\n    String hKey = \"global\";\n\n    String servername = UserPreferences.get(hKey, \"ServerName\");\n    if (servername == null)\n      servername = \"\";\n\n    for (int i = 0; i < parameterArray.length + readOnlyParameterArray.length; i++) {\n      VoidParameter parameter;\n      if (i < parameterArray.length) {\n        parameter = parameterArray[i];\n      } else {\n        parameter = readOnlyParameterArray[i - parameterArray.length];\n      }\n      if (parameter instanceof StringParameter) {\n        if (UserPreferences.get(hKey, parameter.getName()) != null) {\n          String stringValue =\n            UserPreferences.get(hKey, parameter.getName());\n          ((StringParameter)parameter).setParam(stringValue);\n        }\n      } else if (parameter instanceof IntParameter) {\n        if (UserPreferences.get(hKey, parameter.getName()) != null) {\n          int intValue =\n            UserPreferences.getInt(hKey, parameter.getName());\n          ((IntParameter)parameter).setParam(intValue);\n        }\n      } else if (parameter instanceof BoolParameter) {\n        if (UserPreferences.get(hKey, parameter.getName()) != null) {\n          boolean booleanValue =\n            UserPreferences.getBool(hKey, parameter.getName());\n          ((BoolParameter)parameter).setParam(booleanValue);\n        }\n      } else {\n        vlog.error(String.format(\"Unknown parameter type for parameter %s\",\n                   parameter.getName()));\n      }\n    }\n\n    return servername;\n  }\n\n  private static void updateConnHistory(String serverName) {\n    String hKey = \"ServerDialog\";\n    if (serverName != null && !serverName.isEmpty()) {\n      String valueStr = UserPreferences.get(hKey, \"history\");\n      String t = (valueStr == null) ? \"\" : valueStr;\n      StringTokenizer st = new StringTokenizer(t, \",\");\n      StringBuffer sb = new StringBuffer().append(serverName);\n      while (st.hasMoreTokens()) {\n        String str = st.nextToken();\n        if (!str.equals(serverName) && !str.equals(\"\"))\n          sb.append(',').append(str);\n      }\n      UserPreferences.set(hKey, \"history\", sb.toString());\n      UserPreferences.save(hKey);\n    }\n  }\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/PasswdDialog.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.event.*;\nimport javax.swing.*;\n\nimport com.jcraft.jsch.*;\nimport com.tigervnc.rfb.*;\n\nimport static java.awt.GridBagConstraints.HORIZONTAL;\nimport static java.awt.GridBagConstraints.LINE_START;\nimport static java.awt.GridBagConstraints.NONE;\nimport static java.awt.GridBagConstraints.REMAINDER;\n\nclass PasswdDialog extends Dialog implements UserInfo,\n                                             UIKeyboardInteractive {\n\n  public PasswdDialog(String title,\n                      boolean userDisabled, boolean passwdDisabled) {\n    super(true);\n    setResizable(false);\n    setTitle(title);\n    addWindowListener(new WindowAdapter() {\n      public void windowClosing(WindowEvent e) {\n        endDialog();\n      }\n    });\n\n    JPanel p1 = new JPanel(new GridBagLayout());\n    p1.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));\n\n    userLabel = new JLabel(\"Username:\");\n    userLabel.setEnabled(!userDisabled);\n    p1.add(userLabel, new GridBagConstraints(0, 0,\n                                             1, 1,\n                                             LIGHT, LIGHT,\n                                             LINE_START, NONE,\n                                             new Insets(0, 0, 0, 0),\n                                             NONE, NONE));\n    userEntry = new JTextField(30);\n    userEntry.setEnabled(!userDisabled);\n    p1.add(userEntry, new GridBagConstraints(1, 0,\n                                             1, 1,\n                                             HEAVY, LIGHT,\n                                             LINE_START, REMAINDER,\n                                             new Insets(0, 5, 0, 0),\n                                             NONE, NONE));\n\n    passwdLabel = new JLabel(\"Password:\");\n    passwdLabel.setEnabled(!passwdDisabled);\n    p1.add(passwdLabel, new GridBagConstraints(0, 1,\n                                               1, 1,\n                                               LIGHT, LIGHT,\n                                               LINE_START, NONE,\n                                               new Insets(5, 0, 0, 0),\n                                               NONE, NONE));\n    passwdEntry = new JPasswordField(30);\n    passwdEntry.setEnabled(!passwdDisabled);\n    p1.add(passwdEntry, new GridBagConstraints(1, 1,\n                                               1, 1,\n                                               HEAVY, LIGHT,\n                                               LINE_START, REMAINDER,\n                                               new Insets(5, 5, 0, 0),\n                                               NONE, NONE));\n\n    this.add(p1);\n    addListeners(this);\n    pack();\n    if (userEntry.isEnabled()) {\n      userEntry.requestFocus();\n    } else {\n      passwdEntry.requestFocus();\n    }\n  }\n\n  /** Handle the key-pressed event. */\n  public void keyPressed(KeyEvent event) {\n    Object s = event.getSource();\n    if (s instanceof JTextField && (JTextField)s == userEntry) {\n       if (KeyMap.get_keycode_fallback_extended(event) == KeyEvent.VK_ENTER) {\n         endDialog();\n        }\n    } else if (s instanceof JPasswordField\n              && (JPasswordField)s == passwdEntry) {\n        if (KeyMap.get_keycode_fallback_extended(event) == KeyEvent.VK_ENTER) {\n         endDialog();\n        }\n    }\n  }\n\n  public String getPassword() {\n    return new String(passwdEntry.getPassword());\n  }\n\n  public String getPassphrase() { return null; }\n  public boolean promptPassphrase(String message) { return false; }\n\n  public boolean promptPassword(String message) {\n    setTitle(message);\n    showDialog();\n    if (userEntry.isEnabled())\n      if (userEntry.getText().equals(\"\"))\n        return false;\n      else if (!passwdEntry.isEnabled())\n        return true;\n    if (passwdEntry.isEnabled())\n      if (!passwdEntry.getText().equals(\"\"))\n        return true;\n    return false;\n  }\n\n  public void showMessage(String message) {\n    JOptionPane.showMessageDialog(null, message, \"Message\",\n                                  JOptionPane.PLAIN_MESSAGE);\n  }\n\n  public boolean promptYesNo(String str) {\n    Object[] options={ \"YES\", \"NO\" };\n    int ret=JOptionPane.showOptionDialog(null,\n           str,\n           \"Warning\",\n           JOptionPane.DEFAULT_OPTION,\n           JOptionPane.WARNING_MESSAGE,\n           null, options, options[0]);\n     return (ret == 0);\n  }\n\n  public String[] promptKeyboardInteractive(String destination,\n                                            String name,\n                                            String instruction,\n                                            String[] prompt,\n                                            boolean[] echo) {\n    Container panel = new JPanel(new GridBagLayout());\n    ((JPanel)panel).setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));\n\n    panel.add(new JLabel(instruction),\n              new GridBagConstraints(0, 0,\n                                     REMAINDER, 1,\n                                     LIGHT, LIGHT,\n                                     LINE_START, NONE,\n                                     new Insets(0, 0, 0, 0),\n                                     NONE, NONE));\n\n    JTextField[] texts=new JTextField[prompt.length];\n    for (int i = 0; i < prompt.length; i++) {\n      panel.add(new JLabel(prompt[i]),\n                new GridBagConstraints(0, i+1,\n                                       1, 1,\n                                       LIGHT, LIGHT,\n                                       LINE_START, NONE,\n                                       new Insets(5, 0, 0, 0),\n                                       NONE, NONE));\n\n      if(echo[i])\n        texts[i]=new JTextField(20);\n      else\n        texts[i]=new JPasswordField(20);\n\n      panel.add(texts[i],\n                new GridBagConstraints(1, i+1,\n                                       1, 1,\n                                       HEAVY, LIGHT,\n                                       LINE_START, HORIZONTAL,\n                                       new Insets(5, 5, 0, 0),\n                                       NONE, NONE));\n    }\n\n    if (JOptionPane.showConfirmDialog(null, panel,\n                                      destination+\": \"+name,\n                                      JOptionPane.OK_CANCEL_OPTION,\n                                      JOptionPane.QUESTION_MESSAGE)\n        == JOptionPane.OK_OPTION) {\n      String[] response=new String[prompt.length];\n      for(int i=0; i<prompt.length; i++){\n        response[i]=texts[i].getText();\n      }\n\t    return response;\n    } else{\n      return null;  // cancel\n    }\n  }\n\n  JLabel userLabel;\n  JTextField userEntry;\n  JLabel passwdLabel;\n  JPasswordField passwdEntry;\n  static LogWriter vlog = new LogWriter(\"PasswdDialog\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/PlatformPixelBuffer.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2012 Brian P.Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.image.*;\nimport java.nio.ByteOrder;\n\nimport com.tigervnc.rfb.*;\nimport com.tigervnc.rfb.Point;\n\npublic class PlatformPixelBuffer extends FullFramePixelBuffer\n{\n  public PlatformPixelBuffer(PixelFormat pf,\n                             int w, int h,\n                             WritableRaster data)\n  {\n    super(pf, w, h, data);\n    damage = new Rect(0, 0, w, h);\n  }\n\n  public void commitBufferRW(Rect r)\n  {\n    super.commitBufferRW(r);\n    synchronized(damage) {\n      Rect n = damage.union_boundary(r);\n      damage.setXYWH(n.tl.x, n.tl.y, n.width(), n.height());\n    }\n  }\n\n  public Rect getDamage() {\n    Rect r = new Rect();\n\n    synchronized(damage) {\n      r.setXYWH(damage.tl.x, damage.tl.y, damage.width(), damage.height());\n      damage.clear();\n    }\n\n    return r;\n  }\n\n  protected Rect damage;\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/README",
    "content": "\nTigerVNC Java viewer\n====================\n\nThis distribution is based on the standard VNC source and includes new\nTigerVNC-specific features and fixes, such as additional low-bandwidth\noptimizations, major GUI improvements, and more.\n\n        Copyright (C) 2000-2003 Constantin Kaplinsky\n        Copyright (C) 2003 Sun Microsystems, Inc.\n        Copyright (C) 2002-2005 RealVNC Ltd.\n        Copyright (C) 2004-2005 Cendio AB\n        Copyright (C) 2005 Martin Koegler\n        Copyright (C) 2009 Pierre Ossman for Cendio AB\n        Copyright (C) 2011-2014 Brian P. Hinz\n        Copyright (C) 2009-2026 TigerVNC team\n        All rights reserved.\n\nThis software is distributed under the GNU General Public Licence as\npublished by the Free Software Foundation. See the file LICENCE.TXT for the\nconditions under which this software is made available. TigerVNC also\ncontains code from other sources. See the Acknowledgements section below, and\nthe individual files for details of the conditions under which they are made\navailable.\n\n\nInstallation\n============\n\nThe TigerVNC Java viewer requires installation of either a JRE (Java\nRuntime Environment) or a JDK (Java Development Kit).  If VncViewer.jar is\nin the current directory, then the TigerVNC Java viewer can be launched\nwith the following command line:\n\n   java -jar VncViewer.jar [parameters]\n\nAdd an argument of -? to the above command line to print a list of\noptional parameters supported by VncViewer.\n\n\nParameters\n==========\n\nThe TigerVNC Java viewer accepts a number of optional parameters, allowing you\nto customize its behavior. Example:\n\n  java -jar VncViewer.jar Port=5901 ScalingFactor=50\n\nBoth parameter names and their values are case-insensitive.\n\nFor a complete list of parameters and their descriptions, run:\n\n  java -jar VncViewer.jar -?\n\n\nHINTS\n=====\n\n--> To refresh the remote desktop in the view-only mode, press \"r\" or \"R\"\n    on the keyboard.\n\n\nACKNOWLEDGEMENTS\n================\n\nThis distribution contains Java DES software by Dave Zimmerman\n<dzimm@widget.com> and Jef Poskanzer <jef@acme.com>.  This is:\n\n    Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved.\n\n    Permission to use, copy, modify, and distribute this software and its\n    documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee\n    is hereby granted, provided that this copyright notice is kept intact.\n    \n    WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE\n    SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT\n    NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n    PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE\n    LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,\n    MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.\n    \n    THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE\n    CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE\n    PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT\n    NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE\n    SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE\n    SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE\n    PHYSICAL OR ENVIRONMENTAL DAMAGE (\"HIGH RISK ACTIVITIES\").  WIDGET\n    WORKSHOP SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF\n    FITNESS FOR HIGH RISK ACTIVITIES.\n\n    Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>.  All rights\n    reserved.\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n    1. Redistributions of source code must retain the above copyright\n       notice, this list of conditions and the following disclaimer.\n    2. Redistributions in binary form must reproduce the above copyright\n       notice, this list of conditions and the following disclaimer in the\n       documentation and/or other materials provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS\n    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\n    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    Visit the ACME Labs Java page for up-to-date versions of this and other\n    fine Java utilities: http://www.acme.com/java/\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/ServerDialog.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011-2016 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.event.*;\nimport java.io.File;\nimport java.nio.CharBuffer;\nimport javax.swing.*;\nimport javax.swing.border.*;\nimport javax.swing.filechooser.*;\nimport javax.swing.WindowConstants.*;\nimport java.util.*;\n\nimport com.tigervnc.rfb.*;\n\nimport static java.awt.GridBagConstraints.HORIZONTAL;\nimport static java.awt.GridBagConstraints.LINE_START;\nimport static java.awt.GridBagConstraints.LINE_END;\nimport static java.awt.GridBagConstraints.NONE;\nimport static java.awt.GridBagConstraints.REMAINDER;\n\nimport static com.tigervnc.vncviewer.Parameters.*;\n\nclass ServerDialog extends Dialog implements Runnable {\n\n  @SuppressWarnings({\"unchecked\",\"rawtypes\"})\n  public ServerDialog(String defaultServerName,\n                      CharBuffer vncServerName) {\n    super(true);\n    this.vncServerName = vncServerName;\n    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);\n    setTitle(\"TigerVNC\");\n    setResizable(false);\n    addWindowListener(new WindowAdapter() {\n      public void windowClosing(WindowEvent e) {\n        endDialog();\n        System.exit(1);\n      }\n    });\n\n    JLabel serverLabel = new JLabel(\"VNC server:\", JLabel.RIGHT);\n    String valueStr = new String(defaultServerName);\n    ArrayList<String> servernames = new ArrayList<String>();\n    if (!valueStr.isEmpty())\n      servernames.add(valueStr);\n    String history = UserPreferences.get(\"ServerDialog\", \"history\");\n    if (history != null) {\n      for (String s : history.split(\",\")) {\n        if (servernames.indexOf(s) < 0)\n          servernames.add(s);\n      }\n    }\n    serverName = new MyJComboBox(servernames.toArray());\n    serverName.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        JComboBox s = (JComboBox)e.getSource();\n        if (e.getActionCommand().equals(\"comboBoxEdited\")) {\n          s.insertItemAt(editor.getItem(), 0);\n          s.setSelectedIndex(0);\n        }\n      }\n    });\n    if (servernames.size() == 0)\n      serverName.setPrototypeDisplayValue(\"255.255.255.255:5900\");\n\n    serverName.setEditable(true);\n    editor = serverName.getEditor();\n    editor.getEditorComponent().addKeyListener(new KeyListener() {\n      public void keyTyped(KeyEvent e) {}\n      public void keyReleased(KeyEvent e) {}\n      public void keyPressed(KeyEvent e) {\n        if (KeyMap.get_keycode_fallback_extended(e) == KeyEvent.VK_ENTER) {\n          serverName.insertItemAt(editor.getItem(), 0);\n          serverName.setSelectedIndex(0);\n          handleConnect();\n        }\n      }\n    });\n\n    Container contentPane = this.getContentPane();\n    contentPane.setLayout(new GridBagLayout());\n\n    JLabel icon = new JLabel(VncViewer.logoIcon);\n    optionsButton = new JButton(\"Options...\");\n    optionsButton.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        handleOptions();\n      }\n    });\n    JButton loadButton = new JButton(\"Load...\");\n    loadButton.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        handleLoad();\n      }\n    });\n    JButton saveAsButton = new JButton(\"Save As...\");\n    saveAsButton.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        handleSaveAs();\n      }\n    });\n    aboutButton = new JButton(\"About...\");\n    aboutButton.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        handleAbout();\n      }\n    });\n    cancelButton = new JButton(\"Cancel\");\n    cancelButton.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        handleCancel();\n      }\n    });\n    connectButton = new JButton(\"Connect   \\u21B5\");\n    connectButton.addActionListener(new ActionListener() {\n      public void actionPerformed(ActionEvent e) {\n        handleConnect();\n      }\n    });\n\n    contentPane.add(icon,\n                    new GridBagConstraints(0, 0,\n                                           1, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(5, 5, 5, 5),\n                                           NONE, NONE));\n    contentPane.add(serverLabel,\n                    new GridBagConstraints(1, 0,\n                                           1, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, NONE,\n                                           new Insets(5, 10, 5, 5),\n                                           NONE, NONE));\n    contentPane.add(serverName,\n                    new GridBagConstraints(2, 0,\n                                           REMAINDER, 1,\n                                           HEAVY, LIGHT,\n                                           LINE_START, HORIZONTAL,\n                                           new Insets(5, 0, 5, 5),\n                                           NONE, NONE));\n    JPanel buttonPane1 = new JPanel();\n    Box box = Box.createHorizontalBox();\n    JSeparator separator1 = new JSeparator();\n    JSeparator separator2 = new JSeparator();\n    GroupLayout layout = new GroupLayout(buttonPane1);\n    buttonPane1.setLayout(layout);\n    layout.setAutoCreateGaps(false);\n    layout.setAutoCreateContainerGaps(false);\n\t\tlayout.setHorizontalGroup(\n\t\t  layout.createSequentialGroup()\n\t\t    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)\n\t\t      .addGroup(layout.createSequentialGroup()\n\t\t        .addGap(10)\n\t\t        .addComponent(optionsButton))\n\t\t      .addComponent(separator1)\n\t\t      .addGroup(layout.createSequentialGroup()\n\t\t        .addGap(10)\n\t\t        .addComponent(aboutButton)))\n\t\t    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)\n\t\t      .addGroup(layout.createSequentialGroup()\n\t\t        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)\n\t\t        .addComponent(loadButton)\n\t\t        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)\n\t\t        .addComponent(saveAsButton)\n\t\t        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)\n\t\t        .addComponent(box)\n\t\t        .addGap(10))\n\t\t      .addComponent(separator2)\n\t\t      .addGroup(layout.createSequentialGroup()\n\t\t        .addComponent(cancelButton)\n\t\t        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)\n\t\t        .addComponent(connectButton)\n\t\t        .addGap(10)))\n\t\t);\n\t\tlayout.setVerticalGroup(\n\t\t  layout.createSequentialGroup()\n\t\t    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)\n\t\t      .addComponent(optionsButton)\n\t\t      .addComponent(loadButton)\n\t\t      .addComponent(saveAsButton)\n\t\t      .addComponent(box))\n\t\t    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)\n\t\t    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)\n\t\t      .addComponent(separator1)\n\t\t      .addComponent(separator2))\n\t\t    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)\n\t\t    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)\n\t\t      .addComponent(aboutButton)\n\t\t      .addComponent(cancelButton)\n\t\t      .addComponent(connectButton))\n\t\t    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)\n\t\t);\n\t\tlayout.linkSize(SwingConstants.HORIZONTAL,\n                    optionsButton, loadButton, saveAsButton,\n                    aboutButton, cancelButton, box);\n    contentPane.add(buttonPane1,\n                    new GridBagConstraints(0, 1,\n                                           REMAINDER, 1,\n                                           LIGHT, LIGHT,\n                                           LINE_START, HORIZONTAL,\n                                           new Insets(5, 0, 10, 0),\n                                           NONE, NONE));\n    pack();\n  }\n\n  public void run() {\n    this.showDialog();\n  }\n\n  private void handleOptions() {\n    // quirk for mac os x\n    if (VncViewer.os.startsWith(\"mac os x\"))\n      this.setAlwaysOnTop(false);\n    OptionsDialog.showDialog(this);\n  }\n\n  private void handleLoad() {\n    String title = \"Select a TigerVNC configuration file\";\n    File dflt = new File(FileUtils.getVncConfigDir().concat(\"default.tigervnc\"));\n    FileNameExtensionFilter filter =\n      new FileNameExtensionFilter(\"TigerVNC configuration (*.tigervnc)\", \"tigervnc\");\n    File f = showChooser(title, dflt, filter);\n    if (f != null && f.exists() && f.canRead())\n      loadViewerParameters(f.getAbsolutePath());\n  }\n\n  private void handleSaveAs() {\n    String title = \"Save the TigerVNC configuration to file\";\n    File dflt = new File(FileUtils.getVncConfigDir().concat(\"default.tigervnc\"));\n    if (!dflt.exists() || !dflt.isFile())\n      dflt = new File(FileUtils.getVncConfigDir());\n    FileNameExtensionFilter filter =\n      new FileNameExtensionFilter(\"TigerVNC configuration (*.tigervnc)\", \"tigervnc\");\n    File f = showChooser(title, dflt, filter);\n    while (f != null && f.exists() && f.isFile()) {\n      String msg = f.getAbsolutePath();\n      msg = msg.concat(\" already exists. Do you want to overwrite?\");\n      Object[] options = {\"Overwrite\", \"No  \\u21B5\"};\n      JOptionPane op =\n        new JOptionPane(msg, JOptionPane.QUESTION_MESSAGE,\n                        JOptionPane.OK_CANCEL_OPTION, null, options, options[1]);\n      JDialog dlg = op.createDialog(this, \"TigerVNC\");\n      dlg.setIconImage(VncViewer.frameIcon);\n      dlg.setAlwaysOnTop(true);\n      dlg.setVisible(true);\n      if (op.getValue() == options[0])\n        break;\n      else\n        f = showChooser(title, f, filter);\n    }\n    if (f != null && (!f.exists() || f.canWrite()))\n      saveViewerParameters(f.getAbsolutePath(), (String)serverName.getSelectedItem());\n  }\n\n  private void handleAbout() {\n    VncViewer.about_vncviewer(this);\n  }\n\n  private void handleCancel() {\n    endDialog();\n  }\n\n  private void handleConnect() {\n    String servername = (String)serverName.getSelectedItem();\n    servername.trim();\n    vncServerName.put(servername).flip();\n    saveViewerParameters(null, servername);\n    endDialog();\n  }\n\n  @SuppressWarnings(\"rawtypes\")\n  MyJComboBox serverName;\n  ComboBoxEditor editor;\n  JButton aboutButton, optionsButton, connectButton, cancelButton;\n  OptionsDialog options;\n  CharBuffer vncServerName;\n  static LogWriter vlog = new LogWriter(\"ServerDialog\");\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/Tunnel.java",
    "content": "/*\n *  Copyright (C) 2012-2016 Brian P. Hinz. All Rights Reserved.\n *  Copyright (C) 2000 Const Kaplinsky.  All Rights Reserved.\n *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.\n *\n *  This is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  This software is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with this software; if not, write to the Free Software\n *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n *  USA.\n */\n\n/*\n * tunnel.java - SSH tunneling support\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.IOException;\nimport java.net.*;\nimport java.util.*;\n\nimport com.tigervnc.rdr.*;\nimport com.tigervnc.rfb.*;\nimport com.tigervnc.rfb.Exception;\nimport com.tigervnc.network.*;\n\nimport com.jcraft.jsch.JSch;\nimport com.jcraft.jsch.JSchException;\nimport com.jcraft.jsch.ConfigRepository;\nimport com.jcraft.jsch.Logger;\nimport com.jcraft.jsch.OpenSSHConfig;\nimport com.jcraft.jsch.Session;\n\nimport static com.tigervnc.vncviewer.Parameters.*;\n\npublic class Tunnel {\n\n  private final static String DEFAULT_TUNNEL_TEMPLATE\n    = \"-f -L %L:localhost:%R %H sleep 20\";\n  private final static String DEFAULT_VIA_TEMPLATE\n    = \"-f -L %L:%H:%R %G sleep 20\";\n\n  public static void createTunnel(String gatewayHost,\n                                  String remoteHost,\n                                  int remotePort,\n                                  int localPort) throws Exception {\n    if (extSSH.getValue()) {\n      String pattern = extSSHArgs.getValueStr();\n      if (pattern == null || pattern.isEmpty()) {\n        if (tunnel.getValue() && via.getValue().isEmpty()) {\n          pattern = System.getProperty(\"VNC_TUNNEL_CMD\");\n          if (pattern == null || pattern.isEmpty())\n            pattern = DEFAULT_TUNNEL_TEMPLATE;\n        } else {\n          pattern = System.getProperty(\"VNC_VIA_CMD\");\n          if (pattern == null || pattern.isEmpty())\n            pattern = DEFAULT_VIA_TEMPLATE;\n        }\n      }\n      createTunnelExt(gatewayHost, remoteHost, remotePort, localPort, pattern);\n    } else {\n      createTunnelJSch(gatewayHost, remoteHost, remotePort, localPort);\n    }\n  }\n\n  private static class MyJSchLogger implements Logger {\n    public boolean isEnabled(int level){\n      return true;\n    }\n\n    public void log(int level, String msg){\n      switch (level) {\n      case Logger.INFO:\n        vlog.info(msg);\n        break;\n      case Logger.ERROR:\n        vlog.error(msg);\n        break;\n      default:\n        vlog.debug(msg);\n      }\n    }\n  }\n\n  public static String getSshHost() {\n    String sshHost = via.getValue();\n    if (!sshHost.isEmpty()) {\n      int end = sshHost.indexOf(\":\");\n      if (end < 0)\n        end = sshHost.length();\n      sshHost = sshHost.substring(sshHost.indexOf(\"@\")+1, end);\n    }\n    return sshHost;\n  }\n\n  public static String getSshUser() {\n    String sshUser = (String)System.getProperties().get(\"user.name\");\n    String viaStr = via.getValue();\n    if (!viaStr.isEmpty() && viaStr.indexOf(\"@\") > 0)\n      sshUser = viaStr.substring(0, viaStr.indexOf(\"@\"));\n    return sshUser;\n  }\n\n  public static int getSshPort() {\n    String sshPort = \"22\";\n    String viaStr = via.getValue();\n    if (!viaStr.isEmpty() && viaStr.indexOf(\":\") > 0)\n      sshPort = viaStr.substring(viaStr.indexOf(\":\")+1, viaStr.length());\n    return Integer.parseInt(sshPort);\n  }\n\n  public static String getSshKeyFile() {\n    if (!sshKeyFile.getValue().isEmpty())\n      return sshKeyFile.getValue();\n    String[] ids = { \"id_dsa\", \"id_rsa\" };\n    for (String id : ids) {\n      File f = new File(FileUtils.getHomeDir()+\".ssh\"+\n                        FileUtils.getFileSeparator()+id);\n      if (f.exists() && f.canRead())\n        return(f.getAbsolutePath());\n    }\n    return \"\";\n  }\n\n  public static String getSshKey() {\n    if (!sshKey.getValue().isEmpty())\n      return sshKeyFile.getValue().replaceAll(\"\\\\\\\\n\", \"\\n\");\n    return \"\";\n  }\n\n  private static void createTunnelJSch(String gatewayHost, String remoteHost,\n                                       int remotePort, int localPort) throws Exception {\n    JSch.setLogger(new MyJSchLogger());\n    JSch jsch=new JSch();\n\n    try {\n      // NOTE: jsch does not support all ciphers.  User may be\n      //       prompted to accept host key authenticy even if\n      //       the key is in the known_hosts file.\n      File knownHosts = new File(FileUtils.getHomeDir()+\".ssh\"+\n                                 FileUtils.getFileSeparator()+\"known_hosts\");\n      if (knownHosts.exists() && knownHosts.canRead())\n  \t    jsch.setKnownHosts(knownHosts.getAbsolutePath());\n      ArrayList<File> privateKeys = new ArrayList<File>();\n      if (!getSshKey().isEmpty()) {\n        byte[] keyPass = null, key;\n        if (!sshKeyPass.getValue().isEmpty())\n          keyPass = sshKeyPass.getValue().getBytes();\n        jsch.addIdentity(\"TigerVNC\", getSshKey().getBytes(), null, keyPass);\n      } else if (!getSshKeyFile().isEmpty()) {\n        File f = new File(getSshKeyFile());\n        if (!f.exists() || !f.canRead())\n          throw new Exception(\"Cannot access SSH key file \"+getSshKeyFile());\n        privateKeys.add(f);\n      }\n      for (Iterator<File> i = privateKeys.iterator(); i.hasNext();) {\n        File privateKey = (File)i.next();\n        if (privateKey.exists() && privateKey.canRead())\n          if (!sshKeyPass.getValue().isEmpty())\n  \t        jsch.addIdentity(privateKey.getAbsolutePath(),\n                             sshKeyPass.getValue());\n          else\n  \t        jsch.addIdentity(privateKey.getAbsolutePath());\n      }\n\n      String user = getSshUser();\n      String label = new String(\"SSH Authentication\");\n      PasswdDialog dlg =\n        new PasswdDialog(label, (user == null ? false : true), false);\n      dlg.userEntry.setText(user != null ? user : \"\");\n      File ssh_config = new File(sshConfig.getValue());\n      if (ssh_config.exists() && ssh_config.canRead()) {\n        ConfigRepository repo =\n          OpenSSHConfig.parse(ssh_config.getAbsolutePath());\n        jsch.setConfigRepository(repo);\n      }\n      Session session=jsch.getSession(user, gatewayHost, getSshPort());\n      session.setUserInfo(dlg);\n      // OpenSSHConfig doesn't recognize StrictHostKeyChecking\n      if (session.getConfig(\"StrictHostKeyChecking\") == null)\n        session.setConfig(\"StrictHostKeyChecking\", \"ask\");\n      session.connect();\n      if (gatewayHost.equals(remoteHost))\n        session.setPortForwardingL(localPort, new String(\"localhost\"), remotePort);\n      else\n        session.setPortForwardingL(localPort, remoteHost, remotePort);\n    } catch (java.lang.Exception e) {\n      throw new Exception(e.getMessage()); \n    }\n  }\n\n  private static void createTunnelExt(String gatewayHost, String remoteHost,\n                                      int remotePort, int localPort,\n                                      String pattern) throws Exception {\n    String cmd = fillCmdPattern(pattern, gatewayHost, remoteHost,\n                                remotePort, localPort);\n    try {\n      Thread t = new Thread(new ExtProcess(cmd, vlog, true));\n      t.start();\n      // try for up to 5s\n      long start = System.currentTimeMillis();\n      while (System.currentTimeMillis() - start < 5000) {\n        if (isTunnelReady(localPort))\n          return;\n        else\n          Thread.sleep(100);\n      }\n      throw new Exception(\"SSH Tunnel not ready\");\n    } catch (java.lang.Exception e) {\n      throw new Exception(e.getMessage());\n    }\n  }\n\n  private static boolean isTunnelReady(int localPort) throws Exception {\n      // test the local forwarding socket to make\n      // sure the tunnel is up before connecting\n      SocketAddress sockAddr =\n        new InetSocketAddress(\"localhost\", localPort);\n      java.net.Socket socket = new java.net.Socket();\n      boolean ready = false;\n      try {\n        socket.connect(sockAddr, 1000);\n        ready = socket.isConnected();\n        socket.close();\n      } catch (IOException e) {\n        // expected until tunnel is up\n      } catch (java.lang.Exception e) {\n        throw new Exception(e.getMessage());\n      }\n      return ready;\n  }\n\n  private static String fillCmdPattern(String pattern, String gatewayHost,\n                                       String remoteHost, int remotePort,\n                                       int localPort) {\n    boolean H_found = false, G_found = false, R_found = false, L_found = false;\n    boolean P_found = false;\n    String cmd = extSSHClient.getValue() + \" \";\n    pattern.replaceAll(\"^\\\\s+\", \"\");\n\n    String user = getSshUser();\n    int sshPort = getSshPort();\n    gatewayHost = user + \"@\" + gatewayHost;\n\n    for (int i = 0; i < pattern.length(); i++) {\n      if (pattern.charAt(i) == '%') {\n        switch (pattern.charAt(++i)) {\n        case 'H':\n          cmd += remoteHost;\n  \t      H_found = true;\n          continue;\n        case 'G':\n          cmd += gatewayHost;\n  \t      G_found = true;\n  \t      continue;\n        case 'R':\n          cmd += remotePort;\n  \t      R_found = true;\n  \t      continue;\n        case 'L':\n          cmd += localPort;\n  \t      L_found = true;\n  \t      continue;\n        case 'P':\n          cmd += sshPort;\n  \t      P_found = true;\n  \t      continue;\n        }\n      }\n      cmd += pattern.charAt(i);\n    }\n\n    if (pattern.length() > 1024)\n      throw new Exception(\"Tunneling command is too long.\");\n\n    if (!H_found || !R_found || !L_found)\n      throw new Exception(\"%H, %R or %L absent in tunneling command template.\");\n\n    if (!tunnel.getValue() && !G_found)\n      throw new Exception(\"%G pattern absent in tunneling command template.\");\n\n    vlog.info(\"SSH command line: \"+cmd);\n    if (VncViewer.os.startsWith(\"windows\"))\n      cmd.replaceAll(\"\\\\\\\\\", \"\\\\\\\\\\\\\\\\\");\n    return cmd;\n  }\n\n  static LogWriter vlog = new LogWriter(\"Tunnel\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/UserDialog.java",
    "content": "/* Copyright (C) 2017 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.event.*;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.util.*;\nimport javax.swing.*;\nimport javax.swing.event.*;\nimport javax.swing.border.*;\nimport javax.swing.plaf.LayerUI;\n\nimport com.tigervnc.rfb.*;\nimport com.tigervnc.rfb.Point;\nimport com.tigervnc.rfb.Exception;\n\nimport static com.tigervnc.vncviewer.Parameters.*;\nimport static javax.swing.GroupLayout.*;\nimport static javax.swing.JOptionPane.*;\n\n\npublic class UserDialog implements UserPasswdGetter, UserMsgBox\n{\n  public final void getUserPasswd(boolean secure, StringBuffer user, StringBuffer password)\n  {\n    String passwordFileStr = passwordFile.getValue();\n\n    if ((password == null) && sendLocalUsername.getValue()) {\n      user.append((String)System.getProperties().get(\"user.name\"));\n      return;\n    }\n\n    if (user == null && !passwordFileStr.equals(\"\")) {\n      InputStream fp = null;\n      try {\n        fp = new FileInputStream(passwordFileStr);\n      } catch(FileNotFoundException e) {\n        throw new Exception(\"Opening password file failed\");\n      }\n      byte[] obfPwd = new byte[256];\n      try {\n        fp.read(obfPwd);\n        fp.close();\n      } catch(IOException e) {\n        throw new Exception(\"Failed to read VncPasswd file\");\n      }\n      String PlainPasswd = VncAuth.unobfuscatePasswd(obfPwd);\n      password.append(PlainPasswd);\n      password.setLength(PlainPasswd.length());\n      return;\n    }\n\n    JDialog win;\n    JLabel banner;\n    JTextField username = null;\n\n    int y;\n\n    JPanel msg = new JPanel(null);\n    msg.setSize(410, 145);\n\n    banner = new JLabel();\n    banner.setBounds(0, 0, msg.getPreferredSize().width, 20);\n    banner.setHorizontalAlignment(JLabel.CENTER);\n    banner.setOpaque(true);\n\n    if (secure) {\n      banner.setText(\"This connection is secure\");\n      banner.setBackground(Color.GREEN);\n      ImageIcon secure_icon =\n        new ImageIcon(VncViewer.class.getResource(\"secure.png\"));\n      banner.setIcon(secure_icon);\n    } else {\n      banner.setText(\"This connection is not secure\");\n      banner.setBackground(Color.RED);\n      ImageIcon insecure_icon =\n        new ImageIcon(VncViewer.class.getResource(\"insecure.png\"));\n      banner.setIcon(insecure_icon);\n    }\n    msg.add(banner);\n\n    y = 20 + 10;\n\n    JButton icon = new JButton(\"?\");\n    icon.setVerticalAlignment(JLabel.CENTER);\n    icon.setFont(new Font(\"Times\", Font.BOLD, 34));\n    icon.setForeground(Color.BLUE);\n    icon.setBounds(10, y, 50, 50);\n    // the following disables the \"?\" icon without changing the color\n    UIDefaults defaults = UIManager.getLookAndFeelDefaults();\n    Painter painter = (Painter)defaults.get(\"Button[Enabled].backgroundPainter\");\n    defaults.put(\"Button[Disabled].backgroundPainter\", painter);\n    icon.putClientProperty(\"Nimbus.Overrides.InheritDefaults\", Boolean.TRUE);\n    icon.putClientProperty(\"Nimbus.Overrides\", defaults);\n    icon.setEnabled(false);\n    msg.add(icon);\n\n    y += 5;\n\n    if (user != null && !sendLocalUsername.getValue()) {\n      JLabel userLabel = new JLabel(\"Username:\");\n      userLabel.setBounds(70, y, msg.getSize().width-70-10, 20);\n      msg.add(userLabel);\n      y += 20 + 5;\n      username = new JTextField(30);\n      username.setBounds(70, y, msg.getSize().width-70-10, 25);\n      msg.add(username);\n      y += 25 + 5;\n    }\n\n    final JPasswordField passwd = new JPasswordField(30);\n    if (password != null) {\n      JLabel passwdLabel = new JLabel(\"Password:\");\n      passwdLabel.setBounds(70, y, msg.getSize().width-70-10, 20);\n      msg.add(passwdLabel);\n      y += 20 + 5;\n      passwd.setBounds(70, y, msg.getSize().width-70-10, 25);\n      msg.add(passwd);\n      y += 25 + 5;\n    }\n\n    msg.setPreferredSize(new Dimension(410, y));\n\n    Object[] options = {\"OK  \\u21B5\", \"Cancel\"};\n    JOptionPane pane = new JOptionPane(msg,\n                                      PLAIN_MESSAGE,\n                                      OK_CANCEL_OPTION,\n                                      null,       //do not use a custom Icon\n                                      options,    //the titles of buttons\n                                      options[0]){//default button title\n      @Override\n      public void selectInitialValue() {\n        if (password != null)\n          passwd.requestFocusInWindow();\n      }\n    };\n    pane.setBorder(new EmptyBorder(0,0,0,0));\n    Component c = pane.getComponent(pane.getComponentCount()-1);\n    ((JComponent)c).setBorder(new EmptyBorder(0,0,10,10));\n    win = pane.createDialog(\"VNC Authentication\");\n\n    win.setVisible(true);\n\n    if (pane.getValue() == null || pane.getValue().equals(\"Cancel\"))\n      throw new Exception(\"Authentication cancelled\");\n\n    if (user != null)\n      if (sendLocalUsername.getValue())\n         user.append((String)System.getProperties().get(\"user.name\"));\n      else\n         user.append(username.getText());\n    if (password != null)\n      password.append(new String(passwd.getPassword()));\n  }\n\n  public boolean showMsgBox(int flags, String title, String text)\n  {\n    switch (flags & 0xf) {\n    case OK_CANCEL_OPTION:\n      return (showConfirmDialog(null, text, title, OK_CANCEL_OPTION) == OK_OPTION);\n    case YES_NO_OPTION:\n      return (showConfirmDialog(null, text, title, YES_NO_OPTION) == YES_OPTION);\n    default:\n      if (((flags & 0xf0) == ERROR_MESSAGE) ||\n          ((flags & 0xf0) == WARNING_MESSAGE))\n        showMessageDialog(null, text, title, (flags & 0xf0));\n      else\n        showMessageDialog(null, text, title, PLAIN_MESSAGE);\n      return true;\n    }\n  }\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/UserPreferences.java",
    "content": "/* Copyright (C) 2012 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// For storing user preferences not specified as configuration parameters.\n//\n\npackage com.tigervnc.vncviewer;\n\nimport java.util.prefs.Preferences;\nimport java.util.prefs.BackingStoreException;\n\nimport com.tigervnc.rfb.*;\n\npublic class UserPreferences {\n\n  private static Preferences root = Preferences.userRoot().node(\"TigerVNC\");\n\n  public static void set(String nName, String key, String val) {\n    Preferences node = root.node(nName);\n    node.put(key, val);\n  }\n\n  public static void set(String nName, String key, int val) {\n    Preferences node = root.node(nName);\n    node.putInt(key, val);\n  }\n\n  public static void set(String nName, String key, boolean val) {\n    Preferences node = root.node(nName);\n    node.putBoolean(key, val);\n  }\n\n  public static String get(String nName, String key) {\n    Preferences node = root.node(nName);\n    VoidParameter p = Configuration.getParam(key);\n    if (p != null)\n      return node.get(key, p.getDefaultStr());\n    return node.get(key, null);\n  }\n\n  public static boolean getBool(String nName, String key, boolean defval) {\n    Preferences node = root.node(nName);\n    VoidParameter p = Configuration.getParam(key);\n    if (p != null && p.isBool())\n      return node.getBoolean(key, ((p.getDefaultStr() == \"1\") ? true : false));\n    // for non-parameter preferences\n    return node.getBoolean(key, defval);\n  }\n\n  public static boolean getBool(String nName, String key) {\n    // default value of \"false\" arbitrarily chosen\n    return getBool(nName, key, false);\n  }\n\n  public static int getInt(String nName, String key) {\n    Preferences node = root.node(nName);\n    VoidParameter p = Configuration.getParam(key);\n    if (p != null && !p.isBool())\n      return node.getInt(key, Integer.parseInt(p.getDefaultStr()));\n    // FIXME\n    return -1;\n  }\n\n  public static void save() {\n    try {\n      root.sync();\n      String[] keys = root.keys();\n      for (int i = 0; i < keys.length; i++)\n        vlog.debug(keys[i]+\" = \"+root.get(keys[i], null));\n    } catch (BackingStoreException e) {\n      vlog.error(e.getMessage());\n    }\n  }\n\n  public static void save(String nName) {\n    try {\n      Preferences node = root.node(nName);\n      node.sync();\n      String[] keys = root.keys();\n      for (int i = 0; i < keys.length; i++)\n        vlog.debug(keys[i]+\" = \"+node.get(keys[i], null));\n    } catch (BackingStoreException e) {\n      vlog.error(e.getMessage());\n    }\n  }\n\n  public static void clear() {\n    try {\n      root.clear();\n      String[] children = root.childrenNames();\n      for (int i = 0; i < children.length; i++) {\n        Preferences node = root.node(children[i]);\n        node.removeNode();\n      }\n      root.sync();\n    } catch (BackingStoreException e) {\n      vlog.error(e.getMessage());\n    }\n  }\n\n  public static void clear(String nName) {\n    try {\n      Preferences node = root.node(nName);\n      node.clear();\n      node.sync();\n    } catch (BackingStoreException e) {\n      vlog.error(e.getMessage());\n    }\n  }\n\n  public static void load(String nName) {\n    // Sets the value of any corresponding Configuration parameters\n    try {\n      Preferences node = root.node(nName);\n      String[] keys = node.keys();\n      for (int i = 0; i < keys.length; i++) {\n        String key = keys[i];\n        VoidParameter p = Configuration.getParam(key);\n        if (p == null)\n          continue;\n        String valueStr = node.get(key, null);\n        if (valueStr == null)\n          valueStr = p.getDefaultStr();\n        Configuration.setParam(key, valueStr);\n      }\n    } catch (BackingStoreException e) {\n      vlog.error(e.getMessage());\n    }\n  }\n\n  public static void delete(String nName, String key) {\n      Preferences node = root.node(nName);\n      node.remove(key);\n  }\n\n  static LogWriter vlog = new LogWriter(\"UserPreferences\");\n}\n\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/Viewport.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2006 Constantin Kaplinsky.  All Rights Reserved.\n * Copyright (C) 2009 Paul Donohue.  All Rights Reserved.\n * Copyright (C) 2010, 2012-2013 D. R. Commander.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// DesktopWindow is an AWT Canvas representing a VNC desktop.\n//\n// Methods on DesktopWindow are called from both the GUI thread and the thread\n// which processes incoming RFB messages (\"the RFB thread\").  This means we\n// need to be careful with synchronization here.\n//\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.event.*;\nimport java.awt.geom.AffineTransform;\nimport java.awt.image.*;\nimport java.nio.*;\nimport java.util.*;\nimport javax.swing.*;\n\nimport javax.imageio.*;\nimport java.io.*;\n\nimport com.tigervnc.rfb.*;\nimport com.tigervnc.rfb.Cursor;\nimport com.tigervnc.rfb.Exception;\nimport com.tigervnc.rfb.Point;\n\nimport static java.awt.event.KeyEvent.*;\nimport static com.tigervnc.vncviewer.Parameters.*;\nimport static com.tigervnc.rfb.Keysymdef.*;\n\nclass Viewport extends JPanel implements ActionListener {\n\n  static LogWriter vlog = new LogWriter(\"Viewport\");\n\n  enum ID { EXIT, FULLSCREEN, MINIMIZE, RESIZE, NEWVIEWER,\n            CTRL, ALT, MENUKEY, CTRLALTDEL, CLIPBOARD,\n            REFRESH, OPTIONS, INFO, ABOUT, DISMISS,\n            ZOOM_IN, ZOOM_OUT, ZOOM_RESET, ZOOM_TO_FIT }\n\n  enum MENU { INACTIVE, TOGGLE, VALUE, RADIO,\n              INVISIBLE, SUBMENU_POINTER, SUBMENU, DIVIDER }\n\n  public Viewport(int w, int h, PixelFormat serverPF, CConn cc_)\n  {\n    cc = cc_;\n    setScaledSize(w, h);\n    frameBuffer = createFramebuffer(serverPF, w, h);\n    assert(frameBuffer != null);\n    setBackground(Color.BLACK);\n\n    cc.setFramebuffer(frameBuffer);\n\n    contextMenu = new JPopupMenu();\n\n    OptionsDialog.addCallback(\"handleOptions\", this);\n\n    addMouseListener(new MouseAdapter() {\n      public void mouseClicked(MouseEvent e) { }\n      public void mouseEntered(MouseEvent e) { handle(e); }\n      public void mouseExited(MouseEvent e) { handle(e); }\n      public void mouseReleased(MouseEvent e) { handle(e); }\n      public void mousePressed(MouseEvent e) { handle(e); }\n    });\n    addMouseWheelListener(new MouseAdapter() {\n      public void mouseWheelMoved(MouseWheelEvent e) { handle(e); }\n    });\n    addMouseMotionListener(new MouseMotionAdapter() {\n      public void mouseDragged(MouseEvent e) { handle(e); }\n      public void mouseMoved(MouseEvent e) { handle(e); }\n    });\n    addKeyListener(new KeyAdapter() {\n      public void keyTyped(KeyEvent e) { }\n      public void keyPressed(KeyEvent e) { handleSystemEvent(e); }\n      public void keyReleased(KeyEvent e) { handleSystemEvent(e); }\n    });\n    addFocusListener(new FocusAdapter() {\n      public void focusGained(FocusEvent e) {\n        ClipboardDialog.clientCutText();\n      }\n      public void focusLost(FocusEvent e) {\n        releaseDownKeys();\n      }\n    });\n    // Override default key bindings from L&F\n    getActionMap().put(\"null\", new AbstractAction() {\n      public void actionPerformed(ActionEvent e) { }\n    });\n    ArrayList<KeyStroke> keys = new ArrayList<KeyStroke>();\n    keys.add(KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0, true));\n    keys.add(KeyStroke.getKeyStroke(KeyEvent.VK_ALT, 0, true));\n    for (int i=0; i<keys.size(); i++)\n      getInputMap(JComponent.WHEN_FOCUSED).put(keys.get(i), \"null\");\n\n    setFocusTraversalKeysEnabled(false);\n    setFocusable(true);\n\n    setMenuKey();\n\n    // Send a fake pointer event so that the server will stop rendering\n    // a server-side cursor. Ideally we'd like to send the actual pointer\n    // position, but we can't really tell when the window manager is done\n    // placing us so we don't have a good time for that.\n    handlePointerEvent(new Point(w/2, h/2), 0);\n  }\n\n  // Most efficient format (from Viewport's point of view)\n  public PixelFormat getPreferredPF()\n  {\n    return frameBuffer.getPF();\n  }\n\n  // Copy the areas of the framebuffer that have been changed (damaged)\n  // to the displayed window.\n  public void updateWindow() {\n    Rect r = frameBuffer.getDamage();\n    if (!r.is_empty()) {\n      if (cc.server.width() != scaledWidth ||\n          cc.server.height() != scaledHeight) {\n        AffineTransform t = new AffineTransform(); \n        t.scale((double)scaleRatioX, (double)scaleRatioY);\n        Rectangle s = new Rectangle(r.tl.x, r.tl.y, r.width(), r.height());\n        s = t.createTransformedShape(s).getBounds();\n        paintImmediately(s.x, s.y, s.width, s.height);\n      } else {\n        paintImmediately(r.tl.x, r.tl.y, r.width(), r.height());\n      }\n    }\n  }\n\n  static final int[] dotcursor_xpm = {\n    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,\n    0x00000000, 0xff000000, 0xff000000, 0xff000000, 0x00000000,\n    0x00000000, 0xff000000, 0xff000000, 0xff000000, 0x00000000,\n    0x00000000, 0xff000000, 0xff000000, 0xff000000, 0x00000000,\n    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,\n  };\n\n  public void setCursor(int width, int height, Point hotspot,\n                        byte[] data)\n  {\n    int i;\n\n    if (cursor != null)\n      cursor.flush();\n\n    for (i = 0; i < width*height; i++)\n      if (data[i*4 + 3] != 0) break;\n\n    useSystemCursor = false;\n    if ((i == width*height) && alwaysCursor.getValue()) {\n      String cursorTypeStr = cursorType.getValueStr();\n      if (cursorTypeStr.matches(\"^System$\")) {\n        useSystemCursor = true;\n      } else {\n        vlog.debug(\"Cursor is empty: Using dot\");\n      }\n      // Do this anyway to prevent cursor being null\n      cursor = new BufferedImage(5, 5, BufferedImage.TYPE_INT_ARGB_PRE);\n      cursor.setRGB(0, 0, 5, 5, dotcursor_xpm, 0, 5);\n      cursorHotspot.x = cursorHotspot.y = 3;\n    } else {\n      if ((width == 0) || (height == 0)) {\n        cursor = new BufferedImage(tk.getBestCursorSize(0, 0).width,\n                                   tk.getBestCursorSize(0, 0).height,\n                                   BufferedImage.TYPE_INT_ARGB_PRE);\n        cursorHotspot.x = cursorHotspot.y = 0;\n      } else {\n        IntBuffer buffer = IntBuffer.allocate(width*height);\n        buffer.put(ByteBuffer.wrap(data).asIntBuffer());\n        cursor =\n          new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);\n        cursor.setRGB(0, 0, width, height, buffer.array(), 0, width);\n        cursorHotspot = hotspot;\n      }\n    }\n\n    int cw = (int) Math.floor((float) cursor.getWidth() * scaleRatioX);\n    int ch = (int) Math.floor((float) cursor.getHeight() * scaleRatioY);\n    int x = cursorHotspot.x;\n    int y = cursorHotspot.y;\n    Dimension cs = tk.getBestCursorSize(cw, ch);\n    if (cs.width != cursor.getWidth() || cs.height != cursor.getHeight()) {\n      cw = VncViewer.os.startsWith(\"windows\") ?  Math.min(cw, cs.width) : cs.width;\n      ch = VncViewer.os.startsWith(\"windows\") ?  Math.min(ch, cs.height) : cs.height;\n      BufferedImage tmp = new BufferedImage(cs.width, cs.height, BufferedImage.TYPE_INT_ARGB_PRE);\n      Graphics2D g2 = tmp.createGraphics();\n      g2.drawImage(cursor, 0, 0, cw, ch, 0, 0, width, height, null);\n      g2.dispose();\n      x = (int) Math.min(Math.floor((float) x * (float) cw / (float) width), Math.max(cw - 1, 0));\n      y = (int) Math.min(Math.floor((float) y * (float) ch / (float) height), Math.max(ch - 1, 0));\n      cursor = tmp;\n    }\n\n    setCursor(cursor, x, y);\n  }\n\n  private void setCursor(Image img, int x, int y)\n  {\n    java.awt.Point hotspot;\n    java.awt.Cursor softCursor;\n    String name = \"rfb cursor\";\n\n    hotspot = new java.awt.Point(x, y);\n    softCursor = tk.createCustomCursor(img, hotspot, name);\n    if (useSystemCursor)\n      setCursor(java.awt.Cursor.getDefaultCursor());\n    else\n      setCursor(softCursor);\n  }\n\n  public void resize(int x, int y, int w, int h) {\n    if ((w != frameBuffer.width()) || (h != frameBuffer.height())) {\n      vlog.debug(\"Resizing framebuffer from \"+frameBuffer.width()+\"x\"+\n                 frameBuffer.height()+\" to \"+w+\"x\"+h);\n      frameBuffer = createFramebuffer(frameBuffer.getPF(), w, h);\n      assert(frameBuffer != null);\n      cc.setFramebuffer(frameBuffer);\n    }\n    setScaledSize(w, h);\n  }\n\n  public int handle(MouseEvent e)\n  {\n    int buttonMask, wheelMask;\n    switch (e.getID()) {\n    case MouseEvent.MOUSE_ENTERED:\n      if (cursor != null)\n        setCursor(cursor, cursorHotspot.x, cursorHotspot.y);\n      return 1;\n    case MouseEvent.MOUSE_EXITED:\n      setCursor(java.awt.Cursor.getDefaultCursor());\n      return 1;\n    case MouseEvent.MOUSE_PRESSED:\n    case MouseEvent.MOUSE_RELEASED:\n    case MouseEvent.MOUSE_DRAGGED:\n    case MouseEvent.MOUSE_MOVED:\n    case MouseEvent.MOUSE_WHEEL:\n      buttonMask = 0;\n      if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) != 0)\n        buttonMask |= 1;\n      if ((e.getModifiersEx() & MouseEvent.BUTTON2_DOWN_MASK) != 0)\n        buttonMask |= 2;\n      if ((e.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) != 0)\n        buttonMask |= 4;\n\n      if (e.getID() == MouseEvent.MOUSE_WHEEL) {\n        wheelMask = 0;\n        int clicks = ((MouseWheelEvent)e).getWheelRotation();\n        if (clicks < 0)\n          wheelMask |= e.isShiftDown() ? 32 : 8;\n        else\n          wheelMask |= e.isShiftDown() ? 64 : 16;\n        Point pt = new Point(e.getX(), e.getY());\n        for (int i = 0; i < Math.abs(clicks); i++) {\n          handlePointerEvent(pt, buttonMask|wheelMask);\n          handlePointerEvent(pt, buttonMask);\n        }\n        return 1;\n      }\n\n      handlePointerEvent(new Point(e.getX(), e.getY()), buttonMask);\n      return 1;\n    }\n\n    return -1;\n  }\n\n  private PlatformPixelBuffer createFramebuffer(PixelFormat pf, int w, int h)\n  {\n    PlatformPixelBuffer fb;\n\n    fb = new JavaPixelBuffer(w, h);\n\n    return fb;\n  }\n\n  //\n  // Callback methods to determine geometry of our Component.\n  //\n\n  public Dimension getPreferredSize() {\n    return new Dimension(scaledWidth, scaledHeight);\n  }\n\n  public Dimension getMinimumSize() {\n    return new Dimension(scaledWidth, scaledHeight);\n  }\n\n  public Dimension getMaximumSize() {\n    return new Dimension(scaledWidth, scaledHeight);\n  }\n\n  public void paintComponent(Graphics g) {\n    Graphics2D g2 = (Graphics2D)g;\n    synchronized(frameBuffer.getImage()) {\n      if (cc.server.width() != scaledWidth ||\n          cc.server.height() != scaledHeight) {\n        g2.setRenderingHint(RenderingHints.KEY_RENDERING,\n                            RenderingHints.VALUE_RENDER_QUALITY);\n        g2.drawImage(frameBuffer.getImage(), 0, 0,\n                     scaledWidth, scaledHeight, null);\n      } else {\n        g2.drawImage(frameBuffer.getImage(), 0, 0, null);\n      }\n    }\n    g2.dispose();\n  }\n\n  public void setScaledSize(int width, int height)\n  {\n    assert(width != 0 && height != 0);\n    String scaleString = scalingFactor.getValue();\n    if (remoteResize.getValue()) {\n      scaledWidth = width;\n      scaledHeight = height;\n      scaleRatioX = 1.00f;\n      scaleRatioY = 1.00f;\n    } else {\n      if (scaleString.matches(\"^[0-9]+$\")) {\n        int scalingFactor = Integer.parseInt(scaleString);\n        scaledWidth =\n          (int)Math.floor((float)width * (float)scalingFactor/100.0);\n        scaledHeight =\n          (int)Math.floor((float)height * (float)scalingFactor/100.0);\n      } else if (scaleString.equalsIgnoreCase(\"Auto\")) {\n        scaledWidth = width;\n        scaledHeight = height;\n      } else {\n        float widthRatio = (float)width / (float)cc.server.width();\n        float heightRatio = (float)height / (float)cc.server.height();\n        float ratio = Math.min(widthRatio, heightRatio);\n        scaledWidth = (int)Math.floor(cc.server.width() * ratio);\n        scaledHeight = (int)Math.floor(cc.server.height() * ratio);\n      }\n      scaleRatioX = (float)scaledWidth / (float)cc.server.width();\n      scaleRatioY = (float)scaledHeight / (float)cc.server.height();\n    }\n    if (scaledWidth != getWidth() || scaledHeight != getHeight())\n      setSize(new Dimension(scaledWidth, scaledHeight));\n  }\n\n  private void handlePointerEvent(Point pos, int buttonMask)\n  {\n    if (!viewOnly.getValue()) {\n      if (buttonMask != lastButtonMask || !pos.equals(lastPointerPos)) {\n        try {\n          if (cc.server.width() != scaledWidth ||\n              cc.server.height() != scaledHeight) {\n            int sx = (scaleRatioX == 1.00) ?\n              pos.x : (int)Math.floor(pos.x / scaleRatioX);\n            int sy = (scaleRatioY == 1.00) ?\n              pos.y : (int)Math.floor(pos.y / scaleRatioY);\n            pos = pos.translate(new Point(sx - pos.x, sy - pos.y));\n          }\n          cc.writer().writePointerEvent(pos, buttonMask);\n        } catch (Exception e) {\n          vlog.error(\"%s\", e.getMessage());\n          cc.close();\n        }\n      }\n      lastPointerPos = pos;\n      lastButtonMask = buttonMask;\n    }\n  }\n\n  public void handleKeyPress(long keyCode, int keySym)\n  {\n    // Prevent recursion if the menu wants to send it's own\n    // activation key.\n    if ((menuKeySym != 0) && keySym == menuKeySym && !menuRecursion) {\n      popupContextMenu();\n      return;\n    }\n\n    if (viewOnly.getValue())\n      return;\n\n    if (keyCode == 0) {\n      vlog.error(\"No key code specified on key press\");\n      return;\n    }\n\n    if (VncViewer.os.startsWith(\"mac os x\")) {\n      // Alt on OS X behaves more like AltGr on other systems, and to get\n      // sane behaviour we should translate things in that manner for the\n      // remote VNC server. However that means we lose the ability to use\n      // Alt as a shortcut modifier. Do what RealVNC does and hijack the\n      // left command key as an Alt replacement.\n      switch (keySym) {\n      case XK_Meta_L:\n        keySym = XK_Alt_L;\n        break;\n      case XK_Meta_R:\n        keySym = XK_Super_L;\n        break;\n      case XK_Alt_L:\n        keySym = XK_Mode_switch;\n        break;\n      case XK_Alt_R:\n        keySym = XK_ISO_Level3_Shift;\n        break;\n      }\n    }\n\n    if (VncViewer.os.startsWith(\"windows\")) {\n      // Ugly hack alert!\n      //\n      // Windows doesn't have a proper AltGr, but handles it using fake\n      // Ctrl+Alt. Unfortunately X11 doesn't generally like the combination\n      // Ctrl+Alt+AltGr, which we usually end up with when Xvnc tries to\n      // get everything in the correct state. Cheat and temporarily release\n      // Ctrl and Alt when we send some other symbol.\n      if (downKeySym.containsValue(XK_Control_L) &&\n          downKeySym.containsValue(XK_Alt_R)) {\n        vlog.debug(\"Faking release of AltGr (Ctrl_L+Alt_R)\");\n        try {\n          cc.writer().writeKeyEvent(XK_Control_L, false);\n          cc.writer().writeKeyEvent(XK_Alt_R, false);\n        } catch (Exception e) {\n          vlog.error(\"%s\", e.getMessage());\n          cc.close();\n        }\n      }\n    }\n\n    // Because of the way keyboards work, we cannot expect to have the same\n    // symbol on release as when pressed. This breaks the VNC protocol however,\n    // so we need to keep track of what keysym a key _code_ generated on press\n    // and send the same on release.\n    downKeySym.put(keyCode, keySym);\n\n    vlog.debug(\"Key pressed: 0x%016x => 0x%04x\", keyCode, keySym);\n\n    try {\n      // Fake keycode?\n      if (keyCode > 0xffffffffL)\n        cc.writer().writeKeyEvent(keySym, true);\n      else\n        cc.writer().writeKeyEvent(keySym, true);\n    } catch (Exception e) {\n      vlog.error(\"%s\", e.getMessage());\n      cc.close();\n    }\n\n    if (VncViewer.os.startsWith(\"windows\")) {\n      // Ugly hack continued...\n      if (downKeySym.containsValue(XK_Control_L) &&\n          downKeySym.containsValue(XK_Alt_R)) {\n        vlog.debug(\"Restoring AltGr state\");\n        try {\n          cc.writer().writeKeyEvent(XK_Control_L, true);\n          cc.writer().writeKeyEvent(XK_Alt_R, true);\n        } catch (Exception e) {\n          vlog.error(\"%s\", e.getMessage());\n          cc.close();\n        }\n      }\n    }\n  }\n\n  public void handleKeyRelease(long keyCode)\n  {\n    Integer iter;\n\n    if (viewOnly.getValue())\n      return;\n\n    iter = downKeySym.get(keyCode);\n    if (iter == null) {\n      // These occur somewhat frequently so let's not spam them unless\n      // logging is turned up.\n      vlog.debug(\"Unexpected release of key code %d\", keyCode);\n      return;\n    }\n\n    vlog.debug(\"Key released: 0x%016x => 0x%04x\", keyCode, iter);\n\n    try {\n      if (keyCode > 0xffffffffL)\n        cc.writer().writeKeyEvent(iter, false);\n      else\n        cc.writer().writeKeyEvent(iter, false);\n    } catch (Exception e) {\n      vlog.error(\"%s\", e.getMessage());\n      cc.close();\n    }\n\n    downKeySym.remove(keyCode);\n  }\n\n  private int handleSystemEvent(AWTEvent event)\n  {\n\n    if (event instanceof KeyEvent) {\n      KeyEvent ev = (KeyEvent)event;\n      if (KeyMap.get_keycode_fallback_extended(ev) == 0) {\n        // Not much we can do with this...\n        vlog.debug(\"Ignoring KeyEvent with unknown Java keycode\");\n        return 0;\n      }\n\n      if (ev.getID() == KeyEvent.KEY_PRESSED) {\n        // Generate a fake keycode just for tracking if we can't figure\n        // out the proper one.  Java virtual key codes aren't unique \n        // between left/right versions of keys, so we can't use them as\n        // indexes to the downKeySym map.\n        long keyCode = KeyMap.get_keycode_fallback_extended(ev) | ((long)ev.getKeyLocation()<<32);\n\n        // Pressing Ctrl wreaks havoc with the symbol lookup, so turn\n        // that off. But AltGr shows up as Ctrl_L+Alt_R in Windows, so\n        // construct a new KeyEvent that uses a proper AltGraph for the\n        // symbol lookup.\n        int keySym;\n        if (VncViewer.os.startsWith(\"windows\") &&\n            downKeySym.containsValue(XK_Control_L) &&\n            downKeySym.containsValue(XK_Alt_R)) {\n          int mask = ev.getModifiers();\n          mask &= ~CTRL_MASK;\n          mask &= ~ALT_MASK;\n          mask |= ALT_GRAPH_MASK;\n          AWTKeyStroke ks =\n            AWTKeyStroke.getAWTKeyStroke(KeyMap.get_keycode_fallback_extended(ev), mask);\n          // The mask manipulations above break key combinations involving AltGr\n          // and a key with an accented letter on some keyboard layouts (i.e. IT).\n          // So the code should first try the modified event, but if it returns no\n          // symbol, the original event should be used.\n          final KeyEvent winev = new KeyEvent((JComponent)ev.getSource(), ev.getID(),\n                            ev.getWhen(), mask, KeyMap.get_keycode_fallback_extended(ev),\n                            ks.getKeyChar(), ev.getKeyLocation());\n          keySym = KeyMap.vkey_to_keysym(winev);\n          if (keySym == KeyMap.NoSymbol)\n            keySym = KeyMap.vkey_to_keysym(ev);\n          else\n            ev = winev;\n        } else {\n          keySym = KeyMap.vkey_to_keysym(ev);\n        }\n\n        if (keySym == KeyMap.NoSymbol)\n          vlog.error(\"No symbol for virtual key 0x%016x\", keyCode);\n\n        if (VncViewer.os.startsWith(\"linux\")) {\n          switch (keySym) {\n          // For the first few years, there wasn't a good consensus on what the\n          // Windows keys should be mapped to for X11. So we need to help out a\n          // bit and map all variants to the same key...\n          case XK_Hyper_L:\n            keySym = XK_Super_L;\n            break;\n          case XK_Hyper_R:\n            keySym = XK_Super_R;\n            break;\n          // There has been several variants for Shift-Tab over the years.\n          // RFB states that we should always send a normal tab.\n          case XK_ISO_Left_Tab:\n            keySym = XK_Tab;\n            break;\n          }\n        }\n\n        handleKeyPress(keyCode, keySym);\n\n        if (VncViewer.os.startsWith(\"mac os x\")) {\n          // We don't get any release events for CapsLock, so we have to\n          // send the release right away.\n          if (keySym == XK_Caps_Lock)\n            handleKeyRelease(keyCode);\n        }\n\n        return 1;\n      } else if (ev.getID() == KeyEvent.KEY_RELEASED) {\n        long keyCode = KeyMap.get_keycode_fallback_extended(ev) | ((long)ev.getKeyLocation()<<32);\n        handleKeyRelease(keyCode);\n        return 1;\n      }\n    }\n\n    return 0;\n  }\n\n  private void initContextMenu()\n  {\n    contextMenu.setLightWeightPopupEnabled(false);\n\n    contextMenu.removeAll();\n\n    menu_add(contextMenu, \"Exit viewer\", KeyEvent.VK_X,\n             this, ID.EXIT, EnumSet.of(MENU.DIVIDER));\n\n    menu_add(contextMenu, \"Full screen\", KeyEvent.VK_F, this, ID.FULLSCREEN,\n             window().fullscreen_active() ?\n             EnumSet.of(MENU.TOGGLE, MENU.VALUE) : EnumSet.of(MENU.TOGGLE));\n    menu_add(contextMenu, \"Minimize\", KeyEvent.VK_Z,\n             this, ID.MINIMIZE, EnumSet.noneOf(MENU.class));\n    menu_add(contextMenu, \"Resize window to session\", KeyEvent.VK_W,\n             this, ID.RESIZE,\n             window().fullscreen_active() ?\n             EnumSet.of(MENU.INACTIVE, MENU.DIVIDER) : EnumSet.of(MENU.DIVIDER));\n\n    menu_add(contextMenu, \"Clipboard viewer...\", KeyEvent.VK_UNDEFINED,\n             this, ID.CLIPBOARD, EnumSet.of(MENU.DIVIDER));\n\n    menu_add(contextMenu, \"Ctrl\", KeyEvent.VK_C,\n             this, ID.CTRL,\n             menuCtrlKey ? EnumSet.of(MENU.TOGGLE, MENU.VALUE) : EnumSet.of(MENU.TOGGLE));\n    menu_add(contextMenu, \"Alt\", KeyEvent.VK_A,\n             this, ID.ALT,\n             menuAltKey ? EnumSet.of(MENU.TOGGLE, MENU.VALUE) : EnumSet.of(MENU.TOGGLE));\n\n    if (menuKeySym != 0) {\n      String sendMenuKey = String.format(\"Send %s\", menuKey.getValueStr());\n      menu_add(contextMenu, sendMenuKey, menuKeyJava,\n               this, ID.MENUKEY, EnumSet.noneOf(MENU.class));\n    }\n\n    menu_add(contextMenu, \"Send Ctrl-Alt-Del\", KeyEvent.VK_D,\n             this, ID.CTRLALTDEL, EnumSet.of(MENU.DIVIDER));\n\n    menu_add(contextMenu, \"Refresh screen\", KeyEvent.VK_R,\n             this, ID.REFRESH, EnumSet.of(MENU.DIVIDER));\n\n    menu_add(contextMenu, \"New connection...\", KeyEvent.VK_N,\n             this, ID.NEWVIEWER, EnumSet.of(MENU.DIVIDER));\n\n    menu_add(contextMenu, \"Options...\", KeyEvent.VK_O,\n             this, ID.OPTIONS, EnumSet.noneOf(MENU.class));\n    menu_add(contextMenu, \"Connection info...\", KeyEvent.VK_I,\n             this, ID.INFO, EnumSet.noneOf(MENU.class));\n    menu_add(contextMenu, \"About TigerVNC...\", KeyEvent.VK_T,\n             this, ID.ABOUT, EnumSet.of(MENU.DIVIDER));\n\n    menu_add(contextMenu, \"Zoom in\", KeyEvent.VK_EQUALS,\n             this, ID.ZOOM_IN, EnumSet.noneOf(MENU.class));\n    menu_add(contextMenu, \"Zoom out\", KeyEvent.VK_MINUS,\n             this, ID.ZOOM_OUT, EnumSet.noneOf(MENU.class));\n    menu_add(contextMenu, \"Reset zoom\", KeyEvent.VK_0,\n             this, ID.ZOOM_RESET, EnumSet.noneOf(MENU.class));\n    menu_add(contextMenu, \"Zoom to fit (fixed aspect)\", KeyEvent.VK_F,\n             this, ID.ZOOM_TO_FIT, EnumSet.of(MENU.DIVIDER));\n\n    menu_add(contextMenu, \"Dismiss menu\", KeyEvent.VK_M,\n             this, ID.DISMISS, EnumSet.noneOf(MENU.class));\n  }\n\n  static void menu_add(JPopupMenu menu, String text,\n                       int shortcut, ActionListener cb,\n                       ID data, EnumSet<MENU> flags)\n  {\n    JMenuItem item;\n    if (flags.contains(MENU.TOGGLE)) {\n      item = new JCheckBoxMenuItem(text, flags.contains(MENU.VALUE));\n    } else {\n      if (shortcut != 0)\n        item = new JMenuItem(text, shortcut);\n      else\n        item = new JMenuItem(text);\n    }\n    item.setActionCommand(data.toString());\n    item.addActionListener(cb);\n    item.setEnabled(!flags.contains(MENU.INACTIVE));\n    menu.add(item);\n    if (flags.contains(MENU.DIVIDER))\n      menu.addSeparator();\n  }\n\n  void popupContextMenu()\n  {\n    // initialize context menu before display\n    initContextMenu();\n\n    contextMenu.setCursor(java.awt.Cursor.getDefaultCursor());\n\n    contextMenu.show(this, lastPointerPos.x, lastPointerPos.y);\n  }\n\n  public void actionPerformed(ActionEvent ev)\n  {\n    switch(ID.valueOf(ev.getActionCommand())) {\n    case EXIT:\n      cc.close();\n      break;\n    case FULLSCREEN:\n      if (window().fullscreen_active())\n        window().fullscreen_off();\n      else\n        window().fullscreen_on();\n      break;\n    case MINIMIZE:\n      if (window().fullscreen_active())\n        window().fullscreen_off();\n      window().setExtendedState(JFrame.ICONIFIED);\n      break;\n    case RESIZE:\n      if (window().fullscreen_active())\n        break;\n      int dx = window().getInsets().left + window().getInsets().right;\n      int dy = window().getInsets().top + window().getInsets().bottom;\n      window().setSize(getWidth()+dx, getHeight()+dy);\n      break;\n    case CLIPBOARD:\n      ClipboardDialog.showDialog(window());\n      break;\n    case CTRL:\n      if (((JMenuItem)ev.getSource()).isSelected())\n        handleKeyPress(0x1d, XK_Control_L);\n      else\n        handleKeyRelease(0x1d);\n      menuCtrlKey = !menuCtrlKey;\n      break;\n    case ALT:\n      if (((JMenuItem)ev.getSource()).isSelected())\n        handleKeyPress(0x38, XK_Alt_L);\n      else\n        handleKeyRelease(0x38);\n      menuAltKey = !menuAltKey;\n      break;\n    case MENUKEY:\n      menuRecursion = true;\n      handleKeyPress(menuKeyCode, menuKeySym);\n      menuRecursion = false;\n      handleKeyRelease(menuKeyCode);\n      break;\n    case CTRLALTDEL:\n      handleKeyPress(0x1d, XK_Control_L);\n      handleKeyPress(0x38, XK_Alt_L);\n      handleKeyPress(0xd3, XK_Delete);\n\n      handleKeyRelease(0xd3);\n      handleKeyRelease(0x38);\n      handleKeyRelease(0x1d);\n      break;\n    case REFRESH:\n      cc.refreshFramebuffer();\n      break;\n    case NEWVIEWER:\n      VncViewer.newViewer();\n      break;\n    case OPTIONS:\n      OptionsDialog.showDialog(cc.desktop);\n      break;\n    case INFO:\n      Window fullScreenWindow =\n        DesktopWindow.getFullScreenWindow();\n      if (fullScreenWindow != null)\n        DesktopWindow.setFullScreenWindow(null);\n      JOptionPane op = new JOptionPane(cc.connectionInfo(),\n                                       JOptionPane.PLAIN_MESSAGE,\n                                       JOptionPane.DEFAULT_OPTION);\n      JDialog dlg = op.createDialog(window(), \"VNC connection info\");\n      dlg.setIconImage(VncViewer.frameIcon);\n      dlg.setAlwaysOnTop(true);\n      dlg.setVisible(true);\n      if (fullScreenWindow != null)\n        DesktopWindow.setFullScreenWindow(fullScreenWindow);\n      break;\n    case ABOUT:\n      VncViewer.about_vncviewer(cc.desktop);\n      break;\n    case ZOOM_IN:\n      if (!remoteResize.getValue()) window().adjustRelativeScalePercent(5);\n      break;\n    case ZOOM_OUT:\n      if (!remoteResize.getValue()) window().adjustRelativeScalePercent(-5);\n      break;\n    case ZOOM_RESET:\n      if (!remoteResize.getValue()) window().resetZoomToDefault();\n      break;\n    case ZOOM_TO_FIT:\n      if (!remoteResize.getValue()) window().setZoomToFit();\n      break;\n    case DISMISS:\n      break;\n    }\n  }\n\n  private void setMenuKey()\n  {\n    menuKeyJava = MenuKey.getMenuKeyJavaCode();\n    menuKeyCode = MenuKey.getMenuKeyCode();\n    menuKeySym = MenuKey.getMenuKeySym();\n  }\n\n  public void handleOptions()\n  {\n    setMenuKey();\n    /*\n    setScaledSize(cc.server.width(), cc.server.height());\n    if (!oldSize.equals(new Dimension(scaledWidth, scaledHeight))) {\n    // Re-layout the DesktopWindow when the scaled size changes.\n    // Ideally we'd do this with a ComponentListener, but unfortunately\n    // sometimes a spurious resize event is triggered on the viewport\n    // when the DesktopWindow is manually resized via the drag handles.\n    if (cc.desktop != null && cc.desktop.isVisible()) {\n      JScrollPane scroll = (JScrollPane)((JViewport)getParent()).getParent();\n      scroll.setViewportBorder(BorderFactory.createEmptyBorder(0,0,0,0));\n      cc.desktop.pack();\n    }\n    */\n  }\n\n  public void releaseDownKeys() {\n    while (!downKeySym.isEmpty())\n      handleKeyRelease(downKeySym.keySet().iterator().next());\n  }\n\n  private DesktopWindow window() {\n    return (DesktopWindow)getTopLevelAncestor();\n  }\n  private int x() { return getX(); }\n  private int y() { return getY(); }\n  private int w() { return getWidth(); }\n  private int h() { return getHeight(); }\n  // access to cc by different threads is specified in CConn\n  private CConn cc;\n\n  // access to the following must be synchronized:\n  private PlatformPixelBuffer frameBuffer;\n\n  Point lastPointerPos = new Point(0, 0);\n  int lastButtonMask = 0;\n\n  private class DownMap extends HashMap<Long, Integer> {\n    public DownMap(int capacity) {\n      super(capacity);\n    }\n  }\n  DownMap downKeySym = new DownMap(256);\n\n  int menuKeySym;\n  int menuKeyCode, menuKeyJava;\n  JPopupMenu contextMenu;\n  boolean menuRecursion = false;\n\n  boolean menuCtrlKey = false;\n  boolean menuAltKey = false;\n\n  static Toolkit tk = Toolkit.getDefaultToolkit();\n\n  public int scaledWidth = 0, scaledHeight = 0;\n  float scaleRatioX, scaleRatioY;\n\n  static BufferedImage cursor;\n  static boolean useSystemCursor = false;\n  Point cursorHotspot = new Point();\n\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/VncViewer.java",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * Copyright (C) 2011-2013 D. R. Commander.  All Rights Reserved.\n * Copyright (C) 2011-2019 Brian P. Hinz\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n * USA.\n */\n\n//\n// VncViewer - the VNC viewer.  It behaves as much as possible like the native\n// viewers.\n//\n// Unfortunately, because of the way Java classes are loaded on demand, only\n// configuration parameters defined in this file can be set from the command\n// line.\n\npackage com.tigervnc.vncviewer;\n\nimport java.awt.*;\nimport java.awt.event.*;\nimport java.awt.Color;\nimport java.awt.Graphics;\nimport java.awt.Image;\nimport java.io.BufferedReader;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.IOException;\nimport java.io.File;\nimport java.lang.Character;\nimport java.lang.reflect.*;\nimport java.net.URL;\nimport java.nio.CharBuffer;\nimport java.util.*;\nimport java.util.jar.Attributes;\nimport java.util.jar.Manifest;\nimport javax.swing.*;\nimport javax.swing.border.*;\nimport javax.swing.plaf.FontUIResource;\nimport javax.swing.SwingUtilities;\nimport javax.swing.UIManager.*;\n\nimport com.tigervnc.rdr.*;\nimport com.tigervnc.rfb.*;\nimport com.tigervnc.network.*;\n\nimport static com.tigervnc.vncviewer.Parameters.*;\n\npublic class VncViewer implements Runnable {\n\n  public static final String aboutText =\n    new String(\"TigerVNC Java viewer v%s (%s)%n\"+\n               \"Built on %s at %s%n\"+\n               \"Copyright (C) 1999-2026 TigerVNC team and many others (see README.rst)%n\"+\n               \"See https://www.tigervnc.org for information on TigerVNC.\");\n\n  public static String version = null;\n  public static String build = null;\n  public static String buildDate = null;\n  public static String buildTime = null;\n  static ImageIcon frameIconSrc =\n    new ImageIcon(VncViewer.class.getResource(\"tigervnc.ico\"));\n  public static final Image frameIcon = frameIconSrc.getImage();\n  public static final ImageIcon logoIcon =\n    new ImageIcon(VncViewer.class.getResource(\"tigervnc.png\"));\n  public static final Image logoImage = logoIcon.getImage();\n  public static final InputStream timestamp =\n    VncViewer.class.getResourceAsStream(\"timestamp\");\n  public static final String os = \n    System.getProperty(\"os.name\").toLowerCase(Locale.ENGLISH);\n\n  private String defaultServerName;\n  int VNCSERVERNAMELEN = 256;\n  CharBuffer vncServerName = CharBuffer.allocate(VNCSERVERNAMELEN);\n\n  public static void setLookAndFeel() {\n    try {\n      if (os.startsWith(\"mac os x\")) {\n        String appClassName = new String(\"com.apple.eawt.Application\");\n        String appMethodName = new String(\"getApplication\");\n        String setIconMethodName = new String(\"setDockIconImage\");\n        // JEP-272. Platform-specific Desktop Features are strongly encapsulated\n        // in JRE 9 & above, but the API features needed aren't in JRE 8.\n        if (Float.parseFloat(System.getProperty(\"java.specification.version\")) > 1.8) {\n          appClassName = new String(\"java.awt.Taskbar\");\n          appMethodName = new String(\"getTaskbar\");\n          setIconMethodName = new String(\"setIconImage\");\n        }\n        Class appClass = Class.forName(appClassName);\n        Method getApplication = \n          appClass.getMethod(appMethodName, (Class[])null);\n        Object app = getApplication.invoke(appClass);\n        Class paramTypes[] = new Class[1];\n        paramTypes[0] = Image.class;\n        Method setDockIconImage =\n          appClass.getMethod(setIconMethodName, paramTypes);\n        setDockIconImage.invoke(app, VncViewer.logoImage);\n      }\n      // Use Nimbus LookAndFeel if it's available, otherwise fallback\n      // to the native laf, or Metal if no native laf is available.\n      String laf = System.getProperty(\"swing.defaultlaf\");\n      if (laf == null) {\n        LookAndFeelInfo[] installedLafs = UIManager.getInstalledLookAndFeels();\n        for (int i = 0; i < installedLafs.length; i++) {\n          if (installedLafs[i].getName().equals(\"Nimbus\"))\n            laf = installedLafs[i].getClassName();\n        }\n        if (laf == null)\n          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());\n      }\n      UIManager.setLookAndFeel(laf);\n      if (UIManager.getLookAndFeel().getName().equals(\"Metal\")) {\n        UIManager.put(\"swing.boldMetal\", Boolean.FALSE);\n        Enumeration<Object> keys = UIManager.getDefaults().keys();\n        while (keys.hasMoreElements()) {\n          Object key = keys.nextElement();\n          Object value = UIManager.get(key);\n          if (value instanceof FontUIResource) {\n            String name = ((FontUIResource)value).getName();\n            int style = ((FontUIResource)value).getStyle();\n            int size = ((FontUIResource)value).getSize()-1;\n            FontUIResource f = new FontUIResource(name, style, size);\n            UIManager.put(key, f);\n          }\n        }\n      } else if (UIManager.getLookAndFeel().getName().equals(\"Nimbus\")) {\n        Font f = UIManager.getFont(\"TitledBorder.font\");\n        String name = f.getName();\n        int style = f.getStyle();\n        int size = f.getSize()-2;\n        FontUIResource r = new FontUIResource(name, style, size);\n      \tUIManager.put(\"TitledBorder.font\", r);\n      }\n    } catch (java.lang.Exception e) {\n      vlog.info(e.toString());\n    }\n  }\n\n  public static void main(String[] argv) {\n    setLookAndFeel();\n    VncViewer viewer = new VncViewer(argv);\n    viewer.start();\n  }\n\n  public VncViewer(String[] argv) {\n\n    SecurityClient.setDefaults();\n\n    // Write about text to console, still using normal locale codeset\n    getTimestamp();\n    System.err.format(\"%n\");\n    System.err.format(aboutText, version, build, buildDate, buildTime);\n    System.err.format(\"%n\");\n\n    Configuration.enableViewerParams();\n\n    /* Load the default parameter settings */\n    try {\n      defaultServerName = loadViewerParameters(null);\n    } catch (com.tigervnc.rfb.Exception e) {\n      defaultServerName = \"\";\n      vlog.info(e.getMessage());\n    }\n\n    // Override defaults with command-line options\n    int i = 0;\n    for (; i < argv.length; i++) {\n      if (argv[i].length() == 0)\n        continue;\n\n      if (argv[i].equalsIgnoreCase(\"-config\")) {\n        if (++i >= argv.length)\n          usage();\n        defaultServerName = loadViewerParameters(argv[i]);\n        continue;\n      }\n\n      if (argv[i].equalsIgnoreCase(\"-log\")) {\n        if (++i >= argv.length) usage();\n        System.err.println(\"Log setting: \"+argv[i]);\n        LogWriter.setLogParams(argv[i]);\n        continue;\n      }\n\n      if (argv[i].charAt(0) == '-') {\n        if (i+1 < argv.length) {\n          if (Configuration.setParam(argv[i].substring(1), argv[i+1])) {\n            i++;\n            continue;\n          }\n        }\n        if (Configuration.setParam(argv[i]))\n          continue;\n\n        usage();\n      }\n\n      vncServerName.put(argv[i].toCharArray()).flip();\n    }\n\n    // Check if the server name in reality is a configuration file\n    potentiallyLoadConfigurationFile(vncServerName);\n\n    migrateDeprecatedOptions();\n  }\n\n  public static void usage() {\n    String usage = (\"\\nusage: vncviewer [options/parameters] \"+\n                    \"[host:displayNum]\\n\"+\n                    \"       vncviewer [options/parameters] -listen [port] \"+\n                    \"[options/parameters]\\n\"+\n                    \"       vncviewer [options/parameters] [.tigervnc file]\\n\"+\n                    \"\\n\"+\n                    \"Options:\\n\"+\n                    \"  -log <level>    configure logging level\\n\"+\n                    \"\\n\"+\n                    \"Parameters can be turned on with -<param> or off with \"+\n                    \"-<param>=0\\n\"+\n                    \"Parameters which take a value can be specified as \"+\n                    \"-<param> <value>\\n\"+\n                    \"Other valid forms are <param>=<value> -<param>=<value> \"+\n                    \"--<param>=<value>\\n\"+\n                    \"Parameter names are case-insensitive.  The parameters \"+\n                    \"are:\\n\"+\n                    \"\\n\");\n    System.err.print(usage);\n\n    Configuration.listParams(79, 14);\n    String propertiesString = (\"\\n\"+\n\"System properties (adapted from the TurboVNC vncviewer man page)\\n\"+\n\"  When started with the -via option, vncviewer reads the VNC_VIA_CMD\\n\"+\n\"  System property, expands patterns beginning with the \\\"%\\\" character,\\n\"+\n\"  and uses the resulting command line to establish the secure tunnel\\n\"+\n\"  to the VNC gateway.  If VNC_VIA_CMD is not set, this command line\\n\"+\n\"  defaults to \\\"/usr/bin/ssh -f -L %L:%H:%R %G sleep 20\\\".\\n\"+\n\"\\n\"+\n\"  The following patterns are recognized in the VNC_VIA_CMD property\\n\"+\n\"  (note that all of the patterns %G, %H, %L and %R must be present in \\n\"+\n\"  the command template):\\n\"+\n\"\\n\"+\n\"  \\t%%     A literal \\\"%\\\";\\n\"+\n\"\\n\"+\n\"  \\t%G     gateway machine name;\\n\"+\n\"\\n\"+\n\"  \\t%H     remote VNC machine name, (as known to the gateway);\\n\"+\n\"\\n\"+\n\"  \\t%L     local TCP port number;\\n\"+\n\"\\n\"+\n\"  \\t%R     remote TCP port number.\\n\"+\n\"\\n\"+\n\"  When started with the -tunnel option, vncviewer reads the VNC_TUNNEL_CMD\\n\"+\n\"  System property, expands patterns beginning with the \\\"%\\\" character, and\\n\"+\n\"  uses the resulting command line to establish the secure tunnel to the\\n\"+\n\"  VNC server.  If VNC_TUNNEL_CMD is not set, this command line defaults\\n\"+\n\"  to \\\"/usr/bin/ssh -f -L %L:localhost:%R %H sleep 20\\\".\\n\"+\n\"\\n\"+\n\"  The following patterns are recognized in the VNC_TUNNEL_CMD property\\n\"+\n\"  (note that all of the patterns %H, %L and %R must be present in \\n\"+\n\"  the command template):\\n\"+\n\"\\n\"+\n\"  \\t%%     A literal \\\"%\\\";\\n\"+\n\"\\n\"+\n\"  \\t%H     remote VNC machine name (as known to the client);\\n\"+\n\"\\n\"+\n\"  \\t%L     local TCP port number;\\n\"+\n\"\\n\"+\n\"  \\t%R     remote TCP port number.\\n\"+\n\"\\n\");\n    System.err.print(propertiesString);\n    // Technically, we shouldn't use System.exit here but if there is a parameter\n    // error then the problem is in the index/html file anyway.\n    System.exit(1);\n  }\n\n  public static void potentiallyLoadConfigurationFile(CharBuffer vncServerName) {\n    String serverName = vncServerName.toString();\n    boolean hasPathSeparator = (serverName.indexOf('/') != -1 ||\n                                (serverName.indexOf('\\\\')) != -1);\n\n    if (hasPathSeparator) {\n      try {\n        serverName = loadViewerParameters(vncServerName.toString());\n        if (serverName == \"\") {\n          vlog.info(\"Unable to load the server name from given file\");\n          System.exit(1);\n        }\n        vncServerName.clear();\n        vncServerName.put(serverName).flip();\n      } catch (com.tigervnc.rfb.Exception e) {\n        vlog.info(e.getMessage());\n        System.exit(1);\n      }\n    }\n  }\n\n  public static void newViewer() {\n    String cmd = \"java -jar \";\n    try {\n      URL url =\n        VncViewer.class.getProtectionDomain().getCodeSource().getLocation();\n      File f = new File(url.toURI());\n      if (!f.exists() || !f.canRead()) {\n        String msg = new String(\"The jar file \"+f.getAbsolutePath()+\n                                \" does not exist or cannot be read.\");\n        JOptionPane.showMessageDialog(null, msg, \"ERROR\",\n                                      JOptionPane.ERROR_MESSAGE);\n        return;\n      }\n      cmd = cmd.concat(f.getAbsolutePath());\n      Thread t = new Thread(new ExtProcess(cmd, vlog));\n      t.start();\n    } catch (java.net.URISyntaxException e) {\n      vlog.info(e.getMessage());\n    } catch (java.lang.Exception e) {\n      vlog.info(e.getMessage());\n    }\n  }\n\n  private static void getTimestamp() {\n    if (version == null || build == null) {\n      try {\n        Manifest manifest = new Manifest(timestamp);\n        Attributes attributes = manifest.getMainAttributes();\n        version = attributes.getValue(\"Version\");\n        build = attributes.getValue(\"Build\");\n        buildDate = attributes.getValue(\"Package-Date\");\n        buildTime = attributes.getValue(\"Package-Time\");\n      } catch (java.lang.Exception e) { }\n    }\n  }\n\n  public static void about_vncviewer(Container parent) {\n    String pkgDate = \"\";\n    String pkgTime = \"\";\n    try {\n      Manifest manifest = new Manifest(VncViewer.timestamp);\n      Attributes attributes = manifest.getMainAttributes();\n      pkgDate = attributes.getValue(\"Package-Date\");\n      pkgTime = attributes.getValue(\"Package-Time\");\n    } catch (java.lang.Exception e) { }\n\n    Window fullScreenWindow = DesktopWindow.getFullScreenWindow();\n    if (fullScreenWindow != null)\n      DesktopWindow.setFullScreenWindow(null);\n    String msg =\n      String.format(VncViewer.aboutText, VncViewer.version, VncViewer.build,\n                    VncViewer.buildDate, VncViewer.buildTime);\n    Object[] options = {\"Close  \\u21B5\"};\n    JOptionPane op =\n      new JOptionPane(msg, JOptionPane.INFORMATION_MESSAGE,\n                      JOptionPane.DEFAULT_OPTION, VncViewer.logoIcon, options);\n    JDialog dlg = op.createDialog(parent, \"About TigerVNC\");\n    dlg.setIconImage(VncViewer.frameIcon);\n    dlg.setAlwaysOnTop(true);\n    dlg.setVisible(true);\n    if (fullScreenWindow != null)\n      DesktopWindow.setFullScreenWindow(fullScreenWindow);\n  }\n\n  public void start() {\n    (new Thread(this, \"VncViewer Thread\")).start();\n  }\n\n  public void exit(int n) {\n    System.exit(n);\n  }\n\n  void reportException(java.lang.Exception e) {\n    String title, msg = e.getMessage();\n    int msgType = JOptionPane.ERROR_MESSAGE;\n    title = \"TigerVNC : Error\";\n    e.printStackTrace();\n    JOptionPane.showMessageDialog(null, msg, title, msgType);\n  }\n\n  public void run() {\n    cc = null;\n    UserDialog dlg = new UserDialog();\n    CSecurity.upg = dlg;\n    CSecurity.msg = dlg;\n    Socket sock = null;\n\n    /* Specifying -via and -listen together is nonsense */\n    if (listenMode.getValue() && !via.getValueStr().isEmpty()) {\n      vlog.error(\"Parameters -listen and -via are incompatible\");\n      String msg =\n        new String(\"Parameters -listen and -via are incompatible\");\n      JOptionPane.showMessageDialog(null, msg, \"ERROR\",\n                                    JOptionPane.ERROR_MESSAGE);\n      exit(1);\n    }\n\n    if (listenMode.getValue()) {\n      int port = 5500;\n\n      if (vncServerName.charAt(0) != 0 &&\n          Character.isDigit(vncServerName.charAt(0)))\n        port = Integer.parseInt(vncServerName.toString());\n\n      TcpListener listener = null;\n      try {\n        listener = new TcpListener(null, port);\n      } catch (java.lang.Exception e) {\n        reportException(e);\n        exit(1);\n      }\n\n      vlog.info(\"Listening on port \"+port);\n\n      while (sock == null)\n        sock = listener.accept();\n    } else {\n      if (vncServerName.charAt(0) == 0) {\n        try {\n          SwingUtilities.invokeAndWait(\n            new ServerDialog(defaultServerName, vncServerName));\n        } catch (InvocationTargetException e) {\n          reportException(e);\n        } catch (InterruptedException e) {\n          reportException(e);\n        }\n        if (vncServerName.charAt(0) == 0)\n          exit(0);\n      }\n    }\n\n    try {\n      cc = new CConn(vncServerName.toString(), sock);\n      while (!cc.shuttingDown)\n        cc.processMsg();\n      exit(0);\n    } catch (java.lang.Exception e) {\n      if (cc == null || !cc.shuttingDown) {\n        reportException(e);\n        if (cc != null)\n          cc.close();\n      }\n      exit(1);\n    }\n  }\n\n  static void migrateDeprecatedOptions() {\n    if (dotWhenNoCursor.getValue()) {\n      vlog.info(\"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\");\n\n      alwaysCursor.setParam(true);\n      cursorType.setParam(\"Dot\");\n    }\n  }\n\n  public static CConn cc;\n  public static StringParameter config\n  = new StringParameter(\"Config\",\n  \"Specifies a configuration file to load.\", null);\n\n  static LogWriter vlog = new LogWriter(\"VncViewer\");\n}\n"
  },
  {
    "path": "java/com/tigervnc/vncviewer/timestamp.in",
    "content": "Manifest-Version: 1.0\nMain-Class: com.tigervnc.vncviewer.VncViewer\nPackage-Date: @JAVA_DATE@\nPackage-Time: @JAVA_TIME@\nVersion: @VERSION@\nBuild: @BUILD@\n"
  },
  {
    "path": "media/CMakeLists.txt",
    "content": "set(LINUX_ICON_SIZES 16 22 24 32 48 64 128)\nset(WINDOWS_ICON_SIZES 16 24 32 48 256)\nset(MACOS_ICON_SIZES 16 32 128 256 512)\n\nfind_program(CONVERT_EXECUTABLE convert)\nfind_program(PNG2ICNS_EXECUTABLE png2icns)\n\nif(CONVERT_EXECUTABLE)\n  set(ICON_FILES icons/tigervnc.ico)\n  foreach(SIZE ${LINUX_ICON_SIZES})\n    list(APPEND ICON_FILES ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc_${SIZE}.png)\n  endforeach()\n  if(PNG2ICNS_EXECUTABLE)\n    list(APPEND ICON_FILES icons/tigervnc.icns)\n  endif()\n  add_custom_target(icons DEPENDS ${ICON_FILES})\n\n  foreach(SIZE ${LINUX_ICON_SIZES} ${WINDOWS_ICON_SIZES} ${MACOS_ICON_SIZES})\n    if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tigervnc_${SIZE}.svg)\n      set(ICON_SRC_FILE ${CMAKE_CURRENT_SOURCE_DIR}/tigervnc_${SIZE}.svg)\n    else()\n      set(ICON_SRC_FILE ${CMAKE_CURRENT_SOURCE_DIR}/tigervnc_48.svg)\n    endif()\n    add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc_${SIZE}.png\n      COMMAND ${CONVERT_EXECUTABLE} -depth 8 -background transparent\n        -size ${SIZE}x${SIZE} ${ICON_SRC_FILE}\n        ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc_${SIZE}.png\n      DEPENDS ${ICON_SRC_FILE}\n      COMMENT \"Generating icons/tigervnc_${SIZE}.png\")\n  endforeach()\n\n  foreach(SIZE ${WINDOWS_ICON_SIZES})\n    if(${SIZE} LESS_EQUAL 32)\n      list(APPEND ICO_LEGACY \\\\\\( ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc_${SIZE}.png -depth 4 -colors 16 \\\\\\))\n      list(APPEND ICO_LEGACY \\\\\\( ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc_${SIZE}.png -depth 8 -colors 256 \\\\\\))\n    endif()\n    list(APPEND ICO_NORMAL \\\\\\( ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc_${SIZE}.png \\\\\\))\n    list(APPEND ICO_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc_${SIZE}.png)\n  endforeach()\n  add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc.ico\n    COMMAND ${CONVERT_EXECUTABLE} ${ICO_LEGACY} ${ICO_NORMAL}\n      ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc.ico\n    DEPENDS ${ICO_DEPENDS}\n    COMMENT \"Generating icons/tigervnc.ico\")\n\n  if(PNG2ICNS_EXECUTABLE)\n    # FIXME: Should be a drop shadow here as well\n    foreach(SIZE ${MACOS_ICON_SIZES})\n      list(APPEND ICNS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc_${SIZE}.png)\n    endforeach()\n    add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc.icns\n      COMMAND ${PNG2ICNS_EXECUTABLE}\n          ${CMAKE_CURRENT_SOURCE_DIR}/icons/tigervnc.icns ${ICNS_FILES}\n      DEPENDS ${ICNS_FILES}\n      COMMENT \"Generating icons/tigervnc.icns\")\n  endif()\nendif()\n"
  },
  {
    "path": "media/insecure.xpm",
    "content": "/* XPM */\nstatic char *insecure[] = {\n/* columns rows colors chars-per-pixel */\n\"16 16 22 1 \",\n\"  c #000000\",\n\". c #040000\",\n\"X c #0D0000\",\n\"o c #120000\",\n\"O c #3A0000\",\n\"+ c #3D0000\",\n\"@ c #4B0000\",\n\"# c #530000\",\n\"$ c #5B0000\",\n\"% c #770000\",\n\"& c #810000\",\n\"* c #8E0000\",\n\"= c #940000\",\n\"- c #980000\",\n\"; c #AB0000\",\n\": c #BB0000\",\n\"> c #C00000\",\n\", c #DC0000\",\n\"< c #E30000\",\n\"1 c #E40000\",\n\"2 c #FC0000\",\n\"3 c #FF0000\",\n/* pixels */\n\"3333333333333333\",\n\"33333333333;%333\",\n\"33333<#XX#*. ,33\",\n\"3333<o      :333\",\n\"3333# @1-  =3333\",\n\"3333X <;. %33333\",\n\"3333  ;. :333333\",\n\"33O     &33$ O33\",\n\"33     %33$   33\",\n\"33    &33$    33\",\n\"33   &33$     33\",\n\"3;  &33$      33\",\n\";. &33$       33\",\n\"& *33$       +33\",\n\"3>33333333333333\",\n\"3333333333333333\"\n};\n"
  },
  {
    "path": "media/secure.xpm",
    "content": "/* XPM */\nstatic char *secure[] = {\n/* columns rows colors chars-per-pixel */\n\"16 16 12 1 \",\n\"  c #000000\",\n\". c #000D00\",\n\"X c #001200\",\n\"o c #003A00\",\n\"O c #003C00\",\n\"+ c #004B00\",\n\"@ c #005300\",\n\"# c #005500\",\n\"$ c #00D800\",\n\"% c #00E300\",\n\"& c #00E400\",\n\"* c #00FF00\",\n/* pixels */\n\"****************\",\n\"****************\",\n\"*****%@..@$*****\",\n\"****%X    .%****\",\n\"****@ +&%+ #****\",\n\"****. %**% .****\",\n\"****  ****  ****\",\n\"**o          O**\",\n\"**            **\",\n\"**            **\",\n\"**            **\",\n\"**            **\",\n\"**            **\",\n\"**O          O**\",\n\"****************\",\n\"****************\"\n};\n"
  },
  {
    "path": "po/CMakeLists.txt",
    "content": "# Gettext support - mostly borrowed from the Licq project\n\nfile(STRINGS LINGUAS po_FILES)\nset_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS LINGUAS)\n\nif (NOT GETTEXT_MSGMERGE_EXECUTABLE AND NOT GETTEXT_MSGFMT_EXECUTABLE)\n  message(FATAL_ERROR \"Gettext message catalog tools NOT found\")\nendif (NOT GETTEXT_MSGMERGE_EXECUTABLE AND NOT GETTEXT_MSGFMT_EXECUTABLE)\n\nfind_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)\nif (GETTEXT_XGETTEXT_EXECUTABLE)\n  # Get list of all source files\n  file(GLOB_RECURSE po_source\n    RELATIVE ${PROJECT_SOURCE_DIR}\n    ${PROJECT_SOURCE_DIR}/vncviewer/*.h\n    ${PROJECT_SOURCE_DIR}/vncviewer/*.cxx\n    ${PROJECT_SOURCE_DIR}/vncviewer/*.desktop.in.in\n    ${PROJECT_SOURCE_DIR}/vncviewer/*.metainfo.xml.in\n  )\n\n  add_custom_target(translations_update\n    ${GETTEXT_XGETTEXT_EXECUTABLE}\n      \"--directory=${PROJECT_SOURCE_DIR}\"\n      \"--output=${CMAKE_CURRENT_SOURCE_DIR}/tigervnc.pot\"\n      --default-domain=tigervnc\n      --from-code=UTF-8\n      --keyword=_\n      --keyword=p_:1c,2\n      --keyword=N_\n      \"--copyright-holder=TigerVNC team and many others \\(see README.rst\\)\"\n      --msgid-bugs-address=tigervnc-devel@googlegroups.com\n      --sort-by-file\n      --add-location\n      --add-comments=TRANSLATORS\n      ${po_source}\n    COMMENT \"Updating tigervnc.pot\"\n    VERBATIM\n  )\nendif (GETTEXT_XGETTEXT_EXECUTABLE)\n\nforeach(lang ${po_FILES})\n  set(po  \"${CMAKE_CURRENT_SOURCE_DIR}/${lang}.po\")\n  set(mo \"${CMAKE_CURRENT_BINARY_DIR}/${lang}.mo\")\n\n  # Add command to build X.mo from X.po\n  add_custom_command(OUTPUT ${mo}\n    COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} --check --check-accelerators -o ${mo} ${po}\n    DEPENDS ${po}\n  )\n\n  install(FILES ${mo}\n    DESTINATION \"${CMAKE_INSTALL_FULL_LOCALEDIR}/${lang}/LC_MESSAGES\"\n    RENAME tigervnc.mo\n  )\n\n  set(moFiles ${moFiles} ${mo})\nendforeach(lang)\n\nadd_custom_target(translations ALL DEPENDS ${moFiles})\n"
  },
  {
    "path": "po/DO_NOT_EDIT",
    "content": "DO NO EDIT ANY FILE HERE MANUALLY!\n\nThe translations here are done by the Translation Project:\n\nhttps://translationproject.org/\n\nThe .po files here are merely a copy of what's on the Translation\nProject's servers. Any local changes here will be overwritten!\n\nSee the above web page for reporting bugs or contributing in other\nways.\n"
  },
  {
    "path": "po/LINGUAS",
    "content": "ar\nbg\ncs\nda\nde\nel\neo\nes\nfi\nfr\nfur\nhe\nhu\nid\nit\nka\nko\nnl\npl\npt_BR\nro\nru\nsk\nsr\nsv\ntr\nuk\nvi\nzh_CN\nzh_TW\n"
  },
  {
    "path": "po/ar.po",
    "content": "# Arabic translation for tigervnc\n# Copyright (C) 2025 TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n#\n# Zayed Al-Saidi <zayed.alsaidi@gmail.com>, 2025.\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc-1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2025-11-16 10:56+0400\\n\"\n\"Last-Translator: Zayed Al-Saidi <zayed.alsaidi@gmail.com>\\n\"\n\"Language-Team: Arabic <(nothing)>\\n\"\n\"Language: ar\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\\n\"\n\"X-Generator: Lokalize 25.07.70\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"متّصل بالمقبس %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"متّصل بالمضيف %s المنفذ %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"أخفق الاتصال بـ \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"اسم سطح المكتب: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"المضيف: %.80s المنفذ: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"الحجم: %d × %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"صيغة البكسل: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"الترميز المطلوب: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"آخر ترميز مستخدم: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"تقدير سرعة الخط: %d كيلوبت/ث\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"إصدار البروتوكول: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"طريقة الأمن: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"أسقط الخادم الاتصال قبل أن يترسّخ الجلسة.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"أخفق الاستيثاق: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"أخفق الاستيثاق مع الخادم. السبب المعطى من الخادم:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"السعة %d كيلوبت/ث - التغيير إلى الجودة %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"السعة %d كيلوبت/ث - اللون الكامل مفعّل الآن\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"السعة %d كيلوبت/ث - اللون الكامل معطّل الآن\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"يستخدم صيغة البكسل %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"حددت هندسة غير صالحة!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"تصغير حجم النافذة لتناسب الشاشة الحالية\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"اضغط %sM لفتح قائمة السياق\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s - TigerVNC (لوحة المفاتيح مقبوضة)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s - TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"يضبط حجم النافذة لتجنب طلب ملء الشاشة العرضي\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"اضغط %sEnter لمغادرة وضع ملء الشاشة\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"إخفاق في قبض التحكم بلوحة المفاتيح\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"اضغط %s لتحرير التحكم بلوحة المفاتيح من الجلسة\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"حسب تخطيط شاشة غير صالح لطلب تغيير الحجم!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"حالة غير صالحة لمحاكاة الزر 3\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"لا يوجد رمز مسح للمفتاح الافتراضي الموسع 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"لا رمز مسح للمفتاح الافتراضي 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"رمز مسح غير صالح 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"لا يوجد رمز للمفتاح الافتراضي الموسع 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"لا يوجد رمز للمفتاح الافتراضي 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"أخفق تحديث حالة LED لوحة المفاتيح: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"لا يوجد رمز لرمز المفتاح %d (في الحالة الحالية)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"أخفق جلب حالة LED لوحة المفاتيح: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"أخفق تحديث حالة LED لوحة المفاتيح\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"أخفق جلب اضبط شاشة النظام\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"فهرس الشاشة %d غير موجود\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"خيارات TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"ألغِ\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"حسنًا\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"الضغط\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"اختيار آلي\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"اسمح بضغط JPEG\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"الترميز المفضل\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"مستوى اللون\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"كامل\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"متوسط\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"منخفض\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"منخفض جدًا\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"مستوى ضغط مخصص\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"مستوى (0=سريع، 9=أفضل)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"مستوى الجودة\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"جودة (0=ضعيفة، 9=أفضل)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"الأمن\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"التعمية\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"لا شيء\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS بشهادات مجهولة\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS بشهادات X509\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"مسار لشهادة X509 CA\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"مسار لملف X509 CRL\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"الاستيثاق\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"VNC قياسي (غير آمن بدون تعمية)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"اسم المستخدم وكلمة السر (غير آمن بدون تعمية)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"الدّخل\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"عرض فقط (تجاهل الفأرة ولوحة المفاتيح)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"الفأرة\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"محاكاة زر الفأرة الأوسط\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"أظهر المؤشر المحلي عندما لا يوفره الخادم\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"نوع المؤشر\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"نقطة\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"النظام\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"لوحة المفاتيح\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"أرسل دائمًا كل دخل لوحة المفاتيح في وضع ملء الشاشة\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"الحافظة\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"اقبل الحافظة من الخادم\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"اضبط أيضًا التحديد الأولي\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"أرسل الحافظة إلى الخادم\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"أرسل التحديد الأولي كحافظة\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"اختصارات لوحة المفاتيح\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"مفاتيح المُعدِّل لاختصارات لوحة المفاتيح:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Shift\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Shift\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Option\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"العرض\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"نمط العرض\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"موضع النافذة\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"ملء الشاشة على الشاشة الحالية\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"ملء الشاشة على كل الشاشات\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"ملء الشاشة على الشاشة/الشاشات المختارة\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"متنوّع\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"مشترك (لا تقطع اتصال المشاهدين الآخرين)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"اسأل لإعادة الاتصال عند أخطاء الاتصال\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"كل اختصارات لوحة المفاتيح معطّلة.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"لتحرير التحكم بلوحة المفاتيح من الجلسة، اضغط %s.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"لتمرير كل دخل لوحة المفاتيح إلى الجلسة، اضغط %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"لتبديل وضع ملء الشاشة، اضغط %sEnter.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"لفتح قائمة سياق الجلسة، اضغط %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"لإرسال تركيبة مفاتيح تتضمن %s مباشرة إلى الجلسة، اضغط %sSpace، وحرر شريط المسافة بدون تحرير %s، واضغط المفتاح المرغوب.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"خادم VNC:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"خيارات...\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"حمّل...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"احفظ كَ‍...\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"عن...\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"اتّصل\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"لا أستطيع تحميل تاريخ الخادم:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"اضبط TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"اختر ملف اضبط TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"لا أستطيع تحميل ملف الضبط المحدد:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"احفظ اضبط TigerVNC في ملف\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s موجود مسبقًا. أريد أن استبدل؟\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"لا\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"استبدل\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"لا أستطيع حفظ ملف الضبط المحدد:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"لا أستطيع حفظ اضبط مبدئي:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"لا أستطيع حفظ تاريخ الخادم:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"لا أستطيع تحديد مسار دليل حالة VNC\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"لا أستطيع فتح \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"أخفق قراءة السطر %d في الملف \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"السطر طويل جدًا\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"أخفق فتح ملف كلمة السر\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"استيثاق VNC\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"هذا الاتصال آمن\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"هذا الاتصال غير آمن\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"اسم المستخدم:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"كلمة السر:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"احتفظ بكلمة السر لإعادة الاتصال\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"وقع خطأ غير متوقع عند الاتصال بالخادم:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"ا&قطع الاتصال\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&ملء الشاشة\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"&صغّر\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"غيّر حجم &النافذة ليناسب الجلسة\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"أرسل Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&حدّث الشاشة\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&خيارات...\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"معلومات &الاتصال...\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"عن &TigerVNC...\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"معلومات اتصال VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"النافذة مسجلة للمس بدلًا من الإيماءات\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"أخفق ضبط تشكيلة الإيماءة (الخطأ 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"أخفق جلب معلومات الإيماءة (الخطأ 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"زر فأرة غير صالح %d، لابد أن رقمًا بين 1 و 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"مفتاح غير معالج 0x%x - لا يمكن توليد حدث لوحة المفاتيح.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"لا أستطيع جلب قناع حدث X Input 2 للنافذة 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"لا يوجد قناع حدث X Input 2 للنافذة 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"النافذة 0x%08lx فيها أكثر من قناع حدث X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"إخفاق في قبض الجهاز %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"اتّصل بخادم VNC واعرض سطح المكتب البعيد\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"الحوسبة الشبكية الافتراضية (VNC) نظام عرض بعيد يتيح لك مشاهدة بيئة سطح المكتب الافتراضي المتشغل على حاسوب آخر في الشبكة والتفاعل معها. باستخدام VNC، يمكنك تشغيل تطبيقات رسومية على حاسوب بعيد وإرسال العرض من هذه التطبيقات إلى جهازك المحلي فقط. هذه الحزمة تحتوي على عميل يمكنه الاتصال بأسطح مكاتب أخرى تشغل خادم VNC. VNC مستقل عن المنصة ويدعم نظم تشغيل ومعماربات مختلفة كخوادم وعملاء.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC إصدار عالي السرعة من VNC يستند إلى قواعد شفرة RealVNC 4 و X.org. بدأ TigerVNC كمجهود تطوير للجيل القادم لـ TightVNC على منصات Unix و Linux، لكنه انفصل عن مشروعه الأم في أوائل 2009 لتركيز TightVNC على منصات Windows. يدعم TigerVNC متغيرًا من ترميز Tight تسارعت بدرجة كبيرة باستخدام مرمّز libjpeg-turbo JPEG.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"اتصال TigerVNC بجهاز سنت أوس\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"اتصال TigerVNC بجهاز ماك أوس\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"اتصال TigerVNC بجهاز ويندوز\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"فريق TigerVNC\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"اسم المعلمة كبير جدًا\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"المعلمة كبيرة جدًا\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"صيغة غير صالحة أو قيمة كبيرة جدًا\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"أخفق إنشاء مفتاح السجل\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"أخفق إغلاق مفتاح السجل\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"أخفق حفظ \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"أخفق إزالة \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"أخفق فتح مفتاح السجل\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"أخفق قراءة مدخل تاريخ الخادم %d: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"أخفق قراءة المعلمة \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"لا أستطيع تحديد مسار دليل ضبط VNC\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"لا أستطيع ترميز المعلمة\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"ملف الضبط %s بصيغة غير صالحة\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"صيغة غير صالحة\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"معلمة غير معروفة\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"رسالة واردة (0x%x) لنافذة غير معالجة\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"حددت نافذة غير صالحة 0x%08lx لقاء قبض المؤشر\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"أخفق إنشاء معالج اللمس: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"لا أستطيع إرفاق معالج الحدث بالنافذة (الخطأ 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"أخفق جلب بيانات الحدث لحدث X Input\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"حدث X Input لنافذة غير معروفة\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"امتداد X Input غير متاح.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2 (أو أحدث) غير متاح.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2.2 (أو أحدث) غير متاح. لا دعم لإيماءات اللمس.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC v%s\\n\"\n\"بني على: %s\\n\"\n\"حقوق النشر (C) 1999-%d لفريق TigerVNC والعديد من الآخرين (انظر README.rst)\\n\"\n\"انظر https://www.tigervnc.org لمعلومات عن TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"عن TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"خطأ FLTK داخلي. يغلق.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"هل تريد محاولة إعادة الاتصال؟\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"خطأ عند بدء اتصال جديد: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"رسالة إنهاء %d واردة. TigerVNC سيغلق الآن.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"نعم\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"أغلق\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"عن\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"أخفِ\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"أنهِ\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"الخدمات\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"أخفِ الآخرين\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"أظهر الكلّ\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&ملف\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"ا&تصال جديد\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"الاستخدام: %s [معلمات] [مضيف][:رقم_العرض]\\n\"\n\"       %s [معلمات] [مضيف][::منفذ]\\n\"\n\"       %s [معلمات] [مقبس يونكس]\\n\"\n\"       %s [معلمات] -استمع [منفذ]\\n\"\n\"       %s [معلمات] [ملف .tigervnc]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"الخيارات:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - يحدد عرض X لنافذة العارض\\n\"\n\"  -geometry geometry - موضع مبدئي لنافذة TigerVNC الرئيسية. انظر\\n\"\n\"                       صفحة man للتفاصيل.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"يمكن تشغيل المعلمات بـ -<معلمة> أو إيقاف تشغيلها بـ -<معلمة>=0\\n\"\n\"المعلمات التي تأخذ قيمة يمكن تحديدها كـ -<معلمة> <قيمة>\\n\"\n\"الأشكال الصالحة الأخرى هي <معلمة>=<قيمة> -<معلمة>=<قيمة> --<معلمة>=<قيمة>\\n\"\n\"أسماء المعلمات غير حساسة لحالة الأحرف. المعلمات هي:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors مهجور، اضبط FullScreenMode على 'all' بدلًا من ذلك\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor مهجور، اضبط AlwaysCursor على 1 و CursorType على 'Dot' بدلًا من ذلك\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc مهجور، يرجى استشارة 'man vncviewer' لمسارات الهجرة.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc مهجور، يرجى التحويل إلى موقع %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"لا أستطيع إنشاء دليل ضبط VNC \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"لا أستطيع تحديد مسار دليل بيانات VNC\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"لا أستطيع إنشاء دليل بيانات VNC \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"لا أستطيع إنشاء دليل حالة VNC \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: خيار غير معروف '%s'\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"انظر '%s --help' لمزيد من المعلومات.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: وسيط إضافي '%s'\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"المعلمتان -listen و -via غير متوافقتين\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"لا أستطيع الاستماع للاتصالات الواردة\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"يستمع على المنفذ %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"أخفق انتظار اتصال VNC وارد:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"أخفق إعداد نفق معمم:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"عارض سطح المكتب البعيد\"\n"
  },
  {
    "path": "po/bg.po",
    "content": "# Bulgarian translation of tigervnc po-file.\n# Copyright (C) 2015, 2017, 2018, 2019. 2021, 2022, 2024, 2025 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Alexander Shopov <ash@kambanaria.org>, 2015, 2017, 2018, 2019, 2021, 2022, 2024, 2025.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2025-11-15 09:16+0100\\n\"\n\"Last-Translator: Alexander Shopov <ash@kambanaria.org>\\n\"\n\"Language-Team: Bulgarian <dict@ludost.net>\\n\"\n\"Language: bg\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Връзка към гнездо „%s“\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Връзка към машина „%s“, порт %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Неуспешно свързване с „%s“:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Име на работен плот: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Машина: %.80s, порт: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Размер: %d ✕ %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Формат на пикселите: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Заявено кодиране: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Последно ползвано кодиране: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Оценка на скоростта на линията: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Версия на протокола: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Вид сигурност: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Връзката бе прекъсната от страната на сървъра, преди да се установи сесия.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Неуспешна идентификация: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Неуспешна идентификация пред сървъра. Сървърът върна следната причина:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Скорост %d kbit/s — преминаване към качество %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Скорост %d kbit/s — пълният цвят е включен\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Скорост %d kbit/s — пълният цвят е изключен\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Ползва се формат на пикселите %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Указани са неправилни размери!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Намаляване на размера на прозореца, за да се побере на текущия монитор\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"За отваряне на контекстното меню натиснете %sM\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s — TigerVNC (прихваната клавиатура)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s — TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Преоразмеряване на екрана за избягване на случайна заявка за цял екран\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"Натиснете %sEnter за излизане от режима на цял екран\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"Неуспешно прихващане на клавиатурата\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"Натиснете %s за прекратяване на прихващането на клавиатурата от сесията\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Изчислено е неправилно разположение на екрана според заявката за преоразмеряване!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Неправилно състояние за емулиране на 3 бутона\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Липсва код за разширения виртуален клавиш 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Липсва код за виртуалния клавиш 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Неправилен код 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Липсва знак за разширения виртуален клавиш 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Липсва знак за виртуалния клавиш 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Неуспешно обновяване на състоянието на светодиодите на клавиатурата: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Липсва знак за кода за клавиш %d (в текущото състояние)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Неуспешно получаване на състоянието на светодиодите на клавиатурата: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Неуспешно обновяване на състоянието на светодиодите на клавиатурата\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Неуспешно получаване на настройките на монитора\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Монитор с индекс %d не съществува\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"Настройки на TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Отмяна\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"Добре\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"Компресия\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"Автоматичен избор\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"Позволяване на компресия JPEG\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"Предпочитано кодиране\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"Цвят\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"Пълен\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"Среден\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"Беден\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"Съвсем беден\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"Друго ниво на компресия\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"ниво (0≡бързо, 9≡най-добро)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"Качество\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"качество (0≡лошо, 9≡най-добро)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"Сигурност\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"Шифриране\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"Без\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS + анонимен сертификат\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS + сертификат X509\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Път към сертификата на удостоверителя по X509\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Път към файла CPL по X509\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"Идентификация\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Стандартна за VNC (несигурна без шифриране)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Име и парола (несигурна без шифриране)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"Права̀\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Визуализация (без вход от мишка и клавиатура)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"Мишка\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Емулация на среден бутон на мишката\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Показване на локален курсор, когато сървърът не предоставя такъв\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"Вид курсор\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"Точка\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"Системен\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"Клавиатура\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"В режим на цял екран да се праща целия вход от клавиатурата\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"Буфер за обмен\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"Приемане на буфера за обмен от сървъра\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"Задаване и на основния избор\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"Изпращане на буфера за обмен към сървъра\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Изпращане на основния избор като буфер за обмен\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"Клавишни комбинации\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"Модификатори на клавишните комбинации:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Shift\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Shift\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Option\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"Визуализация\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"Режим на визуализация\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"В прозорец\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"На цял екран на текущия монитор\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"На цял екран на всички монитори\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"На цял екран на избрания монитор/и\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"Разни\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Споделена (без прекъсване на връзката към останалите визуализатори)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Запитване на повторно свързване при грешка\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"Всички клавишни комбинации са изключени.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"За прекратяване на прихващането на клавиатурата от сесията, натиснете %s.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"За препредаване на целия вход от клавиатурата, натиснете %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"За превключване на режима на цял екран натиснете %sEnter.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"За отваряне на контекстното меню за сесията натиснете %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"За изпращане на клавишна комбинация, която включва %s, директно към сесията натиснете %sSpace, отпуснете клавиша за интервал, без та отпускате %s и натиснете желания клавиш.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"Сървър за VNC:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"Настройки…\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"Зареждане…\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"Запазване като…\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"Относно…\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"Свързване\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Историята на сървърите не може да се получи:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Настройки на връзка за TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Избор на файл с настройки на връзка за TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Указаният файл с настройки не може да се зареди:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Запазване на настройките на връзката във файл за TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"Файлът „%s“ вече съществува, да се презапише ли\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Не\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"Презаписване\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Указаният файл с настройки не може да се запази:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Стандартните настройки не може да се запазят:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Историята на сървърите не може да се запази:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"Пътят до папката за състоянието на VNC не може да бъде получен\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"„%s“ не може да се отвори\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Ред %d от файл „%s“ не може да се прочете\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"Прекалено дълъг ред\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"Файлът с паролата не може да се отвори\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"Идентификация за VNC\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"Тази връзка е сигурна\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"Тази връзка не е сигурна\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"Име:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"Парола:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"Запазване на паролата за повторно свързване\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Неочаквана грешка в комуникацията със сървъра:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"&Прекъсване на връзка\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Цял екран\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"&Минимизиране\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"&Преоразмеряване на прозореца към сесията\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"„&Ctrl“\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"„&Alt“\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Изпращане на „Ctrl-Alt-&Del“\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Опресняване на &екрана\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Настройки…\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&Информация за връзката…\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"&Относно TigerVNC…\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"Информация за връзката по VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Прозорецът е регистриран за докосване, а не за жестове\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Настройките на жестовете не може да се зададат (грешка 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Неуспешно получаване на информацията за жестове (грешка 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Неправилен бутон на мишка: %d — трябва да е от 1 до 7, включително.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Неподдържан клавиш 0x%x — не може да се генерира събитие от клавиатурата.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Не може да се получи маската за събития по X Input 2 за прозорец 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Прозорец 0x%08lx няма маска за събития по X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Прозорец 0x%08lx има поне две маски за събития по X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Неуспешно прихващане на устройство %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Свързване към сървър за VNC и визуализация на отдалечено работно място\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC — виртуални компютри по мрежата) е система за отдалечена визуализация, която позволява да работите с виртуална работна среда, която е стартирана на друг компютър в мрежата. С VNC може да стартирате графични приложения на отдалечени машини, а да ги визуализирате на собственото си устройство. Пакетът съдържа клиент, с който може да се свържете към отдалечени работни среди, които ползват сървър за VNC. Самата система VNC е платформено независима и поддържа различни операционни системи и хардуерни архитектури както за сървъри, така и за клиенти.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC е високоскоростна версия на VNC, която произлиза от RealVNC 4 и X.org. TigerVNC се появява като версия на TightVNC за разработчици под Unix и Linux, но се отделя от родителския проект още през 2009, за да може проектът TightVNC да се концентрира върху Windows. TigerVNC поддържа вариант на кодирането Tight, което е ускорено чрез ползването на кодера за JPEG „libjpeg-turbo“.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"Връзка с TigerVNC към компютър с CentOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"Връзка с TigerVNC към компютър с macOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"Връзка с TigerVNC към компютър с Windows\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"Екипът на TigerVNC\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Името на опцията е прекалено дълго\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"Стойността на опцията е прекалено голяма\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"Неправилен формат или прекалено голяма стойност\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"Ключът за регистъра не може да се създаде\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"Ключът за регистъра не може да се затвори\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"„%s“ не може да се запише: %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"„%s“ не може да се изтрие: %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"Ключът за регистъра не може да си отвори\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Запис №%d в историята на сървърите не може да си прочете: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Неуспешно прочитане на опцията „%s“: %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"Пътят до папката за настройките на VNC не може да се получи\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"Опцията не може да си кодира\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Неправилен формат на файла с настройки „%s“\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"Неправилен формат\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"Непозната опция\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Получено е съобщение (0x%x) за неподдържан прозорец\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Посочен е неправилен прозорец 0x%08lx за прихващане на показалеца\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Функционалността за обработка на събития докосване не може да се създаде: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Не може да се закачи функция за обработка на събития към прозорец (грешка 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Не може да се получат данните за събитие на X Input\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"Събитие на X Input за неизвестен прозорец\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"Разширението X Input липсва.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"Липсва версия 2 или по-нова на разширението X Input.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"Липсва версия 2.2 или по-нова на разширението X Input. Събитията жестове не се поддържат.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC, версия: %s\\n\"\n\"Компилиран на: %s\\n\"\n\"Авторски права © 1999-%d екипът на TigerVNC и мн. др.\\n\"\n\"(погледнете файла README.rst)\\n\"\n\"За повече информация за TigerVNC: http://www.tigervnc.org\\n\"\n\"Превод на български: Александър Шопов\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"Относно TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Вътрешна грешка на FLTK. Спиране на програмата.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Нов опит за връзка?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"Грешка при стартирането на нова връзка: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"Получен е сигнал %d. TigerVNC ще спре работа.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Да\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Затваряне\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"Относно\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Скриване\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Спиране\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Услуги\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Скриване на другите\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Показване на всички\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Файл\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"Нова &връзка\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Употреба: %s [ОПЦИЯ…] [ХОСТ][:НОМЕР_НА_ДИСПЛЕЙ]\\n\"\n\"          %s [ОПЦИЯ…] [ХОСТ][::ПОРТ]\\n\"\n\"          %s [ОПЦИЯ…] [ГНЕЗДО_НА_UNIX]\\n\"\n\"          %s [ОПЦИЯ…] -listen [ПОРТ]\\n\"\n\"          %s [ОПЦИЯ…] [ФАЙЛ_.tigervnc]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Опции:\\n\"\n\"\\n\"\n\"  -display ДИСПЛЕЙ    — указва ДИСПЛЕЙ на X сървър за прозореца на визуализатора\\n\"\n\"  -geometry ГЕОМЕТРИЯ — първоначална позиция на основния прозорец на TigerVNC.\\n\"\n\"                        За повече информация вижте страницата от ръководството.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Опциите се задават с -ОПЦИЯ, а се изключват с -ОПЦИЯ=0\\n\"\n\"Ако опция приема стойност, тя може да се зададе с -ОПЦИЯ СТОЙНОСТ\\n\"\n\"Други варианти на изписване са ОПЦИЯ=СТОЙНОСТ -ОПЦИЯ=СТОЙНОСТ --ОПЦИЯ=СТОЙНОСТ\\n\"\n\"Опциите може да се изписват с малки или главни букви, или смесено.\\n\"\n\"Опциите са:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"Настройката „FullScreenAllMonitors“ е остаряла, вместо това задайте „FullScreenMode“ да е „all“\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"Настройката „DotWhenNoCursor“ е остаряла: задайте „AlwaysCursor“ да е 1, а „CursorType“ да е „Dot“\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"Папката „~/.vnc“ е остаряла. Вижте ръководството „man vncviewer“ кои папки се ползват.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"Папката „%%APPDATA%%\\\\vnc“ е остаряла. Ползвайте „%%APPDATA%%\\\\TigerVNC“.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"Папката за настройки на VNC не може да се създаде „%s“: %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"Папката за данни на VNC не може да се създаде\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"Папката за данни на VNC не може да се създаде „%s“: %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"Папката за състояние на VNC не може да се създаде „%s“: %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: Непозната опция „%s“\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"За повече информация вижте изхода от „%s --help“\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Допълнителен аргумент „%s“\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"„-listen“ и „-via“ са несъвместими\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Не може да се слуша за входящи връзки\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Слуша се на порт %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Неуспешно изчакване на входяща връзка по VNC:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Неуспешно установяване на шифриран тунел:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"Визуализатор на отдалечени работни места\"\n"
  },
  {
    "path": "po/checkaccels",
    "content": "#!/usr/bin/python3\n\nimport polib\nimport sys\n\nok = True\nfor f in sys.argv[1:]:\n    strings = {}\n    for msg in polib.pofile(f):\n        if msg.msgctxt is None:\n            continue\n        if msg.msgctxt not in strings:\n            strings[msg.msgctxt] = set()\n        strings[msg.msgctxt].add(msg)\n\n    for msgctxt in strings:\n        accels = set()\n        for msg in strings[msgctxt]:\n            if \"&\" not in msg.msgstr:\n                if \"&\" in msg.msgid:\n                    print(\"%s: No accelerator in \\\"%s\\\"\" % (f, msg.msgstr))\n                    ok = False\n                continue\n            if msg.msgstr.count(\"&\") > 1:\n                print(\"%s: Multiple accelerators in \\\"%s\\\"\" % (f, msg.msgstr))\n                ok = False\n                continue\n\n            accel = msg.msgstr[msg.msgstr.find(\"&\")+1]\n            if accel in accels:\n                print(\"%s: Duplicate accelerator \\\"%s\\\" in \\\"%s\\\"\" %\n                      (f, accel, msg.msgstr))\n                ok = False\n            accels.add(accel)\n\nif not ok:\n    sys.exit(1)\n"
  },
  {
    "path": "po/cs.po",
    "content": "# Czech translation for TigerVNC.\n# Copyright (C) 2018 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Petr Pisar <petr.pisar@atlas.cz>, 2018, 2019, 2021, 2022, 2024, 2025.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2025-11-14 10:37+01:00\\n\"\n\"Last-Translator: Petr Pisar <petr.pisar@atlas.cz>\\n\"\n\"Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\\n\"\n\"Language: cs\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Připojeno na socket %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Připojeno na stroj %s port %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Připojení k „%s“ selhalo:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Název plochy: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Stroj: %.80s port: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Velikost: %d×%d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Formát pixelu: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Požadované kódování: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Poslední použité kódování: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Odhad rychlosti linky: %d kb/s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Verze protokolu: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Způsob zabezpečení: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Spojení bylo serverem zahozeno dříve, než mohla být ustanovena relace.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Autentizace selhala: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Autentizace u serveru selhala. Server uvedl tento důvod:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Tok %d kb/S – kvalita se mění na %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Tok %d kb/s – plný počet barev je nyní zapnut\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Tok %d kb/s – plný počet barev je nyní vypnut\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Používá se formát pixelu %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Zadána neplatná geometrie!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Velikost okna se zmenšuje, aby se vešlo na současný monitor\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"Kontextovou nabídku otevřete stisknutím %sM\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s – TigerVNC (klávesnice zabrána)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s – TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Upravuje se velikost okna, by se předešlo nechtěnému požadavku na režim celé obrazovky\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"Stiskněte %sEnter pro opuštění režimu celé obrazovky\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"Zabrání ovládání klávesnice se nezdařilo\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"Pro uvolnění ovládání klávesnice v této relaci stiskněte %s\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Pro požadavek na změnu velikosti bylo vypočteno neplatné rozložení obrazovky!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Neplatný stav 3-tlačítkové emulace\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Žádný scan kód pro rozšířenou virtuální klávesu 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Žádný scan kód pro virtuální klávesu 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Neplatný scan kód 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Žádný symbol pro rozšířenou virtuální klávesu 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Žádný symbol pro virtuální klávesu 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Aktualizace stavu diod klávesnice se nezdařila: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Žádný symbol pro kód klávesy %d (v současném stavu)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Získaní stavu diod klávesnice se nezdařilo: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Aktualizace stavu diod klávesnice se nezdařila\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Získání nastavení systémového monitoru selhalo\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Monitor číslo %d neexistuje\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"Volby TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Zrušit\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"Komprese\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"Automaticky vybrat\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"Povolit kompresi JPEG\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"Upřednostňované kódování\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"Barevnost\"\n\n# Attributes for \"Color level\"\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"Plná\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"Střední\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"Nízká\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"Velmi nízká\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"Uživatelská úroveň komprese\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"úroveň (0 = rychlá, 9 = nejlepší)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"Úroveň kvality\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"kvalita (0 = špatná, 9 = nejlepší)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"Zabezpečení\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"Šifrování\"\n\n# TODO: Conext for gender\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"Ne\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS s anonymními certifikáty\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS s certifikáty X509\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Cesta k X509 certifikátu autority\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Cesta k souboru se seznamem odvolaných certifikátů\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"Autentizace\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Standardní VNC (bez šifrování, nezabezpečené)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Uživatelské jméno a heslo (bez šifrování, nezabezpečené)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"Vstup\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Pouze se dívat (ignoruje myš a klávesnici)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"Myš\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Emulovat prostřední tlačítko myši\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Zobrazovat místní ukazatel, když sever žádný nedodá\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"Druh ukazatele\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"Puntík\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"Systémový\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"Klávesnice\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"V režimu celé obrazovky vždy odesílat veškerý vstup klávesnice\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"Schránka\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"Přijímat schránku ze serveru\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"Rovněž nastavovat primární výběr\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"Posílat schránku serveru\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Posílat primární výběr jako schránku\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"Klávesové zkratky\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"Modifikační klávesy pro klávesové zkratky:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Shift\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"^ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Shift\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Option\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"Zobrazení\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"Režim zobrazení\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"V okně\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"Přes celou obrazovku současného monitoru\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"Přes celou obrazovku na všech monitorech\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Přes celou obrazovku na vybraných monitorech\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"Ostatní\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Sdílené (neodpojit ostatní diváky)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Při chybách spojení se dotázat na nové\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"Všechny klávesové zkratky jsou zakázány.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"Pro uvolnění ovládání klávesnice z relace stiskněte %s.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"Pro předávání veškerého vstupu z klávesnice do relace stiskněte %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"Pro přepnutí režimu celé obrazovky stiskněte %sEnter.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"Pro otevření kontextové nabídky relace stiskněte %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"Pro předání kombinace kláves, která obsahuje %s, přímo do relace stiskněte %sMezerník, pak uvolněte mezerník, ale držte %s a nakonec k tomu stiskněte požadovanou klávesu.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"VNC server:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"Volby…\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"Načíst…\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"Uložit jako…\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"O aplikaci…\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"Připojit\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Historii serverů nelze načíst:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Nastavení TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Vybrat konfigurační souboru TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Zadaný konfigurační soubor nelze načíst:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Uložit nastavení TigerVNC do souboru\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s již existuje. Chcete přepsat?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Ne\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"Přepsat\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Zadaný konfigurační soubor nezle uložit:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Výchozí nastavení nelze uložit:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Historii serverů nelze uložit:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"Cestu ke stavovému adresáři VNC nebylo možné určit\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"„%s“ nebylo možné otevřít\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Přečtení řádku %d v souboru „%s“ selhalo\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"Příliš dlouhý řádek\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"Otevření souboru s heslem selhalo\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"Autentizace VNC\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"Toto spojení je zabezpečené\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"Toto spojení není zabezpečené\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"Jméno:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"Heslo:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"Zapamatovat heslo pro případ obnovení spojení\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Při komunikaci se serverem došlo k neočekávané chybě:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"Od&pojit\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"Přes celou o&brazovku\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Minimali&zovat\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Přizpůsobit &velikost okna relaci\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Poslat Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Obnovit ob&razovku\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"V&olby…\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Úda&je o spojení…\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"O &TigerVNC…\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"Údaje o spojení VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Okno je registrováno k dotykům namísto ke gestům\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Nastavení gest selhalo (chyba 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Získání údajů o gestech selhalo (chyba 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Neplatné číslo tlačítka myši %d. Musí se jednat o číslo mezi 1 a 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Neobsluhovaná klávesa 0x%x – nelze vytvořit událost klávesnice.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Masku událostí X Input 2 pro okno 0x%08lx nelze získat\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Okno 0x%08lx nemá žádnou masku událostí X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Okno 0x%08lx má více než jednu masku událostí X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Zabrání zařízení %i se nezdařilo\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Připojí se k severu VNC a zobrazí vzdálenou plochu\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC) je systém vzdáleného displeje, který umožňuje přes síť zobrazit a ovládat virtuální desktopové prostředí běžící na jiném počítači. Pomocí VNC můžete spouštět grafické aplikace na vzdáleném stroji a poslat výstup těchto aplikací na vaše místní zařízení. Tento balík obsahuje klient, který umožňuje se připojit na jiné desktopové prostředí provozující VNC server. VNC je platformě nezávislé a podporuje celou řadu operačních systémů a architektur, jak na straně serveru, tak na straně klientu.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC je vysokorychlostní verze VNC založená na kódu RealVNC 4 a X.org. TigerVNC začalo jako úsilí o vývoj nové generace TightVNC pro Unix a Linux, ale na počátku roku 2009 se oddělilo od rodičovského projektu, aby se TightVNC mohlo soustředit na platformu Windows. TigerVNC podporuje variantu kódování Tight, která je značně urychlena použitím libjpeg-turbo, kodéru a dekodéru formátu JPEG.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"Spojení TigerVNC ke stroji s CentOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"Spojení TigerVNC ke stroji s macOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"Spojení TigerVNC ke stroji s Windows\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"Tým TigerVNC\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Název parametru je příliš dlouhý\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"Parametr je příliš dlouhý\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"Neplatný formát nebo příliš velká hodnota\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"Vytvoření klíče v registru selhalo\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"Uzavření klíče v registru selhalo\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Uložení „%s“ selhalo: %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Odstranění „%s“ selhalo: %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"Otevření klíče v registru selhalo\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Položku historie serverů %d se nepodařilo přečíst: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Přečtení parametru „%s“ selhalo: %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"Cestu ke konfiguračnímu adresáři VNC nebylo možné určit\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"Parametr nebylo možné zakódovat\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Konfigurační soubor %s je v neplatném formátu\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"Neplatný formát\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"Neznámý parametr\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Obdržena zpráva (0x%x) pro neobsluhované okno\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Pro zabrání ukazatele byl zadáno neplatné okno 0x%08lx\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Obsluhu dotyků se nepodařilo vytvořit: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"K oknu nebylo možné připojit obsluhu událostí (chyba 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Z události X Input nebylo možné získat data události\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"Událost X Input pro neznámé okno\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"Rozšíření X Input není dostupné.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"Rozšíření X Input 2 (nebo novější) není dostupné.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"Rozšíření X Input 2.2 (nebo novější) není dostupné. Dotyková gesta nebudou podporována.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC v%s\\n\"\n\"Sestaven v: %s\\n\"\n\"Copyright © 1999–%d tým TigerVNC a mnozí další (vizte README.rst)\\n\"\n\"Podrobnosti o TigerVNC naleznete na <https://www.tigervnc.org/>.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"O TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Vnitřní chyba FLTK. Končí se.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Zkusit se znovu připojit?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"Chyba při zahajování nového spojení: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"Byl přijat ukončovací signál %d. TigerVNC se nyní ukončí.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Ano\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Zavřít\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"O aplikaci\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Skrýt\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Ukončit\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Služby\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Skrýt ostatní\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Ukázat všechny\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Soubor\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Nové spojení\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Usage: %s [parametry] [stroj][:číslo_displeje]\\n\"\n\"       %s [parametry] [stroj][::port]\\n\"\n\"       %s [parametry] [unixový_socket]\\n\"\n\"       %s [parametry] -listen [port]\\n\"\n\"       %s [parametry] [soubor_.tigervnc]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Přepínače:\\n\"\n\"\\n\"\n\"  -display displej    − Určuje displej X pro okno prohlížeče\\n\"\n\"  -geometry geometrie − Počáteční umístění hlavního okna TigerVNC. Pro\\n\"\n\"                        podrobnosti nahlédněte to manuálu.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Parametry lze zapnout pomocí -<parametr> a vypnout pomocí -<parametr>=0.\\n\"\n\"Parametry, které mají hodnotu, lze zadat jako -<parametr> <hodnota>.\\n\"\n\"Další možné zápisy jsou <parametr>=<hodnota>, -<parametr>=<hodnota> a\\n\"\n\"--<parametr>=<hodnota>.\\n\"\n\"Názvy parametrů nerozlišují velikost písmen. Parametry jsou:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"Volba FullScreenAllMonitors je zastaralá, místo ní nastavte FullScreenMode na „all“\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor je zastaralý, místo toho nastavte AlwaysCursor na 1 a CursorType na „Dot“\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"Cesta ~/.vnc je zastaralá. Cestu, kam přejít, naleznete popsanou v „man vncviewer“.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"Cesta %%APPDATA%%\\\\vnc je zastaralá. Prosím, cestu změňte na %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"Nebylo možné vytvořit konfigurační adresář pro VNC „%s“: %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"Nebylo možné určit datový adresář pro VNC\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"Nebylo možné vytvořit datový adresář pro VNC „%s“: %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"Nebylo možné vytvořit stavový adresář pro VNC „%s“: %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: Nerozpoznaný přepínač „%s\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"Podrobnosti získáte příkazem „%s --help“.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Nadbytečný argument „%s“\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Parametry -listen a -via se vzájemně vylučují\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Nelze začít čekat na příchozí spojení\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Poslouchá se na portu %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Chyba při čekání na příchozí spojení VNC:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Sestavení šifrovaného tunelu se nezdařilo:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"Prohlížeč vzdálené plochy\"\n\n#, c-format\n#~ msgid \"(server default %s)\"\n#~ msgstr \"(výchozí serveru %s)\"\n\n#, c-format\n#~ msgid \"SetDesktopSize failed: %d\"\n#~ msgstr \"Požadavek SetDesktopSize selhal: %d\"\n\n#~ msgid \"Invalid SetColourMapEntries from server!\"\n#~ msgstr \"Neplatná zpráva SetColourMapEntries od serveru!\"\n\n#, c-format\n#~ msgid \"Invalid configuration specified for %s\"\n#~ msgstr \"Zadáno neplatné nastavení pro %s\"\n\n#, c-format\n#~ msgid \"Invalid monitor index '%s'\"\n#~ msgstr \"Neplatné číslo monitoru „%s“\"\n\n#, c-format\n#~ msgid \"Unexpected character '%c'\"\n#~ msgstr \"Nečekaný znak „%c“\"\n\n#~ msgid \"Pass system keys directly to server (full screen)\"\n#~ msgstr \"Předávat systémové klávesy přímo serveru (režim celé obrazovky)\"\n\n#~ msgid \"Menu key\"\n#~ msgstr \"Klávesa pro vyvolání nabídky\"\n\n#~ msgid \"VNC viewer: Connection details\"\n#~ msgstr \"Prohlížeč VNC: Podrobnosti o připojení\"\n\n#, c-format\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Send %s\"\n#~ msgstr \"Poslat %s\"\n\n#~ msgid \"TigerVNC viewer\"\n#~ msgstr \"Prohlížeč TigerVNC\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"Zobrazovat puntík, když chybí kurzor\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"Aktualizace stavu diod klávesnice se nezdařila: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"Při stisku klávesy nebyl zadán žádný kód klávesy\"\n\n#, c-format\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"Žádný symbol pro kód klávesy 0x%02x (v současném stavu)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"Neznámý typ parametru\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"Prohlížeč VNC: Volby připojení\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"Ostatní\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"Nebylo možné získat název monitoru, protože rozšíření X11 RandR nebylo nalezeno\"\n\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"Získání údajů o CRTC %d selhalo\"\n\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"Získání údajů o výstupu %d pro CRTC %d selhalo\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"Obrazovka\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"Při připojení změnit velikost vzdálené relace\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"Změnit velikost vzdálené relace na velikost místního okna\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"Povolit režim celé obrazovky\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"Plná (všechny dostupné barvy)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"Střední (256 barev)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"Nízká (64 barev)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"Velmi nízká (8 barev)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"úroveň (1=rychlá, 6=nejlepší [4–6 jsou málo kdy užitečné])\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"Režim celé obrazovky\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"&Ukončit prohlížeč\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"Schovat &nabídku\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"Zápis parametru %s typu %s do registru selhal: %ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"Název parametru %s byl příliš dlouhý na přečtení z registru\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"Parametr %s byl příliš dlouhý na přečtení z registru\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"Zapsaní konfiguračního souboru selhalo, nelze získat cestu k domovskému adresáři.\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"Zapsání konfiguračního souboru selhalo, %s nelze otevřít: %s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"Přečtení konfiguračního souboru selhalo, nelze získat cestu k domovskému adresáři.\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"Neznámý parametr %s na řádku %d v souboru %s\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"Nebylo možné vytvořit domovský adresář pro VNC: nelze získat cestu k domovskému adresáři.\"\n\n# This is a proper name of an icon file\n#~ msgid \"tigervnc\"\n#~ msgstr \"tigervnc\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Zapínají se spojité aktualizace\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"vypnut\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"zapnut\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Používá se kódování %s\"\n"
  },
  {
    "path": "po/da.po",
    "content": "# Danish translation of tigervnc.\n# Copyright (C) 2018 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Joe Hansen <joedalton2@yahoo.dk>, 2015, 2016, 2017, 2018.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.8.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2018-06-13 14:22+0000\\n\"\n\"PO-Revision-Date: 2018-08-12 13:22+0200\\n\"\n\"Last-Translator: joe Hansen <joedalton2@yahoo.dk>\\n\"\n\"Language-Team: Danish <dansk@dansk-gruppen.dk>\\n\"\n\"Language: da\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 1.8.11\\n\"\n\n#: vncviewer/CConn.cxx:116\n#, c-format\nmsgid \"connected to socket %s\"\nmsgstr \"forbundet til soklen %s\"\n\n#: vncviewer/CConn.cxx:123\n#, c-format\nmsgid \"connected to host %s port %d\"\nmsgstr \"forbundet til værten %s på port %d\"\n\n#: vncviewer/CConn.cxx:184\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Skrivebordsnavn: %.80s\"\n\n#: vncviewer/CConn.cxx:189\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Vært: %.80s port: %d\"\n\n#: vncviewer/CConn.cxx:194\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Størrelse: %d x %d\"\n\n#: vncviewer/CConn.cxx:202\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Billedformat: %s\"\n\n#: vncviewer/CConn.cxx:209\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(serverstandard %s)\"\n\n#: vncviewer/CConn.cxx:214\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Anmodt kodning: %s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Sidst anvendt kodning: %s\"\n\n#: vncviewer/CConn.cxx:224\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Linjehastighedsestimat: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:229\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Protokolversion: %d.%d\"\n\n#: vncviewer/CConn.cxx:234\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Sikkerhedsmetode: %s\"\n\n#: vncviewer/CConn.cxx:358\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"SetDesktopSize fejlede: %d\"\n\n#: vncviewer/CConn.cxx:428\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"Ugyldig SetColourMapEntries fra server!\"\n\n#: vncviewer/CConn.cxx:479\nmsgid \"Enabling continuous updates\"\nmsgstr \"Aktiverer fortsættende opdateringer\"\n\n#: vncviewer/CConn.cxx:556\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Gennemløb %d kbit/s - ændrer til kvalitet %d\"\n\n#: vncviewer/CConn.cxx:578\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now %s\"\nmsgstr \"Gennemløb %d kbit/s - fuld farve er nu %s\"\n\n#: vncviewer/CConn.cxx:580\nmsgid \"disabled\"\nmsgstr \"deaktiveret\"\n\n#: vncviewer/CConn.cxx:580\nmsgid \"enabled\"\nmsgstr \"aktiveret\"\n\n#: vncviewer/CConn.cxx:590\n#, c-format\nmsgid \"Using %s encoding\"\nmsgstr \"Bruger %s-kodning\"\n\n#: vncviewer/CConn.cxx:637\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Bruger billedpunktsformat %s\"\n\n#: vncviewer/DesktopWindow.cxx:122\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Ugyldig geometri angivet!\"\n\n#: vncviewer/DesktopWindow.cxx:451\nmsgid \"Adjusting window size to avoid accidental full screen request\"\nmsgstr \"Justerer vinduesstørrelse for at undgå utilsigtet anmodning om fuld skærm\"\n\n#: vncviewer/DesktopWindow.cxx:495\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Tryk %s for at åbne kontekstmenuen\"\n\n#: vncviewer/DesktopWindow.cxx:794 vncviewer/DesktopWindow.cxx:802\n#: vncviewer/DesktopWindow.cxx:822\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Kunne ikke fange tastatur\"\n\n#: vncviewer/DesktopWindow.cxx:896\nmsgid \"Failure grabbing mouse\"\nmsgstr \"Kunne ikke fange mus\"\n\n#: vncviewer/DesktopWindow.cxx:1120\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Ugyldig skærmlayout beregnet for anmodning om ny størrelse!\"\n\n#: vncviewer/OptionsDialog.cxx:57\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"VNC-fremviser: Forbindelsesindstillinger\"\n\n#: vncviewer/OptionsDialog.cxx:83 vncviewer/ServerDialog.cxx:91\n#: vncviewer/vncviewer.cxx:282\nmsgid \"Cancel\"\nmsgstr \"Afbryd\"\n\n#: vncviewer/OptionsDialog.cxx:88 vncviewer/vncviewer.cxx:281\nmsgid \"OK\"\nmsgstr \"O.k.\"\n\n#: vncviewer/OptionsDialog.cxx:423\nmsgid \"Compression\"\nmsgstr \"Komprimering\"\n\n#: vncviewer/OptionsDialog.cxx:439\nmsgid \"Auto select\"\nmsgstr \"Vælg automatisk\"\n\n#: vncviewer/OptionsDialog.cxx:451\nmsgid \"Preferred encoding\"\nmsgstr \"Foretrukken kodning\"\n\n#: vncviewer/OptionsDialog.cxx:499\nmsgid \"Color level\"\nmsgstr \"Farveniveau\"\n\n#: vncviewer/OptionsDialog.cxx:510\nmsgid \"Full (all available colors)\"\nmsgstr \"Fuld (alle tilgængelige farver)\"\n\n#: vncviewer/OptionsDialog.cxx:517\nmsgid \"Medium (256 colors)\"\nmsgstr \"Mellem (256 farver)\"\n\n#: vncviewer/OptionsDialog.cxx:524\nmsgid \"Low (64 colors)\"\nmsgstr \"Lav (64 farver)\"\n\n#: vncviewer/OptionsDialog.cxx:531\nmsgid \"Very low (8 colors)\"\nmsgstr \"Meget lav (8 farver)\"\n\n#: vncviewer/OptionsDialog.cxx:548\nmsgid \"Custom compression level:\"\nmsgstr \"Tilpasset komprimeringsniveau:\"\n\n#: vncviewer/OptionsDialog.cxx:554\nmsgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\nmsgstr \"niveau (1=hurtig, 6=bedst [4-6 bruges sjældent])\"\n\n#: vncviewer/OptionsDialog.cxx:561\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Tillad JPEG-komprimering:\"\n\n#: vncviewer/OptionsDialog.cxx:567\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"kvalitet (0=dårlig, 9=bedst)\"\n\n#: vncviewer/OptionsDialog.cxx:578\nmsgid \"Security\"\nmsgstr \"Sikkerhed\"\n\n#: vncviewer/OptionsDialog.cxx:593\nmsgid \"Encryption\"\nmsgstr \"Kryptering\"\n\n#: vncviewer/OptionsDialog.cxx:604 vncviewer/OptionsDialog.cxx:657\n#: vncviewer/OptionsDialog.cxx:737\nmsgid \"None\"\nmsgstr \"Ingen\"\n\n#: vncviewer/OptionsDialog.cxx:610\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS med anonyme certifikater\"\n\n#: vncviewer/OptionsDialog.cxx:616\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS med X509-certifikater\"\n\n#: vncviewer/OptionsDialog.cxx:623\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Sti til X509 CA-certifikat\"\n\n#: vncviewer/OptionsDialog.cxx:630\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Sti til X509 CRL-fil\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Authentication\"\nmsgstr \"Godkendelse\"\n\n#: vncviewer/OptionsDialog.cxx:663\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Standard-VNC (usikker uden kryptering)\"\n\n#: vncviewer/OptionsDialog.cxx:669\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Bruernavn og adgangskode (usikker uden kryptering)\"\n\n#: vncviewer/OptionsDialog.cxx:688\nmsgid \"Input\"\nmsgstr \"Inddata\"\n\n#: vncviewer/OptionsDialog.cxx:696\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Vis kun (ignorer mus og tastatur)\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"Accept clipboard from server\"\nmsgstr \"Accepter udklipsholderen fra serveren\"\n\n#: vncviewer/OptionsDialog.cxx:710\nmsgid \"Also set primary selection\"\nmsgstr \"Angiv også primær markering\"\n\n#: vncviewer/OptionsDialog.cxx:717\nmsgid \"Send clipboard to server\"\nmsgstr \"Send udklipsholderen til serveren\"\n\n#: vncviewer/OptionsDialog.cxx:725\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Send primær markering som udklipsholder\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Videresend systemnøgler direkte til serveren (fuld skærm)\"\n\n#: vncviewer/OptionsDialog.cxx:735\nmsgid \"Menu key\"\nmsgstr \"Menutast\"\n\n#: vncviewer/OptionsDialog.cxx:751\nmsgid \"Screen\"\nmsgstr \"Skærm\"\n\n#: vncviewer/OptionsDialog.cxx:759\nmsgid \"Resize remote session on connect\"\nmsgstr \"Ændr størrelse for ekstern session ved forbind\"\n\n#: vncviewer/OptionsDialog.cxx:772\nmsgid \"Resize remote session to the local window\"\nmsgstr \"Ændr størrelse for ekstern session til det lokale vindue\"\n\n#: vncviewer/OptionsDialog.cxx:778\nmsgid \"Full-screen mode\"\nmsgstr \"Tilstand for fuld skærm\"\n\n#: vncviewer/OptionsDialog.cxx:784\nmsgid \"Enable full-screen mode over all monitors\"\nmsgstr \"Aktiver tilstand for fuld skærm over alle skærme\"\n\n#: vncviewer/OptionsDialog.cxx:793\nmsgid \"Misc.\"\nmsgstr \"Div.\"\n\n#: vncviewer/OptionsDialog.cxx:801\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Delt (afbryd ikke andre fremvisere)\"\n\n#: vncviewer/OptionsDialog.cxx:807\nmsgid \"Show dot when no cursor\"\nmsgstr \"Vis punktum når ingen markør\"\n\n#: vncviewer/ServerDialog.cxx:42\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"VNC-fremviser: Forbindelsesdetaljer\"\n\n#: vncviewer/ServerDialog.cxx:49 vncviewer/ServerDialog.cxx:54\nmsgid \"VNC server:\"\nmsgstr \"VNC-server:\"\n\n#: vncviewer/ServerDialog.cxx:64\nmsgid \"Options...\"\nmsgstr \"Tilvalg ...\"\n\n#: vncviewer/ServerDialog.cxx:69\nmsgid \"Load...\"\nmsgstr \"Indlæs ...\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"Save As...\"\nmsgstr \"Gem som ...\"\n\n#: vncviewer/ServerDialog.cxx:86\nmsgid \"About...\"\nmsgstr \"Om ...\"\n\n#: vncviewer/ServerDialog.cxx:96\nmsgid \"Connect\"\nmsgstr \"Forbind\"\n\n#: vncviewer/ServerDialog.cxx:137 vncviewer/ServerDialog.cxx:171\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"TigerVNC-konfiguration (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:138\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Vælg en TigerVNC-konfigurationsfil\"\n\n#: vncviewer/ServerDialog.cxx:172\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Gem TigerVNC-konfigurationen til fil\"\n\n#: vncviewer/ServerDialog.cxx:197\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s findes allerede. Ønsker du at overskrive?\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:279\nmsgid \"No\"\nmsgstr \"Nej\"\n\n#: vncviewer/ServerDialog.cxx:198\nmsgid \"Overwrite\"\nmsgstr \"Overskriv\"\n\n#: vncviewer/UserDialog.cxx:85\nmsgid \"Opening password file failed\"\nmsgstr \"Åbning af adgangskodefil mislykkedes\"\n\n#: vncviewer/UserDialog.cxx:105\nmsgid \"VNC authentication\"\nmsgstr \"VNC-godkendelse\"\n\n#: vncviewer/UserDialog.cxx:112\nmsgid \"This connection is secure\"\nmsgstr \"Denne forbindelse er sikker\"\n\n#: vncviewer/UserDialog.cxx:116\nmsgid \"This connection is not secure\"\nmsgstr \"Denne forbindelse er ikke sikker\"\n\n#: vncviewer/UserDialog.cxx:133\nmsgid \"Username:\"\nmsgstr \"Brugernavn:\"\n\n#: vncviewer/UserDialog.cxx:140\nmsgid \"Password:\"\nmsgstr \"Adgangskode:\"\n\n#: vncviewer/UserDialog.cxx:179\nmsgid \"Authentication cancelled\"\nmsgstr \"Godkendelse afbrudt\"\n\n#: vncviewer/Viewport.cxx:377\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Kunne ikke opdatere tastatur-LED-tilstand: %lu\"\n\n#: vncviewer/Viewport.cxx:383 vncviewer/Viewport.cxx:389\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"Kunne ikke opdatere tastatur-LED-tilstand: %d\"\n\n#: vncviewer/Viewport.cxx:419\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Kunne ikke opdatere tastatur-LED-tilstand\"\n\n#: vncviewer/Viewport.cxx:446 vncviewer/Viewport.cxx:454\n#: vncviewer/Viewport.cxx:471\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Kunne ikke indhente tastatur-LED-tilstand: %d\"\n\n#: vncviewer/Viewport.cxx:817\nmsgid \"No key code specified on key press\"\nmsgstr \"Ingen nøglekode angivet ved tastaturtryk\"\n\n#: vncviewer/Viewport.cxx:959\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Ingen skanningskode for udvidet virtuel nøgle 0x%02x\"\n\n#: vncviewer/Viewport.cxx:961\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Ingen skanningskode for virtuel nøgle 0x%02x\"\n\n#: vncviewer/Viewport.cxx:967\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Ugyldig skanningskode 0x%02x\"\n\n#: vncviewer/Viewport.cxx:997\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Intet symbol for udvidet virtuel nøgle 0x%02x\"\n\n#: vncviewer/Viewport.cxx:999\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Intet symbol for virtuel nøgle 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1086\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"Intet symbol for nøglekode 0x%02x (i den nuværende tilstand)\"\n\n#: vncviewer/Viewport.cxx:1119\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Intet symbol for nøglekode %d (i den nuværende tilstand)\"\n\n#: vncviewer/Viewport.cxx:1170\nmsgctxt \"ContextMenu|\"\nmsgid \"E&xit viewer\"\nmsgstr \"&Afslut fremviser\"\n\n#: vncviewer/Viewport.cxx:1173\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Fuld skærm\"\n\n#: vncviewer/Viewport.cxx:1176\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"&Minimer\"\n\n#: vncviewer/Viewport.cxx:1178\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Ændr størrelse for &vindue til session\"\n\n#: vncviewer/Viewport.cxx:1183\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:1186\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1192\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"Send %s\"\n\n#: vncviewer/Viewport.cxx:1198\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Send Ctrl-Alt-&Slet\"\n\n#: vncviewer/Viewport.cxx:1201\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&Opdater skærm\"\n\n#: vncviewer/Viewport.cxx:1204\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Indstillinger ...\"\n\n#: vncviewer/Viewport.cxx:1206\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Forbindelses&info ...\"\n\n#: vncviewer/Viewport.cxx:1208\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"Om &TigerVNC-fremviseren ...\"\n\n#: vncviewer/Viewport.cxx:1211\nmsgctxt \"ContextMenu|\"\nmsgid \"Dismiss &menu\"\nmsgstr \"Fjern &menu\"\n\n#: vncviewer/Viewport.cxx:1300\nmsgid \"VNC connection info\"\nmsgstr \"VNC-forbindelsesinfo\"\n\n#: vncviewer/parameters.cxx:279 vncviewer/parameters.cxx:313\n#, c-format\nmsgid \"The name of the parameter %s was too large to write to the registry\"\nmsgstr \"Navnet på parameteren %s var for lang til at kunne skrives til registret\"\n\n#: vncviewer/parameters.cxx:285 vncviewer/parameters.cxx:292\n#, c-format\nmsgid \"The parameter %s was too large to write to the registry\"\nmsgstr \"Parameteren %s var for lang til at kunne skrives til registret\"\n\n#: vncviewer/parameters.cxx:298 vncviewer/parameters.cxx:319\n#, c-format\nmsgid \"Failed to write parameter %s of type %s to the registry: %ld\"\nmsgstr \"Kunne ikke skrive parameteren %s af typen %s til registret: %ld\"\n\n#: vncviewer/parameters.cxx:334 vncviewer/parameters.cxx:373\n#, c-format\nmsgid \"The name of the parameter %s was too large to read from the registry\"\nmsgstr \"Navnet for parameteren %s var for lang til at kunne læses fra registret\"\n\n#: vncviewer/parameters.cxx:343 vncviewer/parameters.cxx:382\n#, c-format\nmsgid \"Failed to read parameter %s from the registry: %ld\"\nmsgstr \"Kunne ikke læse parameteren %s fra registret: %ld\"\n\n#: vncviewer/parameters.cxx:352\n#, c-format\nmsgid \"The parameter %s was too large to read from the registry\"\nmsgstr \"Parameteren %s var for lang til at kunne læses fra registret\"\n\n#: vncviewer/parameters.cxx:402\n#, c-format\nmsgid \"Failed to create registry key: %ld\"\nmsgstr \"Kunne ikke oprette registernøgle: %ld\"\n\n#: vncviewer/parameters.cxx:416 vncviewer/parameters.cxx:465\n#: vncviewer/parameters.cxx:527 vncviewer/parameters.cxx:660\n#, c-format\nmsgid \"Unknown parameter type for parameter %s\"\nmsgstr \"Ukendt parametertype for parameteren %s\"\n\n#: vncviewer/parameters.cxx:423 vncviewer/parameters.cxx:472\n#, c-format\nmsgid \"Failed to close registry key: %ld\"\nmsgstr \"Kunne ikke lukke registernøgle: %ld\"\n\n#: vncviewer/parameters.cxx:439\n#, c-format\nmsgid \"Failed to open registry key: %ld\"\nmsgstr \"Kunne ikke åbne registernøgle: %ld\"\n\n#: vncviewer/parameters.cxx:496\nmsgid \"Failed to write configuration file, can't obtain home directory path.\"\nmsgstr \"Kunne ikke skrive konfigurationsfil, kan ikke indhente hjemmemappens sti.\"\n\n#: vncviewer/parameters.cxx:509\n#, c-format\nmsgid \"Failed to write configuration file, can't open %s: %s\"\nmsgstr \"Kunne ikke skrive konfigurationsfil, kan ikke åbne %s: %s\"\n\n#: vncviewer/parameters.cxx:554\nmsgid \"Failed to read configuration file, can't obtain home directory path.\"\nmsgstr \"Kunne ikke læse konfigurationsfil, kan ikke indhente hjemmemappens sti.\"\n\n#: vncviewer/parameters.cxx:567\n#, c-format\nmsgid \"Failed to read configuration file, can't open %s: %s\"\nmsgstr \"Kunne ikke læse konfigurationsfil, kan ikke åbne %s: %s\"\n\n#: vncviewer/parameters.cxx:580 vncviewer/parameters.cxx:585\n#: vncviewer/parameters.cxx:610 vncviewer/parameters.cxx:623\n#: vncviewer/parameters.cxx:639\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"Kunne ikke læse linje %d i filen %s: %s\"\n\n#: vncviewer/parameters.cxx:586\nmsgid \"Line too long\"\nmsgstr \"Linjen er for lang\"\n\n#: vncviewer/parameters.cxx:593\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Konfigurationsfilen %s er i et ugyldigt format\"\n\n#: vncviewer/parameters.cxx:611\nmsgid \"Invalid format\"\nmsgstr \"Ugyldigt format\"\n\n#: vncviewer/parameters.cxx:624 vncviewer/parameters.cxx:640\nmsgid \"Invalid format or too large value\"\nmsgstr \"Ugyldigt format eller for stor værdi\"\n\n#: vncviewer/parameters.cxx:667\n#, c-format\nmsgid \"Unknown parameter %s on line %d in file %s\"\nmsgstr \"Ukendt parameter %s på linje %d i filen %s\"\n\n#: vncviewer/vncviewer.cxx:100\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer %d-bit v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See http://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC-fremviser %d-bit v%s\\n\"\n\"Bygget på: %s\\n\"\n\"Ophavsret 1999-%d TigerVNC-holdet og mange andre (se README.rst)\\n\"\n\"Se http://www.tigervnc.org for information om TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:127\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"Om TigerVNC-fremviseren\"\n\n#: vncviewer/vncviewer.cxx:140\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Intern FLTK-fejl. Afbryder.\"\n\n#: vncviewer/vncviewer.cxx:158 vncviewer/vncviewer.cxx:170\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Fejl ved start af ny TigerVNC-fremviser: %s\"\n\n#: vncviewer/vncviewer.cxx:179\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"Opsigelsessignalet %d er blevet modtaget. TigerVNC-fremviseren vil nu afslutte.\"\n\n#: vncviewer/vncviewer.cxx:271 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"TigerVNC-fremviser\"\n\n#: vncviewer/vncviewer.cxx:280\nmsgid \"Yes\"\nmsgstr \"Ja\"\n\n#: vncviewer/vncviewer.cxx:283\nmsgid \"Close\"\nmsgstr \"Luk\"\n\n#: vncviewer/vncviewer.cxx:288\nmsgid \"About\"\nmsgstr \"Om\"\n\n#: vncviewer/vncviewer.cxx:291\nmsgid \"Hide\"\nmsgstr \"Skjul\"\n\n#: vncviewer/vncviewer.cxx:294\nmsgid \"Quit\"\nmsgstr \"Afslut\"\n\n#: vncviewer/vncviewer.cxx:298\nmsgid \"Services\"\nmsgstr \"Tjenester\"\n\n#: vncviewer/vncviewer.cxx:299\nmsgid \"Hide Others\"\nmsgstr \"Skjul andre\"\n\n#: vncviewer/vncviewer.cxx:300\nmsgid \"Show All\"\nmsgstr \"Vis alle\"\n\n#: vncviewer/vncviewer.cxx:309\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Fil\"\n\n#: vncviewer/vncviewer.cxx:312\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Ny forbindelse\"\n\n#: vncviewer/vncviewer.cxx:324\nmsgid \"Could not create VNC home directory: can't obtain home directory path.\"\nmsgstr \"Kunne ikke oprette VNC-hjemmemappen: Kan ikke indhente hjemmemappens sti.\"\n\n#: vncviewer/vncviewer.cxx:329\n#, c-format\nmsgid \"Could not create VNC home directory: %s.\"\nmsgstr \"Kunne ikke oprette VNC-hjemmemappe: %s.\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:581 vncviewer/vncviewer.cxx:583\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Parameterne -listen og -via er ikke kompatible\"\n\n#: vncviewer/vncviewer.cxx:598\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Lytter på port %d\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"Ekstern skrivebordsviser\"\n\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Forbind til VNC-server og vis eksternt skrivebord\"\n\n#: vncviewer/vncviewer.desktop.in.in:7\nmsgid \"tigervnc\"\nmsgstr \"tigervnc\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"Ikke nok hukommelse for framebuffer\"\n"
  },
  {
    "path": "po/de.po",
    "content": "# German translation of tigervnc.\n# Copyright (C) 2014 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n#\n# Klaus Franken <Klaus.Franken@StrukturPunkt.de>, 2005.\n# Mario Blättermann <mario.blaettermann@gmail.com>, 2014-2016, 2019, 2021-2022, 2025.\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2025-11-13 19:47+0100\\n\"\n\"Last-Translator: Mario Blättermann <mario.blaettermann@gmail.com>\\n\"\n\"Language-Team: German <translation-team-de@lists.sourceforge.net>\\n\"\n\"Language: de\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Lokalize 25.08.2\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Verbunden mit Socket %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Verbunden mit Rechner %s, Port %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Verbindung zu »%s« ist fehlgeschlagen:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Desktop-Name: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Rechner: %.80s Port: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Größe: %d x %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Pixelformat: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Angeforderte Zeichenkodierung: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Zuletzt verwendete Zeichenkodierung: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Geschätzte Verbindungsgeschwindigkeit: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Protokollversion: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Sicherheitsmethode: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Die Verbindung wurde vom Server abgebrochen, bevor die Sitzung eingerichtet werden konnte.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Authentifizierung fehlgeschlagen: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Authentifizierung am Server ist fehlgeschlagen. Vom Server angegebener Grund:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Durchsatz %d kbit/s - Qualität wird auf %d geändert\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Durchsatz %d kbit/s - Vollfarbmodus ist jetzt aktiviert\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Durchsatz %d kbit/s - Vollfarbmodus ist jetzt deaktiviert\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Pixelformat %s wird verwendet\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Unzulässige Geometrie wurde angegeben!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Fenstergröße an den aktuellen Bildschirm anpassen\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"Drücken Sie %sM, um das Kontextmenü zu öffnen\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s - TigerVNC (Tastatur erkannt)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s - TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Fenstergröße anpassen, um zufällige Vollbild-Anforderung zu vermeiden\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"Drücken Sie %sEnter, um den Vollbildmodus zu verlassen\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"Fehler beim Erkennen der Tastatursteuerung\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"Drücken Sie %s, um die Tastatursteuerung von der Sitzung abzukoppeln\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Ungültige Bildschirmanordnung wurde für die Größenänderungsanforderung ermittelt!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Unzulässiger Status für 3-Tasten-Emulation\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Kein Scan-Code für erweiterte virtuelle Taste 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Kein Scan-Code für virtuelle Taste 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Ungültiger Scancode 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Kein Symbol für erweiterte virtuelle Taste 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Kein Symbol für virtuelle Taste 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Tastatur-LED-Status konnte nicht aktualisiert werden: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Kein Symbol für Tastencode %d (im aktuellen Zustand)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Tastatur-LED-Status konnte nicht ermittelt werden: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Tastatur-LED-Status konnte nicht aktualisiert werden\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Konfiguration des Systembildschirms konnte nicht ermittelt werden\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Bildschirm-Index %d existiert nicht\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"TigerVNC-Optionen\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Abbrechen\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"Kompression\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"Automatisch auswählen\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"JPEG-Kompression erlauben\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"Bevorzugte Kodierung\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"Farbstufe\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"Vollständig\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"Mittel\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"Niedrig\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"Sehr niedrig\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"Individuelle Kompressionsstufe\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"Stufe (0=schnellste, 9=beste)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"Qualitätsstufe\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"Qualität (0=schlechte, 9=beste)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"Sicherheit\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"Verschlüsselung\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"Keine\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS mit anonymen Zertifikaten\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS mit X509-Zertifikaten\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Pfad zum X509-CA-Zertifikat\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Pfad zur X509-CRL-Datei\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"Authentifizierung\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Standard-VNC (unsicher ohne Verschlüsselung)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Benutzername und Passwort (unsicher ohne Verschlüsselung)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"Eingabe\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Nur Ansicht (Maus und Tastatur ignorieren)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"Maus\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Mittlere Maustaste emulieren\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Lokalen Cursor anzeigen, wenn der Server keinen bereitstellt\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"Cursortyp\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"Dot\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"System\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"Tastatur\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"Immer alle Tastatureingaben im Vollbildmodus senden\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"Zwischenablage\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"Zwischenablage vom Server akzeptieren\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"Primäre Auswahl ebenfalls setzen\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"Zwischenablage zum Server senden\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Primäre Auswahl als Zwischenablage senden\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"Tastaturkürzel\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"Modifikatortasten für Tastaturkürzel:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Strg\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Umschalt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Strg\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Umschalt\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Option\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Befehl\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"Anzeige\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"Anzeigemodus\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"Fenster anpassen\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"Vollbild auf dem aktuellen Bildschirm\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"Vollbild auf allen Bildschirmen\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Vollbild auf ausgewählte(n) Bildschirm(en)\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"Verschiedenes\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Gemeinsamer Zugriff (andere VNC-Viewer nicht trennen)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Bei Verbindungsfehlern um erneute Verbindung nachfragen\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"Alle Tastaturkürzel sind deaktiviert.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"Drücken Sie %s, um die Tastatursteuerung von der Sitzung abzukoppeln.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"Um alle Tastatureingaben an die Sitzung weiterzureichen, drücken Sie %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"Um den Vollbildmodus ein- oder auszuschalten, drücken Sie %sEnter.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"Um das Kontextmenü der Sitzung zu öffnen, drücken Sie %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"Um eine Tastenkombination zu senden, die %s direkt in die Sitzung einschließt, drücken Sie %sLeertaste, lassen Sie die Leertaste los, halten aber %s gedrückt und drücken die gewünschte Taste.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"VNC-Server:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"Optionen …\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"Laden...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"Speichern unter …\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"Info …\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"Verbinden\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Die Server-Chronik konnte nicht geladen werden:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"TigerVNC-Konfiguration (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Eine TigerVNC-Konfigurationsdatei wählen\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Die angegebene Konfigurationsdatei konnte nicht geladen werden:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Eine TigerVNC-Konfigurationsdatei speichern\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s existiert bereits. Wollen Sie es überschreiben?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Nein\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"Überschreiben\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Die angegebene Konfigurationsdatei konnte nicht gespeichert werden:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Die Standardkonfiguration konnte nicht gespeichert werden:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Die Server-Chronik konnte nicht gespeichert werden:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"Pfad zum VNC-Statusverzeichnis konnte nicht ermittelt werden\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"»%s« konnte nicht geöffnet werden\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Zeile %d in Datei %s konnte nicht gelesen werden\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"Zeile ist zu lang\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"Öffnen der Passwortdatei fehlgeschlagen\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"VNC-Autorisierung\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"Diese Verbindung ist sicher\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"Diese Verbindung ist nicht sicher\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"Benutzername:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"Passwort:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"Passwort für Wiederverbinden merken\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Bei der Kommunikation mit dem Server trat in unerwarteter Fehler auf:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"Verbindung &trennen\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Vollbildmodus\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"M&inimieren\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"&Fenster an Sitzung anpassen\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Strg\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Strg-Alt-E&ntf senden\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&Bildschirm aktualisieren\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Optionen …\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Verbind&ungsinformationen …\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"Info &zu TigerVNC …\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"VNC-Verbindungsinformation\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Fenster ist für Touch-Bedienung anstelle von Gesten registriert\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Gesten-Konfiguration konnte nicht gesetzt werden (Fehler 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Gesten-Konfiguration konnte nicht ermittelt werden (Fehler 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Unzulässige Maustaste %d; muss eine Zahl von 1 bis 7 sein.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Nicht verarbeitbare Taste 0x%x - Tastaturereignis kann nicht erstellt werden.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Für Fenster 0x%08lx konnte die X-Input2-Ereignismaske nicht erhalten werden\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Window 0x%08lx hat keine X-Input2-Ereignismaske\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Window 0x%08lx hat mehrere X-Input2-Ereignismasken\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Fehler beim Erkennen des Geräts %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Mite einem VNC-Server verbinden und einen fernen Desktop anzeigen\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC) ist ein Anzeigesystem für ferne Rechner, dass es Ihnen ermöglicht, eine Arbeitsumgebung auf einem anderen Rechner im Netzwerk zu betrachten und damit zu interagieren. Mit VNC können Sie auf dem fernen Rechner grafische Anwendungen ausführen und lediglich die Anzeige dieser Anwendungen auf Ihr lokales Gerät holen. Dieses Paket enthält einen Client, mit dem Sie sich mit über einen laufenden VNC-Server mit anderen Arbeitsumgebungen verbinden können. VNC ist plattformunabhängig und unterstützt verschiedene Betriebssysteme und Architekturen als sowohl Server als auch Client.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC ist eine Hochgeschwindigkeitsversion von VNC, basierend auf den Codebasen von RealVNC 4 und X.org. TigerVNC begann als Weiterentwicklung von TightVNC auf Unix- und Linux-Plattformen und trennte sich Anfang 2009 von seinem Vorgängerprojekt, so dass sich TightVNC auf Windows-Plattformen konzentrieren konnte. TigerVNC unterstützt eine Variante von Tight Encoding, das durch die Verwendung des JPEG-Codecs »libjpeg-turbo« erheblich beschleunigt wird.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"TigerVNC-Verbindung zu einem CentOS-Rechner\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"TigerVNC-Verbindung zu einem macOS-Rechner\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"TigerVNC-Verbindung zu einem Windows-Rechner\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"Das TigerVNC-Team\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Der Parametername ist zu lang\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"Der Parameter ist zu groß\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"Ungültiges Format oder zu großer Wert\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"Registrierungsschlüssel konnte nicht erzeugt werden\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"Registrierungsschlüssel konnte nicht geschlossen werden\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"»%s« konnte nicht gespeichert werden: %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"»%s« konnte nicht entfernt werden: %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"Registrierungsschlüssel konnte nicht geöffnet werden\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Eintrag %d in der Server-Chronik konnte nicht gelesen werden: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Parameter »%s« konnte nicht gelesen werden: %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"Pfad zum VNC-Konfigurationsverzeichnis konnte nicht ermittelt werden\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"Parameter konnte nicht kodiert werden\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Format der Konfigurationsdatei %s ist ungültig\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"Ungültiges Format\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"Unbekannter Parameter\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Nachricht (0x%x) für ein nicht verarbeitbares Fenster erhalten\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Für die Zeigerermittlung wurde das unzulässige Fenster 0x%08lx angegeben\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Touch-Handler konnte nicht erzeugt werden: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Ereignishandler konnte nicht an Fenster angehängt werden (Fehler 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Ereignisdaten für X-Input-Ereignis konnten nicht erhalten werden\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"X-Input-Ereignis für unbekanntes Fenster\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"X-Input-Erweiterung ist nicht verfügbar.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X-Input 2 (oder neuer) ist nicht verfügbar.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X-Input 2.2 (oder neuer) ist nicht verfügbar. Touch-Gesten werden nicht unterstützt.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC Version %s\\n\"\n\"Erstellt auf: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC-Team und viele andere (siehe README.rst)\\n\"\n\"Siehe https://www.tigervnc.org für Informationen zu TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"Info zu TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Interner FLTK-Fehler. Abbruch.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Versuchen, die Verbindung erneut aufzubauen?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"Fehler beim Starten der neuen Verbindung: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"Terminierungssignal %d wurde empfangen. TigerVNC wird nun beendet.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Ja\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Schließen\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"Info\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Verbergen\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Beenden\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Dienste\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Andere verbergen\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Alle zeigen\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Datei\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Neue Verbindung\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Aufruf: %s [Parameter] [Host][:Displaynummer]\\n\"\n\"        %s [Parameter] [Host][::Port]\\n\"\n\"        %s [Parameter] [Unix-Socket]\\n\"\n\"        %s [Parameter] -listen [Port]\\n\"\n\"        %s [Parameter] [.tigervnc-Datei]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Optionen:\\n\"\n\"\\n\"\n\"  -display X-Display  - Gibt das X-Display für das Betrachterfenster an\\n\"\n\"  -geometry Geometrie - Anfängliche Position des Hauptfensters von TigerVNC.\\n\"\n\"                        In der Handbuchseite finden Sie weitere\\n\"\n\"                        Details.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Parameter können mit -<Parameter> eingeschaltet oder mit -<Parameter>=0\\n\"\n\"ausgeschaltet werden. Parameter, welche einen Wert akzeptieren, können als\\n\"\n\"-<Parameter> <Wert> angegeben werden; außerdem sind die Formen\\n\"\n\"<Parameter>=<Wert>, -<Parameter>=<Wert> oder --<Parameter>=<Wert> möglich.\\n\"\n\"Für die Parameternamen wird Groß-/Kleinschreibung nicht berücksichtigt.\\n\"\n\"Die Parameter sind:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors ist veraltet, setzen Sie stattdessen FullScreenMode auf »all«\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor ist veraltet, setzen Sie stattdessen AlwaysCursor auf 1 und CursorType auf »Dot«\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc ist veraltet, bitte rufen Sie »man vncviewer« auf, um Informationen zu den Pfaden zu erhalten, auf die Sie migrieren können.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc ist veraltet, bitte wechseln Sie zum %%APPDATA%%\\\\TigerVNC-Ort.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"VNC-Konfigurationsverzeichnis »%s« konnte nicht erstellt werden: %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"Pfad zum VNC-Datenverzeichnis konnte nicht ermittelt werden\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"VNC-Datenverzeichnis »%s« konnte nicht erstellt werden: %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"VNC-Statusverzeichnis »%s« konnte nicht erstellt werden: %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: Nicht erkannte Option »%s«\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"Siehe »%s --help« für weitere Informationen.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Zusätzliches Argument »%s«\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Die Parameter -listen und -via schließen sich gegenseitig aus\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Warten auf eingehende Verbindungen ist nicht möglich\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Am Port %d wird gelauscht\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Fehler beim Warten auf die eingehende VNC-Verbindung:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Einrichtung des verschlüsselten Tunnels ist fehlgeschlagen:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"Betrachter für ferne Bildschirme\"\n"
  },
  {
    "path": "po/el.po",
    "content": "# TigerVNC Greek (el) translation.\n# Copyright (C) 2014 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# First translator: Vangelis Skarmoutsos <skarmoutsosv@gmail.com>, 2015.\n# Vangelis Skarmoutsos <skarmoutsosv@gmail.com>, 2015, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.9.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2019-10-18 10:14+0200\\n\"\n\"PO-Revision-Date: 2021-04-23 18:00+0300\\n\"\n\"Last-Translator: Vangelis Skarmoutsos <skarmoutsosv@gmail.com>\\n\"\n\"Language-Team: Greek <team@lists.gnome.gr>\\n\"\n\"Language: el\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Generator: Poedit 2.4.2\\n\"\n\n#: vncviewer/CConn.cxx:99\n#, fuzzy, c-format\n#| msgid \"connected to host %s port %d\"\nmsgid \"Connected to socket %s\"\nmsgstr \"σε σύνδεση με ξενιστή %s θύρα %d\"\n\n#: vncviewer/CConn.cxx:106\n#, fuzzy, c-format\n#| msgid \"connected to host %s port %d\"\nmsgid \"Connected to host %s port %d\"\nmsgstr \"σε σύνδεση με ξενιστή %s θύρα %d\"\n\n#: vncviewer/CConn.cxx:157\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Όνομα επιφάνειας εργασίας: %.80s\"\n\n#: vncviewer/CConn.cxx:162\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Ξενιστής: %.80s θύρα: %d\"\n\n#: vncviewer/CConn.cxx:167\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Μέγεθος: %d x %d\"\n\n#: vncviewer/CConn.cxx:175\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Μορφοποίηση pixel: %s\"\n\n#: vncviewer/CConn.cxx:182\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(προκαθορισμένο εξυπηρετητή %s)\"\n\n#: vncviewer/CConn.cxx:187\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Αιτούμενη κωδικοποίηση: %s\"\n\n#: vncviewer/CConn.cxx:192\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Τελευταία χρησιμοποιημένη κωδικοποίηση: %s\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Τελευταία εκτίμηση ταχύτητας: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:202\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Έκδοση πρωτοκόλλου:  %d.%d\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Μέθοδος ασφάλειας: %s\"\n\n#: vncviewer/CConn.cxx:324\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"Απέτυχε το SetDesktopSize: %d\"\n\n#: vncviewer/CConn.cxx:372\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"Άκυρο SetColourMapEntries από τον εξυπηρετητή!\"\n\n#: vncviewer/CConn.cxx:480\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Διαμεταγωγή %d kbit/s - αλλαγή στην ποιότητα %d\"\n\n#: vncviewer/CConn.cxx:502\n#, fuzzy, c-format\n#| msgid \"Throughput %d kbit/s - full color is now %s\"\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Διαμεταγωγή %d kbit/s - το πλήρες χρώμα είναι τώρα %s\"\n\n#: vncviewer/CConn.cxx:505\n#, fuzzy, c-format\n#| msgid \"Throughput %d kbit/s - full color is now %s\"\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Διαμεταγωγή %d kbit/s - το πλήρες χρώμα είναι τώρα %s\"\n\n#: vncviewer/CConn.cxx:531\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Χρήση μορφής pixel %s\"\n\n#: vncviewer/DesktopWindow.cxx:122\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Καθορίστηκε άκυρη γεωμετρία!\"\n\n#: vncviewer/DesktopWindow.cxx:495\nmsgid \"Adjusting window size to avoid accidental full screen request\"\nmsgstr \"Προσαρμογή του μεγέθους παραθύρου για αποφυγή τυχαίου αιτήματος πλήρους οθόνης\"\n\n#: vncviewer/DesktopWindow.cxx:539\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Πατήστε %s για να ανοίξετε το αναδυόμενο μενού\"\n\n#: vncviewer/DesktopWindow.cxx:836 vncviewer/DesktopWindow.cxx:844\n#: vncviewer/DesktopWindow.cxx:864\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Αποτυχία σύλληψης πληκτρολογίου\"\n\n#: vncviewer/DesktopWindow.cxx:938\nmsgid \"Failure grabbing mouse\"\nmsgstr \"Αποτυχία σύλληψης ποντικιού\"\n\n#: vncviewer/DesktopWindow.cxx:1162\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Άκυρη διάταξη οθόνης υπολογισμένη από αίτημα αλλαγής μεγέθους!\"\n\n#: vncviewer/OptionsDialog.cxx:57\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"Θεατής VNC: Επιλογές σύνδεσης\"\n\n#: vncviewer/OptionsDialog.cxx:83 vncviewer/ServerDialog.cxx:91\n#: vncviewer/vncviewer.cxx:282\nmsgid \"Cancel\"\nmsgstr \"Άκυρο\"\n\n#: vncviewer/OptionsDialog.cxx:88 vncviewer/vncviewer.cxx:281\nmsgid \"OK\"\nmsgstr \"Εντάξει\"\n\n#: vncviewer/OptionsDialog.cxx:423\nmsgid \"Compression\"\nmsgstr \"Συμπίεση\"\n\n#: vncviewer/OptionsDialog.cxx:439\nmsgid \"Auto select\"\nmsgstr \"Αυτόματη επιλογή\"\n\n#: vncviewer/OptionsDialog.cxx:451\nmsgid \"Preferred encoding\"\nmsgstr \"Προτιμώμενη κωδικοποίηση\"\n\n#: vncviewer/OptionsDialog.cxx:499\n#, fuzzy\nmsgid \"Color level\"\nmsgstr \"Επίπεδο χρώματος\"\n\n# Color level. Επίπεδο χρώματος.\n#: vncviewer/OptionsDialog.cxx:510\nmsgid \"Full (all available colors)\"\nmsgstr \"Πλήρες (όλα τα διαθέσιμα χρώματα)\"\n\n# Color level. Επίπεδο χρώματος.\n#: vncviewer/OptionsDialog.cxx:517\nmsgid \"Medium (256 colors)\"\nmsgstr \"Ενδιάμεσο (256 χρώματα)\"\n\n# Color level. Επίπεδο χρώματος.\n#: vncviewer/OptionsDialog.cxx:524\nmsgid \"Low (64 colors)\"\nmsgstr \"Χαμηλό (64 χρώματα)\"\n\n# Color level. Επίπεδο χρώματος.\n#: vncviewer/OptionsDialog.cxx:531\nmsgid \"Very low (8 colors)\"\nmsgstr \"Πολύ χαμηλό (8 χρώματα)\"\n\n#: vncviewer/OptionsDialog.cxx:548\nmsgid \"Custom compression level:\"\nmsgstr \"Προσαρμοσμένο επίπεδο συμπίεσης:\"\n\n#: vncviewer/OptionsDialog.cxx:554\nmsgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\nmsgstr \"επίπεδο (1=γρήγορο, 6=καλύτερο [4-6 είναι σπάνια χρήσιμα])\"\n\n#: vncviewer/OptionsDialog.cxx:561\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Να επιτρέπεται η συμπίεση JPEG\"\n\n#: vncviewer/OptionsDialog.cxx:567\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"ποιότητα (0=φτωχή, 9=καλύτερη)\"\n\n#: vncviewer/OptionsDialog.cxx:578\nmsgid \"Security\"\nmsgstr \"Ασφάλεια\"\n\n#: vncviewer/OptionsDialog.cxx:593\nmsgid \"Encryption\"\nmsgstr \"Κρυπτογράφηση\"\n\n#: vncviewer/OptionsDialog.cxx:604 vncviewer/OptionsDialog.cxx:657\n#: vncviewer/OptionsDialog.cxx:737\nmsgid \"None\"\nmsgstr \"Κανένα\"\n\n#: vncviewer/OptionsDialog.cxx:610\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS με ανώνυμα πιστοποιητικά\"\n\n#: vncviewer/OptionsDialog.cxx:616\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS με πιστοποιητικά X509\"\n\n#: vncviewer/OptionsDialog.cxx:623\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Μονοπάτι στο πιστοποιητικό X509 CA\"\n\n#: vncviewer/OptionsDialog.cxx:630\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Μονοπάτι στο αρχείο X509 CRL\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Authentication\"\nmsgstr \"Πιστοποίηση\"\n\n#: vncviewer/OptionsDialog.cxx:663\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Τυπικό VNC (μη ασφαλές χωρίς κρυπτογράφηση)\"\n\n#: vncviewer/OptionsDialog.cxx:669\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Όνομα χρήστη και συνθηματικό\"\n\n#: vncviewer/OptionsDialog.cxx:688\nmsgid \"Input\"\nmsgstr \"Είσοδος\"\n\n#: vncviewer/OptionsDialog.cxx:696\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Μόνο προβολή (αγνόηση ποντικιού και πληκτρολογίου)\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"Accept clipboard from server\"\nmsgstr \"Αποδοχή πρόχειρου από τον εξηπηρετητή\"\n\n#: vncviewer/OptionsDialog.cxx:710\nmsgid \"Also set primary selection\"\nmsgstr \"Επίσης ορίζει την κύρια επιλογή\"\n\n#: vncviewer/OptionsDialog.cxx:717\nmsgid \"Send clipboard to server\"\nmsgstr \"Αποστολή του πρόχειρου στον εξηπηρετητή\"\n\n#: vncviewer/OptionsDialog.cxx:725\n#, fuzzy\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Αποστολή της κύριας επιλογής και αποκοπή της ενδιάμεσης μνήμης ως πρόχειρο\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Πέρασμα των πλήκτρων συστήματος κατ' ευθείαν στον εξυπηρετητή (πλήρης οθόνη)\"\n\n#: vncviewer/OptionsDialog.cxx:735\nmsgid \"Menu key\"\nmsgstr \"Πλήκτρο μενού\"\n\n#: vncviewer/OptionsDialog.cxx:751\nmsgid \"Screen\"\nmsgstr \"Οθόνη\"\n\n#: vncviewer/OptionsDialog.cxx:759\nmsgid \"Resize remote session on connect\"\nmsgstr \"Αλλαγή μεγέθους απομακρυσμένης συνεδρίας κατά την σύνδεση\"\n\n#: vncviewer/OptionsDialog.cxx:772\nmsgid \"Resize remote session to the local window\"\nmsgstr \"Αλλαγή μεγέθους απομακρυσμένης συνεδρίας στο τοπικό παράθυρο\"\n\n#: vncviewer/OptionsDialog.cxx:778\nmsgid \"Full-screen mode\"\nmsgstr \"Κατάσταση πλήρους οθόνης\"\n\n#: vncviewer/OptionsDialog.cxx:784\nmsgid \"Enable full-screen mode over all monitors\"\nmsgstr \"Ενεργοποίηση κατάστασης πλήρους-οθόνης σε όλες τις οθόνες\"\n\n#: vncviewer/OptionsDialog.cxx:793\nmsgid \"Misc.\"\nmsgstr \"Διάφορα\"\n\n#: vncviewer/OptionsDialog.cxx:801\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Κοινόχρηστο (να μην αποσυνδεθούν άλλοι θεατές)\"\n\n#: vncviewer/OptionsDialog.cxx:807\nmsgid \"Show dot when no cursor\"\nmsgstr \"Εμφάνιση κουκίδας όταν δεν υπάρχει δρομέας\"\n\n#: vncviewer/ServerDialog.cxx:42\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"Θεατής VNC: Λεπτομέρειες σύνδεσης\"\n\n#: vncviewer/ServerDialog.cxx:49 vncviewer/ServerDialog.cxx:54\nmsgid \"VNC server:\"\nmsgstr \"Εξυπηρετητής VNC:\"\n\n#: vncviewer/ServerDialog.cxx:64\nmsgid \"Options...\"\nmsgstr \"Επιλογές...\"\n\n#: vncviewer/ServerDialog.cxx:69\nmsgid \"Load...\"\nmsgstr \"Φόρτωση...\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"Save As...\"\nmsgstr \"Αποθήκευση ως...\"\n\n#: vncviewer/ServerDialog.cxx:86\nmsgid \"About...\"\nmsgstr \"Σχετικά...\"\n\n#: vncviewer/ServerDialog.cxx:96\nmsgid \"Connect\"\nmsgstr \"Σύνδεση\"\n\n#: vncviewer/ServerDialog.cxx:137 vncviewer/ServerDialog.cxx:171\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Ρυθμίσεις TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:138\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Επιλογή αρχείου ρυθμίσεων του TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:172\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Αποθήκευση ρυθμίσεων του TigerVNC σε αρχείο\"\n\n#: vncviewer/ServerDialog.cxx:197\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s ήδη υπάρχει. Θέλετε να το αντικαταστήσετε;\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:279\nmsgid \"No\"\nmsgstr \"Όχι\"\n\n#: vncviewer/ServerDialog.cxx:198\nmsgid \"Overwrite\"\nmsgstr \"Αντικατάσταση\"\n\n#: vncviewer/UserDialog.cxx:85\nmsgid \"Opening password file failed\"\nmsgstr \"Απέτυχε το άνοιγμα του αρχείου κωδικού\"\n\n#: vncviewer/UserDialog.cxx:105\nmsgid \"VNC authentication\"\nmsgstr \"Πιστοποίηση VNC\"\n\n#: vncviewer/UserDialog.cxx:112\nmsgid \"This connection is secure\"\nmsgstr \"Η σύνδεση είναι ασφαλής\"\n\n#: vncviewer/UserDialog.cxx:116\n#, fuzzy\n#| msgid \"VNC connection info\"\nmsgid \"This connection is not secure\"\nmsgstr \"Πληροφορίες σύνδεσης VNC\"\n\n#: vncviewer/UserDialog.cxx:133\nmsgid \"Username:\"\nmsgstr \"Όνομα χρήστη:\"\n\n#: vncviewer/UserDialog.cxx:146\nmsgid \"Password:\"\nmsgstr \"Συνθηματικό:\"\n\n#: vncviewer/UserDialog.cxx:185\nmsgid \"Authentication cancelled\"\nmsgstr \"Ακυρώθηκε η πιστοποίηση\"\n\n#: vncviewer/Viewport.cxx:389\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Αποτυχία ενημέρωσης κατάστασης LED πληκτρολογίου: %lu\"\n\n#: vncviewer/Viewport.cxx:395 vncviewer/Viewport.cxx:401\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"Αποτυχία ενημέρωσης κατάστασης LED πληκτρολογίου: %d\"\n\n#: vncviewer/Viewport.cxx:431\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Αποτυχία ενημέρωσης κατάστασης LED πληκτρολογίου\"\n\n#: vncviewer/Viewport.cxx:458 vncviewer/Viewport.cxx:466\n#: vncviewer/Viewport.cxx:483\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Αποτυχία λήψης κατάστασης LED πληκτρολογίου: %d\"\n\n#: vncviewer/Viewport.cxx:833\nmsgid \"No key code specified on key press\"\nmsgstr \"Δεν καθορίστηκε κώδικας πλήκτρου στο πάτημα πλήκτρου\"\n\n#: vncviewer/Viewport.cxx:982\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Χωρίς κώδικα σάρωσης για το εκτεταμένο εικονικό πλήκτρο 0x%02x\"\n\n#: vncviewer/Viewport.cxx:984\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Χωρίς κώδικα σάρωσης για το εικονικό πλήκτρο 0x%02x\"\n\n#: vncviewer/Viewport.cxx:990\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Μη έγκυρος κωδικός σάρωσης 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1020\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Χωρίς σύμβολο για το εκτεταμένο εικονικό πλήκτρο 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1022\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Χωρίς σύμβολο για το εικονικό πλήκτρο 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1115\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"Χωρίς σύμβολο για τον κώδικα πλήκτρου 0x%02x (στην τρέχουσα κατάσταση)\"\n\n#: vncviewer/Viewport.cxx:1148\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Χωρίς σύμβολο για τον κώδικα πλήκτρου %d (στην τρέχουσα κατάσταση)\"\n\n#: vncviewer/Viewport.cxx:1199\n#, fuzzy\n#| msgid \"Exit viewer\"\nmsgctxt \"ContextMenu|\"\nmsgid \"E&xit viewer\"\nmsgstr \"Έ&ξοδος από τον θεατή\"\n\n#: vncviewer/Viewport.cxx:1202\n#, fuzzy\n#| msgid \"Full screen\"\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Πλήρης οθόνη\"\n\n#: vncviewer/Viewport.cxx:1205\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Ε&λαχιστοποίηση\"\n\n#: vncviewer/Viewport.cxx:1207\n#, fuzzy\n#| msgid \"Resize window to session\"\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Αλλαγή &μεγέθους παραθύρου στην συνεδρία\"\n\n#: vncviewer/Viewport.cxx:1212\n#, fuzzy\n#| msgid \"Ctrl\"\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:1215\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1221\n#, fuzzy, c-format\n#| msgid \"Send %s\"\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"Αποστολή %s\"\n\n#: vncviewer/Viewport.cxx:1227\n#, fuzzy\n#| msgid \"Send Ctrl-Alt-Del\"\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Αποστολή Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:1230\n#, fuzzy\n#| msgid \"Refresh screen\"\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Ανανέωση &οθόνης\"\n\n#: vncviewer/Viewport.cxx:1233\n#, fuzzy\n#| msgid \"Options...\"\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Επιλογές...\"\n\n#: vncviewer/Viewport.cxx:1235\n#, fuzzy\n#| msgid \"Connection info...\"\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Πληροφορίες &σύνδεσης...\"\n\n#: vncviewer/Viewport.cxx:1237\n#, fuzzy\n#| msgid \"About TigerVNC viewer...\"\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"Σχετικά με τον θεατή &TigerVNC...\"\n\n#: vncviewer/Viewport.cxx:1240\n#, fuzzy\nmsgctxt \"ContextMenu|\"\nmsgid \"Dismiss &menu\"\nmsgstr \"&Μενού απόρριψης\"\n\n#: vncviewer/Viewport.cxx:1329\nmsgid \"VNC connection info\"\nmsgstr \"Πληροφορίες σύνδεσης VNC\"\n\n#: vncviewer/parameters.cxx:278 vncviewer/parameters.cxx:312\n#, fuzzy, c-format\n#| msgid \"The value of the parameter %s on line %d in file %s is invalid.\"\nmsgid \"The name of the parameter %s was too large to write to the registry\"\nmsgstr \"Η τιμή της παραμέτρου %s στην γραμμή %d του αρχείου %s είναι άκυρη.\"\n\n#: vncviewer/parameters.cxx:284 vncviewer/parameters.cxx:291\n#, c-format\nmsgid \"The parameter %s was too large to write to the registry\"\nmsgstr \"Η παράμετρος %s ήταν πολύ μεγάλη για να εγγραφεί στην registry\"\n\n#: vncviewer/parameters.cxx:297 vncviewer/parameters.cxx:318\n#, c-format\nmsgid \"Failed to write parameter %s of type %s to the registry: %ld\"\nmsgstr \"Αποτυχία εγγραφής παραμέτρου %s τύπου %s στην registry: %ld\"\n\n#: vncviewer/parameters.cxx:334 vncviewer/parameters.cxx:377\n#, c-format\nmsgid \"The name of the parameter %s was too large to read from the registry\"\nmsgstr \"Το όνομα της παραμέτρου %s ήταν πολύ μεγάλο για να διαβαστεί από την registry\"\n\n#: vncviewer/parameters.cxx:346 vncviewer/parameters.cxx:386\n#, c-format\nmsgid \"Failed to read parameter %s from the registry: %ld\"\nmsgstr \"Αποτυχία ανάγνωσης παραμέτρου %s από registry: %ld\"\n\n#: vncviewer/parameters.cxx:357\n#, c-format\nmsgid \"The parameter %s was too large to read from the registry\"\nmsgstr \"Η παράμετρος %s ήταν πολύ μεγάλη για να διαβαστεί από την registry\"\n\n#: vncviewer/parameters.cxx:406\n#, c-format\nmsgid \"Failed to create registry key: %ld\"\nmsgstr \"Αποτυχία δημιουργίας κλειδιού registry: %ld\"\n\n#: vncviewer/parameters.cxx:420 vncviewer/parameters.cxx:469\n#: vncviewer/parameters.cxx:532 vncviewer/parameters.cxx:666\n#, c-format\nmsgid \"Unknown parameter type for parameter %s\"\nmsgstr \"Άγνωστος τύπος παραμέτρου για την παράμετρο %s\"\n\n#: vncviewer/parameters.cxx:427 vncviewer/parameters.cxx:476\n#, c-format\nmsgid \"Failed to close registry key: %ld\"\nmsgstr \"Αποτυχία κλεισίματος του κλειδιού registry: %ld\"\n\n#: vncviewer/parameters.cxx:443\n#, c-format\nmsgid \"Failed to open registry key: %ld\"\nmsgstr \"Αποτυχία ανοίγματος του κλειδιού registry: %ld\"\n\n#: vncviewer/parameters.cxx:500\nmsgid \"Failed to write configuration file, can't obtain home directory path.\"\nmsgstr \"Αποτυχία εγγραφής του αρχείου διαμόρφωσης, δεν μπορεί να ληφθεί το μονοπάτι του αρχικού καταλόγου.\"\n\n#: vncviewer/parameters.cxx:514\n#, fuzzy, c-format\n#| msgid \"Failed to write configuration file, can't open %s\"\nmsgid \"Failed to write configuration file, can't open %s: %s\"\nmsgstr \"Αποτυχία εγγραφής τους αρχείου διαμόρφωσης, δεν μπορεί να ανοίξει το %s\"\n\n#: vncviewer/parameters.cxx:559\nmsgid \"Failed to read configuration file, can't obtain home directory path.\"\nmsgstr \"Αποτυχία ανάγνωσης αρχείου διαμόρφωσης, δεν βρέθηκε το μονοπάτι αρχικού καταλόγου.\"\n\n#: vncviewer/parameters.cxx:573\n#, fuzzy, c-format\n#| msgid \"Failed to read configuration file, can't open %s\"\nmsgid \"Failed to read configuration file, can't open %s: %s\"\nmsgstr \"Αποτυχία ανάγωνσης αρχείου διαμόρφωσης, δεν μπορεί να ανοίξει το %s\"\n\n#: vncviewer/parameters.cxx:586 vncviewer/parameters.cxx:591\n#: vncviewer/parameters.cxx:616 vncviewer/parameters.cxx:629\n#: vncviewer/parameters.cxx:645\n#, fuzzy, c-format\n#| msgid \"Failed to read line %d in file %s\"\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"Αποτυχία ανάγνωσης της γραμμής %d από το αρχείο %s\"\n\n#: vncviewer/parameters.cxx:592\nmsgid \"Line too long\"\nmsgstr \"Πολύ μεγάλη γραμμή\"\n\n#: vncviewer/parameters.cxx:599\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Το αρχείο ρυθμίσεων %s δεν έχει έγκυρη μορφή\"\n\n#: vncviewer/parameters.cxx:617\nmsgid \"Invalid format\"\nmsgstr \"Μη έγκυρη μορφή\"\n\n#: vncviewer/parameters.cxx:630 vncviewer/parameters.cxx:646\nmsgid \"Invalid format or too large value\"\nmsgstr \"Μη έγκυρη μορφή ή πολύ μεγάλη τιμή\"\n\n#: vncviewer/parameters.cxx:673\n#, fuzzy, c-format\n#| msgid \"Invalid parameter name on line: %d in file: %s\"\nmsgid \"Unknown parameter %s on line %d in file %s\"\nmsgstr \"Άκυρο όνομα παραμέτρου στην γραμμή %d στο αρχείο: %s\"\n\n#: vncviewer/vncviewer.cxx:100\n#, fuzzy, c-format\n#| msgid \"\"\n#| \"TigerVNC Viewer %d-bit v%s\\n\"\n#| \"Built on: %s\\n\"\n#| \"Copyright (C) 1999-%d TigerVNC Team and many others (see README.txt)\\n\"\n#| \"See http://www.tigervnc.org for information on TigerVNC.\"\nmsgid \"\"\n\"TigerVNC Viewer %d-bit v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"Θεατής TigerVNC %d-bit v%s\\n\"\n\"Built on: %s\\n\"\n\"Πνευματικά δικαιώματα (C) 1999-%d Ομάδα TigerVNC και πολλοί άλλοι (δείτε το README.txt)\\n\"\n\"Δείτε στο http://www.tigervnc.org για πληροφορίες σχετικά με το TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:127\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"Σχετικά με τον Θεατή TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:140\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Εσωτερικό σφάλμα του FLTK. Γίνεται έξοδος.\"\n\n#: vncviewer/vncviewer.cxx:158 vncviewer/vncviewer.cxx:170\n#, fuzzy, c-format\n#| msgid \"About TigerVNC Viewer\"\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Σχετικά με τον Θεατή TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:179\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"Λήφθηκε σήμα τερματισμού %d. Το TigerVNC θα τερματιστεί.\"\n\n#: vncviewer/vncviewer.cxx:271 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"Θεατής TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:280\nmsgid \"Yes\"\nmsgstr \"Ναι\"\n\n#: vncviewer/vncviewer.cxx:283\nmsgid \"Close\"\nmsgstr \"Κλείσιμο\"\n\n#: vncviewer/vncviewer.cxx:288\nmsgid \"About\"\nmsgstr \"Σχετικά\"\n\n#: vncviewer/vncviewer.cxx:291\nmsgid \"Hide\"\nmsgstr \"Απόκρυψη\"\n\n#: vncviewer/vncviewer.cxx:294\nmsgid \"Quit\"\nmsgstr \"Εγκατάλειψη\"\n\n#: vncviewer/vncviewer.cxx:298\nmsgid \"Services\"\nmsgstr \"Υπηρεσίες\"\n\n#: vncviewer/vncviewer.cxx:299\nmsgid \"Hide Others\"\nmsgstr \"Απόκρυψη άλλων\"\n\n#: vncviewer/vncviewer.cxx:300\nmsgid \"Show All\"\nmsgstr \"Εμφάνιση όλων\"\n\n#: vncviewer/vncviewer.cxx:309\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Αρχείο\"\n\n#: vncviewer/vncviewer.cxx:312\n#, fuzzy\n#| msgid \"VNC connection info\"\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"Πληροφορίες σύνδεσης VNC\"\n\n#: vncviewer/vncviewer.cxx:324\nmsgid \"Could not create VNC home directory: can't obtain home directory path.\"\nmsgstr \"Αδυναμία δημιουργίας αρχικού καταλόγου VNC: δεν μπορεί να ληφθεί το μονοπάτι του αρχικού καταλόγου.\"\n\n#: vncviewer/vncviewer.cxx:329\n#, c-format\nmsgid \"Could not create VNC home directory: %s.\"\nmsgstr \"Αδυναμία δημιουργίας αρχικού καταλόγου VNC: %s.\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:602 vncviewer/vncviewer.cxx:604\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Οι παράμετροι -listen και -via δεν είναι συμβατές\"\n\n#: vncviewer/vncviewer.cxx:619\n#, fuzzy, c-format\n#| msgid \"Listening on port %d\\n\"\nmsgid \"Listening on port %d\"\nmsgstr \"Ακρόαση στην θύρα %d\\n\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"Θεατής απομακρυσμένης επιφάνειας εργασίας\"\n\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Σύνδεση σε ένα εξυπηρετητή VNC και εμφάνιση του απομακρυσμένου επιφάνειας εργασίας\"\n\n#: vncviewer/vncviewer.desktop.in.in:7\nmsgid \"tigervnc\"\nmsgstr \"tigervnc\"\n\n#~ msgid \"Alt\"\n#~ msgstr \"Alt\"\n\n#~ msgid \"Bad Name/Value pair on line: %d in file: %s\"\n#~ msgstr \"Λανθασμένο ζευγάρι ονόματος/τιμής στην γραμμή: %d στο αρχείο: %s\"\n\n#, fuzzy\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"BitBlt απέτυχε\"\n\n#~ msgid \"CleanupSignalHandler called\"\n#~ msgstr \"Κλήθηκε το CleanupSignalHandler\"\n\n#, fuzzy\n#~ msgid \"Could not convert the parameter-name %s to wchar_t* when reading from the Registry, the buffersize is to small.\"\n#~ msgstr \"Δεν μπορούσε να μετατραπεί το όνομα παραμέτου %s σε wchar_t* κατά την ανάγνωση από την registry, το buffersize είναι πολύ μικρό.\"\n\n#, fuzzy\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"Αδυναμία δημιουργίας framebuffer bitmap\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"Αδυναμία δημιουργίας συσκευής framebuffer\"\n\n#~ msgid \"Could not create framebuffer image\"\n#~ msgstr \"Αδυναμία δημιουργίας εικόνας framebuffer\"\n\n#, fuzzy\n#~ msgid \"Could not read the line(%d) in the configuration file,the buffersize is to small.\"\n#~ msgstr \"Αδυναμία ανάγνωσης της γραμμής(%d) στο αρχείο διαμόρφωσης, το buffersize είναι πολύ μικρό.\"\n\n#, fuzzy\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"Αδυναμία εύρεσης κατάλληλης μορφής pixmap\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"Απέτυχε το CreateCompatibleDC\"\n\n#~ msgid \"Decoding: The size of the buffer dest is to small, it needs to be 1 byte bigger.\"\n#~ msgstr \"Αποκωδικοποίηση: Το μέγεθος του buffer είναι πολύ μικρό, χρειάζεται να είναι 1 byte μεγαλύτερο.\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"Η οθόνη στερείται τύπου pixmap για το προκαθορισμένο βάθος\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Ενεργοποίηση συνεχών ενημερώσεων\"\n\n#~ msgid \"Encoding backslash: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Κωδικοποίηση ανάποδης καθέτου: Το μέγεθος του buffer προορισμού είναι πολύ μικρό, χρειάζεται είναι περισσότερο από %d byte μεγαλύτερο.\"\n\n#~ msgid \"Encoding escape sequence: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Κωδικοποίηση ακολουθίας escape: Το μέγεθος του buffer προορισμού είναι πολύ μικρό, χρειάζεται είναι περισσότερο από %d byte μεγαλύτερο.\"\n\n#~ msgid \"Encoding normal character: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Κωδικοποίηση κανονικού χαρακτήρα: Το μέγεθος του buffer προορισμού είναι πολύ μικρό, χρειάζεται είναι περισσότερο από %d byte μεγαλύτερο.\"\n\n#~ msgid \"Error(%d) closing key:  Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Σφάλμα(%d) closing key:  Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) closing key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Σφάλμα(%d) closing key: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) creating key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Σφάλμα(%d) creating key: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) opening key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Σφάλμα(%d) opening key: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"\"\n#~ \"Line 1 in file %s\\n\"\n#~ \"must contain the TigerVNC configuration file identifier string:\\n\"\n#~ \"\\\"%s\\\"\"\n#~ msgstr \"\"\n#~ \"Η γραμμή 1 στο αρχείο %s\\n\"\n#~ \"πρέπει να περιέχει τη συμβολοσειρά αναγνώρισης αρχείου διαμόρφωσης του TigerVNC:\\n\"\n#~ \"\\\"%s\\\"\"\n\n#~ msgid \"Multiple characters given for key code %d (0x%04x): '%s'\"\n#~ msgstr \"Πολλαπλοί χαρακτήρες δόθηκαν για τον κώδικα πλήκτρου %d (0x%04x): '%s'\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"Ανεπάρκεια μνήμης για τον framebuffer\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"Υποστηρίζονται μόνο οθόνες πραγματικού χρώματος\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"Απέτυχε το SelectObject\"\n\n#~ msgid \"The parameterArray contains a object of a invalid type at line %d.\"\n#~ msgstr \"Το parameterArray περιέχει ένα αντικείμενο άκυρου τύπου στην γραμμή %d.\"\n\n#~ msgid \"Unable to create platform specific framebuffer: %s\"\n#~ msgstr \"Αδυναμία δημιουργίας framebuffer στη συγκεκριμένη πλατφόρμα: %s\"\n\n#~ msgid \"Unknown FLTK key code %d (0x%04x)\"\n#~ msgstr \"Άγνωστος FLTK κώδικας πλήκτρου %d (0x%04x)\"\n\n#~ msgid \"Unknown decimal separator: '%s'\"\n#~ msgstr \"Άγνωστο διαχωριστικό δεκαδικών: '%s'\"\n\n#~ msgid \"Unknown escape sequence at character %d\"\n#~ msgstr \"Άγνωστη ακολουθία escape στον χαρακτήρα %d\"\n\n#~ msgid \"Unknown rect encoding\"\n#~ msgstr \"Άγνωστη κωδικοποίηση rect\"\n\n#~ msgid \"Unknown rect encoding %d\"\n#~ msgstr \"Άγνωστη κωδικοποίηση rect %d\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Χρήση κωδικοποίησης %s\"\n\n#~ msgid \"Using default colormap and visual, %sdepth %d.\"\n#~ msgstr \"Χρήση προκαθορισμένου χρωματικού χάρτη και οπτικών, %sβάθος %d.\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"Χρήση ανεξάρτητης πλατφόρμας framebuffer\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"απενεργοποιημένο\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"ενεργοποιημένο\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"αδύνατη η δημιουργία τομέα DIB\"\n"
  },
  {
    "path": "po/eo.po",
    "content": "# Esperanto translation\n# Copyright (C) 2015, 2016, 2018, 2019 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Felipe Castro <fefcas@gmail.com>, 2015, 2016, 2018, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.9.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2019-10-18 10:14+0200\\n\"\n\"PO-Revision-Date: 2019-12-25 12:34-0300\\n\"\n\"Last-Translator: Felipe Castro <fefcas@gmail.com>\\n\"\n\"Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\\n\"\n\"Language: eo\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 2.2.1\\n\"\n\n#: vncviewer/CConn.cxx:99\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Konektita al konektinterfaco %s\"\n\n#: vncviewer/CConn.cxx:106\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Konektita al gastiganto %s pordo %d\"\n\n#: vncviewer/CConn.cxx:157\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Labortabla nomo: %.80s\"\n\n#: vncviewer/CConn.cxx:162\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Gastiganto: %.80s pordo: %d\"\n\n#: vncviewer/CConn.cxx:167\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Grando: %d x %d\"\n\n#: vncviewer/CConn.cxx:175\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Bildero-formo: %s\"\n\n#: vncviewer/CConn.cxx:182\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(servila implicito %s)\"\n\n#: vncviewer/CConn.cxx:187\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Petata enkodigo: %s\"\n\n#: vncviewer/CConn.cxx:192\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Lasta uzata enkodigo: %s\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Lini-rapida konjekto: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:202\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Protokola versio: %d.%d\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Sekureca metodo: %s\"\n\n#: vncviewer/CConn.cxx:324\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"SetDesktopSize fiaskis: %d\"\n\n#: vncviewer/CConn.cxx:372\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"Malvalida SetColourMapEntries el servilo!\"\n\n#: vncviewer/CConn.cxx:480\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Traigo %d kbit/s - ni ŝanĝas al kvalito %d\"\n\n#: vncviewer/CConn.cxx:502\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Traigo %d kbit/s - plenkoloro nun estas ebligita\"\n\n#: vncviewer/CConn.cxx:505\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Traigo %d kbit/s - plenkoloro nun estas malebligita\"\n\n#: vncviewer/CConn.cxx:531\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Ni uzas bilderformon %s\"\n\n#: vncviewer/DesktopWindow.cxx:122\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Malvalida geometrio indikita!\"\n\n#: vncviewer/DesktopWindow.cxx:495\nmsgid \"Adjusting window size to avoid accidental full screen request\"\nmsgstr \"Alĝustigo de fenestra grando por eviti akcidentan plenekranan peton\"\n\n#: vncviewer/DesktopWindow.cxx:539\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Premu %s por malfermi la kuntekstan menuon\"\n\n#: vncviewer/DesktopWindow.cxx:836 vncviewer/DesktopWindow.cxx:844\n#: vncviewer/DesktopWindow.cxx:864\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Fiasko dum elpreno de klavaro\"\n\n#: vncviewer/DesktopWindow.cxx:938\nmsgid \"Failure grabbing mouse\"\nmsgstr \"Fiasko dum elpreno de muso\"\n\n#: vncviewer/DesktopWindow.cxx:1162\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Malvalida ekrana aranĝo komputita por regrandiga peto!\"\n\n#: vncviewer/OptionsDialog.cxx:57\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"Rigardilo VNC: konektaj preferoj\"\n\n#: vncviewer/OptionsDialog.cxx:83 vncviewer/ServerDialog.cxx:91\n#: vncviewer/vncviewer.cxx:282\nmsgid \"Cancel\"\nmsgstr \"Nuligi\"\n\n#: vncviewer/OptionsDialog.cxx:88 vncviewer/vncviewer.cxx:281\nmsgid \"OK\"\nmsgstr \"Bone\"\n\n#: vncviewer/OptionsDialog.cxx:423\nmsgid \"Compression\"\nmsgstr \"Densigo\"\n\n#: vncviewer/OptionsDialog.cxx:439\nmsgid \"Auto select\"\nmsgstr \"Aŭtomate elekti\"\n\n#: vncviewer/OptionsDialog.cxx:451\nmsgid \"Preferred encoding\"\nmsgstr \"Preferata enkodigo\"\n\n#: vncviewer/OptionsDialog.cxx:499\nmsgid \"Color level\"\nmsgstr \"Kolora nivelo\"\n\n#: vncviewer/OptionsDialog.cxx:510\nmsgid \"Full (all available colors)\"\nmsgstr \"Kompleta (ĉiuj disponeblaj koloroj)\"\n\n#: vncviewer/OptionsDialog.cxx:517\nmsgid \"Medium (256 colors)\"\nmsgstr \"Meze (256 koloroj)\"\n\n#: vncviewer/OptionsDialog.cxx:524\nmsgid \"Low (64 colors)\"\nmsgstr \"Malalte (64 koloroj)\"\n\n#: vncviewer/OptionsDialog.cxx:531\nmsgid \"Very low (8 colors)\"\nmsgstr \"Tre malalta (8 koloroj)\"\n\n#: vncviewer/OptionsDialog.cxx:548\nmsgid \"Custom compression level:\"\nmsgstr \"Persona densig-nivelo:\"\n\n#: vncviewer/OptionsDialog.cxx:554\nmsgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\nmsgstr \"nivelo (1=rapida, 6=plejbona [4-6 rare utilas])\"\n\n#: vncviewer/OptionsDialog.cxx:561\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Permesi JPEG-densigon:\"\n\n#: vncviewer/OptionsDialog.cxx:567\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"kvalito (0=aĉa, 9=plejbona)\"\n\n#: vncviewer/OptionsDialog.cxx:578\nmsgid \"Security\"\nmsgstr \"Sekureco\"\n\n#: vncviewer/OptionsDialog.cxx:593\nmsgid \"Encryption\"\nmsgstr \"Ĉifrado\"\n\n#: vncviewer/OptionsDialog.cxx:604 vncviewer/OptionsDialog.cxx:657\n#: vncviewer/OptionsDialog.cxx:737\nmsgid \"None\"\nmsgstr \"Nenio\"\n\n#: vncviewer/OptionsDialog.cxx:610\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS kun anonimaj atestiloj\"\n\n#: vncviewer/OptionsDialog.cxx:616\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS kun atestiloj X509\"\n\n#: vncviewer/OptionsDialog.cxx:623\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Vojo al atestilo X509 CA\"\n\n#: vncviewer/OptionsDialog.cxx:630\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Vojo al dosiero X509 CRL\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Authentication\"\nmsgstr \"Aŭtentikiĝo\"\n\n#: vncviewer/OptionsDialog.cxx:663\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Ordinara VNC (nesekura sen ĉifrado)\"\n\n#: vncviewer/OptionsDialog.cxx:669\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Uzantnomo kaj pasvorto (nesekura sen ĉifrado)\"\n\n#: vncviewer/OptionsDialog.cxx:688\nmsgid \"Input\"\nmsgstr \"Enigo\"\n\n#: vncviewer/OptionsDialog.cxx:696\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Nur rigardi (preteratenti muson kaj klavaron)\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"Accept clipboard from server\"\nmsgstr \"Akcepti tondaĵon el la servilo\"\n\n#: vncviewer/OptionsDialog.cxx:710\nmsgid \"Also set primary selection\"\nmsgstr \"Difini ankaŭ la ĉefan elekton\"\n\n#: vncviewer/OptionsDialog.cxx:717\nmsgid \"Send clipboard to server\"\nmsgstr \"Sendi tondaĵon al la servilo\"\n\n#: vncviewer/OptionsDialog.cxx:725\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Sendi ĉefan elekton kiel tondajô\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Pasi sistemajn klavojn rekte al la servilo (plenekrane)\"\n\n#: vncviewer/OptionsDialog.cxx:735\nmsgid \"Menu key\"\nmsgstr \"Menu-klavo\"\n\n#: vncviewer/OptionsDialog.cxx:751\nmsgid \"Screen\"\nmsgstr \"Ekrano\"\n\n#: vncviewer/OptionsDialog.cxx:759\nmsgid \"Resize remote session on connect\"\nmsgstr \"Regrandigi foran seancon dum konekto\"\n\n#: vncviewer/OptionsDialog.cxx:772\nmsgid \"Resize remote session to the local window\"\nmsgstr \"Regrandigi foran seancon al la loka fenestro\"\n\n#: vncviewer/OptionsDialog.cxx:778\nmsgid \"Full-screen mode\"\nmsgstr \"Plenekrana reĝimo\"\n\n#: vncviewer/OptionsDialog.cxx:784\nmsgid \"Enable full-screen mode over all monitors\"\nmsgstr \"Ebligi plenekranan reĝimon en ĉiuj ekranoj\"\n\n#: vncviewer/OptionsDialog.cxx:793\nmsgid \"Misc.\"\nmsgstr \"Divers.\"\n\n#: vncviewer/OptionsDialog.cxx:801\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Kunhave (ne malkonekti aliajn rigardilojn)\"\n\n#: vncviewer/OptionsDialog.cxx:807\nmsgid \"Show dot when no cursor\"\nmsgstr \"Montri punkton kiam sen kursoro\"\n\n#: vncviewer/ServerDialog.cxx:42\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"Rigardilo VNC: konektaj detaloj\"\n\n#: vncviewer/ServerDialog.cxx:49 vncviewer/ServerDialog.cxx:54\nmsgid \"VNC server:\"\nmsgstr \"Servilo VNC:\"\n\n#: vncviewer/ServerDialog.cxx:64\nmsgid \"Options...\"\nmsgstr \"Modifiloj...\"\n\n#: vncviewer/ServerDialog.cxx:69\nmsgid \"Load...\"\nmsgstr \"Ŝargo...\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"Save As...\"\nmsgstr \"Konservi kiel...\"\n\n#: vncviewer/ServerDialog.cxx:86\nmsgid \"About...\"\nmsgstr \"Pri...\"\n\n#: vncviewer/ServerDialog.cxx:96\nmsgid \"Connect\"\nmsgstr \"Konekti\"\n\n#: vncviewer/ServerDialog.cxx:137 vncviewer/ServerDialog.cxx:171\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Agordo de TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:138\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Elekti agordo-dosieron de TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:172\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Konservi la agordo-dosieron de TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:197\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s jam ekzistas. Ĉu vi volas anstataŭigi?\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:279\nmsgid \"No\"\nmsgstr \"Ne\"\n\n#: vncviewer/ServerDialog.cxx:198\nmsgid \"Overwrite\"\nmsgstr \"Anstataŭigi\"\n\n#: vncviewer/UserDialog.cxx:85\nmsgid \"Opening password file failed\"\nmsgstr \"Malfermo de pasvorta dosiero fiaskis\"\n\n#: vncviewer/UserDialog.cxx:105\nmsgid \"VNC authentication\"\nmsgstr \"Aŭtentikiĝo de VNC\"\n\n#: vncviewer/UserDialog.cxx:112\nmsgid \"This connection is secure\"\nmsgstr \"Tiu ĉi konekto estas sekura\"\n\n#: vncviewer/UserDialog.cxx:116\nmsgid \"This connection is not secure\"\nmsgstr \"Tiu ĉi konekto ne estas sekora\"\n\n#: vncviewer/UserDialog.cxx:133\nmsgid \"Username:\"\nmsgstr \"Uzantnomo:\"\n\n#: vncviewer/UserDialog.cxx:146\nmsgid \"Password:\"\nmsgstr \"Pasvorto:\"\n\n#: vncviewer/UserDialog.cxx:185\nmsgid \"Authentication cancelled\"\nmsgstr \"Aŭtentikiĝo estas nuligita\"\n\n#: vncviewer/Viewport.cxx:389\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Fiasko dum ĝisdatigo de stato de klavaro-LED: %lu\"\n\n#: vncviewer/Viewport.cxx:395 vncviewer/Viewport.cxx:401\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"Fiasko dum ĝisdatigo de stato de klavaro-LED: %d\"\n\n#: vncviewer/Viewport.cxx:431\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Fiasko dum ĝisdatigo de stato de klavaro-LED\"\n\n#: vncviewer/Viewport.cxx:458 vncviewer/Viewport.cxx:466\n#: vncviewer/Viewport.cxx:483\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Fiasko dum kontrolo de stato de klavaro-LED: %d\"\n\n#: vncviewer/Viewport.cxx:833\nmsgid \"No key code specified on key press\"\nmsgstr \"Neniu klavkodo estis specifica por klav-aktivigo\"\n\n#: vncviewer/Viewport.cxx:982\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Neniu skankodo por kroma virtuala klavo 0x%02x\"\n\n#: vncviewer/Viewport.cxx:984\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Neniu skankodo por virtuala klavo 0x%02x\"\n\n#: vncviewer/Viewport.cxx:990\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Malvalida skankodo 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1020\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Neniu simbolo por kroma virtuala klavo 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1022\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Neniu simbolo por virtuala klavo 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1115\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"Neniu simbolo por klavkodo 0x%02x (en la nuna stato)\"\n\n#: vncviewer/Viewport.cxx:1148\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Neniu simbolo por klavkodo %d (en la nuna stato)\"\n\n#: vncviewer/Viewport.cxx:1199\nmsgctxt \"ContextMenu|\"\nmsgid \"E&xit viewer\"\nmsgstr \"E&liri la rigardilon\"\n\n#: vncviewer/Viewport.cxx:1202\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Plena ekrano\"\n\n#: vncviewer/Viewport.cxx:1205\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Mal&grandigi\"\n\n#: vncviewer/Viewport.cxx:1207\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Regrandigi &fenestron al seanco\"\n\n#: vncviewer/Viewport.cxx:1212\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Stirklavo\"\n\n#: vncviewer/Viewport.cxx:1215\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1221\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"Sendi %s\"\n\n#: vncviewer/Viewport.cxx:1227\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Sendi Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:1230\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"A&ktualigi ekranon\"\n\n#: vncviewer/Viewport.cxx:1233\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Modifiloj...\"\n\n#: vncviewer/Viewport.cxx:1235\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&Informo pri konekto...\"\n\n#: vncviewer/Viewport.cxx:1237\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"Pri la rigardilo &TigerVNC...\"\n\n#: vncviewer/Viewport.cxx:1240\nmsgctxt \"ContextMenu|\"\nmsgid \"Dismiss &menu\"\nmsgstr \"Forlasi la me&nuon\"\n\n#: vncviewer/Viewport.cxx:1329\nmsgid \"VNC connection info\"\nmsgstr \"Konekta informo de VNC\"\n\n#: vncviewer/parameters.cxx:278 vncviewer/parameters.cxx:312\n#, c-format\nmsgid \"The name of the parameter %s was too large to write to the registry\"\nmsgstr \"La nomo de la parametro %s estis tro granda por skribi al la registrujo\"\n\n#: vncviewer/parameters.cxx:284 vncviewer/parameters.cxx:291\n#, c-format\nmsgid \"The parameter %s was too large to write to the registry\"\nmsgstr \"La parametro %s estis tro granda por skribi al la registrujo\"\n\n#: vncviewer/parameters.cxx:297 vncviewer/parameters.cxx:318\n#, c-format\nmsgid \"Failed to write parameter %s of type %s to the registry: %ld\"\nmsgstr \"Fiasko dum skribo de la parametro %s el tipo %s al la registrujo: %ld\"\n\n#: vncviewer/parameters.cxx:334 vncviewer/parameters.cxx:377\n#, c-format\nmsgid \"The name of the parameter %s was too large to read from the registry\"\nmsgstr \"La nomo de la parametro %s estis tro longa por legi el la registrujo\"\n\n#: vncviewer/parameters.cxx:346 vncviewer/parameters.cxx:386\n#, c-format\nmsgid \"Failed to read parameter %s from the registry: %ld\"\nmsgstr \"Fiasko dum lego de parametro %s el la registrujo: %ld\"\n\n#: vncviewer/parameters.cxx:357\n#, c-format\nmsgid \"The parameter %s was too large to read from the registry\"\nmsgstr \"La parametro %s estis tro longa por legi el la registrujo\"\n\n#: vncviewer/parameters.cxx:406\n#, c-format\nmsgid \"Failed to create registry key: %ld\"\nmsgstr \"Fiasko dum kreo de registruja ŝlosilo: %ld\"\n\n#: vncviewer/parameters.cxx:420 vncviewer/parameters.cxx:469\n#: vncviewer/parameters.cxx:532 vncviewer/parameters.cxx:666\n#, c-format\nmsgid \"Unknown parameter type for parameter %s\"\nmsgstr \"Nekonata parametra tipo por parametro %s\"\n\n#: vncviewer/parameters.cxx:427 vncviewer/parameters.cxx:476\n#, c-format\nmsgid \"Failed to close registry key: %ld\"\nmsgstr \"Fiasko dum fermo de registruja ŝlosilo: %ld\"\n\n#: vncviewer/parameters.cxx:443\n#, c-format\nmsgid \"Failed to open registry key: %ld\"\nmsgstr \"Fiasko dum malfermo  de registruja ŝlosilo: %ld\"\n\n#: vncviewer/parameters.cxx:500\nmsgid \"Failed to write configuration file, can't obtain home directory path.\"\nmsgstr \"Fiasko dum skribo de agorda dosiero, ne eblas preni la hejman dosierujan vojon.\"\n\n#: vncviewer/parameters.cxx:514\n#, c-format\nmsgid \"Failed to write configuration file, can't open %s: %s\"\nmsgstr \"Fiasko dum skribo de la agorda dosiero, ne eblas malfermi %s: %s\"\n\n#: vncviewer/parameters.cxx:559\nmsgid \"Failed to read configuration file, can't obtain home directory path.\"\nmsgstr \"Fiasko dum lego de agorda dosiero, ne eblas preni la hejman dosierujan vojon.\"\n\n#: vncviewer/parameters.cxx:573\n#, c-format\nmsgid \"Failed to read configuration file, can't open %s: %s\"\nmsgstr \"Fiasko dum lego de agorda dosiero, ne eblas malfermi %s: %s\"\n\n#: vncviewer/parameters.cxx:586 vncviewer/parameters.cxx:591\n#: vncviewer/parameters.cxx:616 vncviewer/parameters.cxx:629\n#: vncviewer/parameters.cxx:645\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"Fiasko dum lego de linio %d en la dosiero %s: %s\"\n\n#: vncviewer/parameters.cxx:592\nmsgid \"Line too long\"\nmsgstr \"Linio tro longas\"\n\n#: vncviewer/parameters.cxx:599\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Agorda dosiero %s estas en nevalida formo\"\n\n#: vncviewer/parameters.cxx:617\nmsgid \"Invalid format\"\nmsgstr \"Nevalida formo\"\n\n#: vncviewer/parameters.cxx:630 vncviewer/parameters.cxx:646\nmsgid \"Invalid format or too large value\"\nmsgstr \"Nevalida formo aŭ tro granda valoro\"\n\n#: vncviewer/parameters.cxx:673\n#, c-format\nmsgid \"Unknown parameter %s on line %d in file %s\"\nmsgstr \"Nekonata parametro %s en linio %d en dosiero %s\"\n\n#: vncviewer/vncviewer.cxx:100\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer %d-bit v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"Rigardilo TigerVNC %d-bit v%s\\n\"\n\"Konstruita en: %s\\n\"\n\"Kopirajto (C) 1999-%d teamo de TigerVNC kaj multaj aliaj (konsultu README.rst)\\n\"\n\"Konsultu https://www.tigervnc.org por informoj pri TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:127\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"Pri la rigardilo TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:140\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Interna eraro de FLTK. Ni ĉesas.\"\n\n#: vncviewer/vncviewer.cxx:158 vncviewer/vncviewer.cxx:170\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Eraro dum ekigo de nova Rigardilo TigerVNC: %s\"\n\n#: vncviewer/vncviewer.cxx:179\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"Finiga signalo %d estis ricevata. La Rigardilo TigerVNC ĉesos nun.\"\n\n#: vncviewer/vncviewer.cxx:271 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"Rigardilo TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:280\nmsgid \"Yes\"\nmsgstr \"Jes\"\n\n#: vncviewer/vncviewer.cxx:283\nmsgid \"Close\"\nmsgstr \"Fermi\"\n\n#: vncviewer/vncviewer.cxx:288\nmsgid \"About\"\nmsgstr \"Pri\"\n\n#: vncviewer/vncviewer.cxx:291\nmsgid \"Hide\"\nmsgstr \"Kaŝi\"\n\n#: vncviewer/vncviewer.cxx:294\nmsgid \"Quit\"\nmsgstr \"Eliri\"\n\n#: vncviewer/vncviewer.cxx:298\nmsgid \"Services\"\nmsgstr \"Servoj\"\n\n#: vncviewer/vncviewer.cxx:299\nmsgid \"Hide Others\"\nmsgstr \"Kaŝi aliajn\"\n\n#: vncviewer/vncviewer.cxx:300\nmsgid \"Show All\"\nmsgstr \"Montri ĉiujn\"\n\n#: vncviewer/vncviewer.cxx:309\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Dosiero\"\n\n#: vncviewer/vncviewer.cxx:312\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Nova konekto\"\n\n#: vncviewer/vncviewer.cxx:324\nmsgid \"Could not create VNC home directory: can't obtain home directory path.\"\nmsgstr \"Ne eblis krei hejman dosierujon de VNC: ne eblas havi tiun vojon.\"\n\n#: vncviewer/vncviewer.cxx:329\n#, c-format\nmsgid \"Could not create VNC home directory: %s.\"\nmsgstr \"Ne eblis krei hejman dosierujon de VNC: %s.\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:602 vncviewer/vncviewer.cxx:604\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Parametroj -listen kaj -via estas malkongruaj\"\n\n#: vncviewer/vncviewer.cxx:619\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Ni aŭskultas pordon %d\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"Defora Labortabla Rigardilo\"\n\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Konekti al servilo VNC kaj montrigi deforan labortablon\"\n\n#: vncviewer/vncviewer.desktop.in.in:7\nmsgid \"tigervnc\"\nmsgstr \"tigervnc\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Ebligo de daŭrigaj ĝisdatigoj\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"malebligita\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"ebligita\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Ni uzas enkodigon %s\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"Ne sufiĉe da memoro por frambufro\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"Ne eblis krei frambufran aparaton\"\n\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"Ne eblis krei frambufran bitmapon\"\n\n#~ msgid \"Unable to create platform specific framebuffer: %s\"\n#~ msgstr \"Ne eblas krei frambufron specifan de platformo: %s\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"Ni uzas frambufron sendependan de platformo\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"ne eblas krei sekcion DIB\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"CreateCompatibleDC malsukcesis\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"SelectObject fiaskis\"\n\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"BitBlt malsukcesis\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"Montri la bildermapan formon \\\"lacks\\\" por apriora profundo\"\n\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"Ne eblis trovi taŭgan bildermapan formon\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"Nur verŝajn-koloraj rigardiloj estas subtenataj\"\n\n#~ msgid \"Using default colormap and visual, TrueColor, depth %d.\"\n#~ msgstr \"Ni uzas aprioran kolormapon kaj ŝajnon, 'TrueColor', profundo %d.\"\n\n#~ msgid \"Could not create framebuffer image\"\n#~ msgstr \"Ne eblis krei frambufran bildon\"\n\n#~ msgid \"Alt\"\n#~ msgstr \"Alt-klavo\"\n\n#~ msgid \"Bad Name/Value pair on line: %d in file: %s\"\n#~ msgstr \"Malĝusta paro novo/valoro en linio: %d en dosiero: %s\"\n\n#~ msgid \"CleanupSignalHandler called\"\n#~ msgstr \"CleanupSignalHandler estas vokita\"\n\n#~ msgid \"Could not convert the parameter-name %s to wchar_t* when reading from the Registry, the buffersize is to small.\"\n#~ msgstr \"Ne eblis konverti la parametro-nomo %s al wchar_t* dum lego el la Registrujo, la bufrogrando tro malgrandas.\"\n\n#~ msgid \"Could not convert the parameter-name %s to wchar_t* when writing to the Registry, the buffersize is to small.\"\n#~ msgstr \"Ne eblis konverti la parametro-nomo %s al wchar_t* dum skribo al la Registrujo, la bufrogrando tro malgrandas.\"\n\n#~ msgid \"Could not convert the parameter-value %s to wchar_t* when writing to the Registry, the buffersize is to small.\"\n#~ msgstr \"Ne eblis konverti la parametro-valoro %s al wchar_t* dum skribo al la Registrujo, la bufrogrando tro malgrandas.\"\n\n#~ msgid \"Could not convert the parameter-value for %s to utf8 char* when reading from the Registry, the buffer dest is to small.\"\n#~ msgstr \"Ne eblis konverti la parametro-valoro %s al utf8 char* dum lego el la Registrujo, la bufra celo tro malgrandas.\"\n\n#~ msgid \"Could not read the line(%d) in the configuration file,the buffersize is to small.\"\n#~ msgstr \"Ne eblis legi la linion(%d) en la agorda dosiero, la bufrogrando tro malgrandas.\"\n\n#~ msgid \"Decoding: The size of the buffer dest is to small, it needs to be 1 byte bigger.\"\n#~ msgstr \"Dekodigo: la grando de la bufra celo tro etas, ĝi bezonas esti 1 bajto pli granda.\"\n\n#~ msgid \"Encoding backslash: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Enkodigo de retroklino: la grando de la bufra celo tro etas, ĝi bezonas esti pli ol %d bajtoj pli granda.\"\n\n#~ msgid \"Encoding escape sequence: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Enkodigo de skapsekvo: la grando de la bufra celo tro etas, ĝi bezonas esti pli ol %d bajtoj pli granda.\"\n\n#~ msgid \"Encoding normal character: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Enkodigo de ordinara signo: la grando de la bufra celo tro etas, ĝi bezonas esti pli ol %d bajtoj pli granda.\"\n\n#~ msgid \"Error(%d) closing key:  Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Eraro(%d) dum fermo de ŝlosilo:  Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) closing key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Eraro(%d) dum fermo de ŝlosilo: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) creating key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Eraro(%d) dum kreo de ŝlosilo: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) opening key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Eraro(%d) dum malfermo de ŝlosilo: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) reading %s from Registry.\"\n#~ msgstr \"Eraro(%d) dum lego de %s el la Registrujo.\"\n\n#~ msgid \"Error(%d) writing %d(REG_DWORD) to Registry.\"\n#~ msgstr \"Eraro(%d) dum skribo de %d(REG_DWORD) al la Registrujo.\"\n\n#~ msgid \"Error(%d) writing %s(REG_SZ) to Registry.\"\n#~ msgstr \"Eraro(%d) dum skribo de %s(REG_SZ) al la Registrujo.\"\n\n#~ msgid \"\"\n#~ \"Line 1 in file %s\\n\"\n#~ \"must contain the TigerVNC configuration file identifier string:\\n\"\n#~ \"\\\"%s\\\"\"\n#~ msgstr \"\"\n#~ \"Linio 1 en la dosiero %s\\n\"\n#~ \"devas enhavi la agordo-dosieran identig-ĉenon de TigerVNC:\\n\"\n#~ \"\\\"%s\\\"\"\n\n#~ msgid \"Multiple characters given for key code %d (0x%04x): '%s'\"\n#~ msgstr \"Multoblaj signoj indikitaj por klavkodo %d (0x%04x): '%s'\"\n\n#~ msgid \"The parameterArray contains a object of a invalid type at line %d.\"\n#~ msgstr \"La parameterArray enhavas objekton de malvalida tipo ĉe linio %d.\"\n\n#~ msgid \"The value of the parameter %s on line %d in file %s is invalid.\"\n#~ msgstr \"La valoro de parametro %s en linio %d en dosiero %s malvalidas.\"\n\n#~ msgid \"Unknown FLTK key code %d (0x%04x)\"\n#~ msgstr \"Nekonata klavkodo de FLTK %d (0x%04x)\"\n\n#~ msgid \"Unknown decimal separator: '%s'\"\n#~ msgstr \"Nekonata dekuma apartigilo: '%s'\"\n\n#~ msgid \"Unknown escape sequence at character %d\"\n#~ msgstr \"Nekonata eskap-sekvo ĉe signo %d\"\n\n#, fuzzy\n#~ msgid \"Unknown rect encoding\"\n#~ msgstr \"Nekonata enkodigo\"\n\n#, fuzzy\n#~ msgid \"Unknown rect encoding %d\"\n#~ msgstr \"Nekonata enkodigo %d\"\n"
  },
  {
    "path": "po/es.po",
    "content": "# Spanish translation for tigervnc.\n# Copyright (C) 2018, 2022, 2023, 2024, 2025, 2026 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Francisco Javier Serrador <fserrador@gmail.com>, 2018.\n# Cristian Othón Martínez Vera <cfuga@cfuga.mx>, 2022, 2023, 2024, 2025, 2026.\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2026-01-15 13:51-0600\\n\"\n\"Last-Translator: Cristian Othón Martínez Vera <cfuga@cfuga.mx>\\n\"\n\"Language-Team: Spanish <es@tp.org.es>\\n\"\n\"Language: es\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Conectado al zócalo %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Conectado al anfitrión %s puerto %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Falló al conectar a \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Nombre del escritorio: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Anfitrión: %.80s puerto: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Tamaño: %d x %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Formato de pixel: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Codificación solicitada: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Última codificación empleada: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Velocidad de línea estimada: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Versión de protocolo: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Método de seguridad: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"La conexión fue rechazada por el servidor antes de que la sesión se pudiera establecer.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Falló la autenticación: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Falló al autenticar con el servidor. Razón dada por el servidor:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Procesamiento %d kbit/s - cambiado a calidad %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Procesamiento %d kbit/s - se activa el color total\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Procesamiento %d kbit/s - se desactiva el color total\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Utilizando formato de pixel %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"¡Se especificó una geometría inválida!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Se reduce el tamaño de ventana para ajustar al monitor actual\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"Pulse %sM para abrir el menú contextual\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s - TigerVNC (teclado capturado)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s - TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Se ajusta el tamaño de ventana para evitar peticiones accidentales de pantalla completa\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"Pulse %sRetorno para abandonar el modo de pantalla completa\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"Error al capturar el control del teclado\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"Pulse %s para liberar el control del teclado de la sesión\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"¡Disposición de pantalla computada inválida para petición de redimensionado!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Estado inválido para la emulación de 3 botones\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"No hay un código de rastreo para la tecla virtual extendida 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"No hay un código de rastreo para la tecla virtual 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Código de rastreo 0x%02x inválido\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"No hay un símbolo para la tecla virtual extendida 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"No hay un símbolo para la tecla virtual 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Falló al actualizar el estado de LED del teclado: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"No hay un símbolo para el código de tecla %d (en el estado actual)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Falló al obtener el estado de LED del teclado: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Falló al actualizar el estado de LED del teclado\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Falló al obtener la configuración del monitor del sistema\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"El índice de monitor %d no existe\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"Opciones de TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Cancelar\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"Aceptar\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"Compresión\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"Autoseleccionar\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"Permitir compresión JPEG\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"Codificación preferida\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"Nivel de color\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"Total\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"Medio\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"Bajo\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"Muy bajo\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"Nivel de compresión personal\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"calidad (0=rápido, 9=mejor)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"Nivel de calidad\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"calidad (0=peor, 9=mejor)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"Seguridad\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"Cifrado\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"Ninguno\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS con certificados anónimos\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS con certificados X509\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Ruta a AC de certificado X509\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Ruta a fichero CRL de X509\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"Autenticación\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"VNC común (inseguro sin cifrado)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Usuario y contraseña (inseguro sin cifrado)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"Entrada\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Ver solo (ignora ratón y teclado)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"Ratón\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Emula el botón medio del ratón\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Muestra el cursor local cuando el servidor no lo proporciona\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"Tipo de cursor\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"Punto\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"Sistema\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"Teclado\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"Siempre envía toda la entrada del teclado en pantalla completa\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"Portapapeles\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"Acepta texto desde el portapapeles\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"Además establece selección primaria\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"Envía portapapel al servidor\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Envía selección primaria como portapapeles\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"Atajos del teclado\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"Teclas modificadoras para los atajos del teclado:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Mayús\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Mayús\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Opción\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"Despliegue\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"Modo de despliegue\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"Ventana\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"Pantalla completa en el monitor actual\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"Pantalla completa en todos los monitores\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Pantalla completa en el(los) monitor(es) seleccionado(s)\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"Misceláneos\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Compartido (no desconecta otras visores)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Pregunta para reconectar después de errores de conexión\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"Todos los atajos del teclado están deshabilitados.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"Para liberar el control del teclado de la sesión, pulse %s.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"Para pasar toda la entrada del teclado a la sesión, pulse %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"Para intercambiar el modo de pantalla completa, pulse %sEntrar.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"Para abrir el menú de contexto de sesión, pulse %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"Para enviar una combinación de teclas que incluya %s directamente a la sesión, pulse %sEspacio, libere la barra espaciadora sin liberar %s, y pulse la tecla deseada.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"Servidor VNC:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"Opciones...\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"Cargar...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"Guardar como...\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"Acerca de...\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"Conectar\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"No se puede cargar la historia del servidor:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Configuración de TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Selecciona un fichero de configuración TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"No se puede cargar el fichero de configuración especificado:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Guarda la configuración de TigerVNC en el fichero\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s ya existe. ¿Lo quiere sobreescribir?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"No\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"Sobreescribir\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"No se puede guardar el fichero de configuración especificado:\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"No se puede guardar la configuración por defecto:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"No se puede guardar la historia del servidor:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"No se puede obtener la ruta del directorio de estado de VNC\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"No se puede abrir \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Falló al leer la línea %d en el fichero \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"Línea demasiado larga\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"Falló al abrir el fichero de contraseña\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"Autenticación VNC\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"Esta conexión es segura\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"Esta conexión no es segura\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"Usuario:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"Contraseña:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"Conserva la contraseña para reconexión\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Sucedió un error inesperado al comunicarse con el servidor:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"Des&conectar\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Pantalla completa\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Minimi&zar\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Redimensionar &ventana a sesión\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Enviar Ctrl+Alt+&Supr\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&Actualizar pantalla\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Opciones...\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&Info de conexión...\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"Acerca de &TigerVNC...\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"Info de conexión VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"La ventana está registrada para toques en lugar de gestos\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Falló al definir la configuración de gestos (error 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Falló al obtener la información de gestos (error 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Botón de ratón %d inválido, debe ser un número entre 1 y 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Tecla 0x%x sin manejar - no se puede generar un evento de teclado.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"No se puede obtener la máscara de evento X Input 2 para la ventana 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"La ventana 0x%08lx no tiene máscara de evento X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"La ventana 0x%08lx tiene más de una máscara de evento X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Error al coger el dispositivo %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Conecta al servidor VNC y muestra el escritorio remoto\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Cómputo de Red Virtual (VNC, por sus siglas en inglés) es un sistema de despliegue remoto que le permite ver e interactuar con un ambiente de escritorio virtual ejecutándose en otra computadora en la red. Al usar VNC, puede ejecutar aplicaciones gráficas en una máquina remota y enviar solamente el despliegue de esas aplicaciones a su dispositivo local. Este paquete contiene un cliente, el cual le permitirá conectarse a otros escritorios que estén ejecutando un servidor VNC. VNC es independiente de plataforma y admite varios sistemas operativos y arquitecturas como servidores así como clientes.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC es una versión de alta velocidad de VNC basada en las bases de código de RealVNC 4 y X.org. TigerVNC empezó como un esfuerzo de desarrollo de próxima generación para TightVNC en plataformas Unix y Linux, pero se separó de su proyecto padre a inicios del 2009 para que TightVNC se enfocara en plataformas Windows. TigerVNC admite una variante de la codificación Tight que tiene una gran aceleración por el uso del codificador JPEG de libjpeg-turbo.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"Conexión TigerVNC a una máquina CentOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"Conexión TigerVNC a una máquina macOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"Conexión TigerVNC a una máquina Windows\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"El equipo TigerVNC\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"El nombre del parámetro es demasiado grande\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"El parámetro es demasiado grande\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"Formato inválido o valor demansiado grande\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"Falló al crear la llave de registro\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"Falló al cerrar la llave de registro\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Falló al guardar \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Falló al borrar \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"Falló al abrir la llave de registro\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Falló al leer la entrada de histora del servidor %d: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Falló al leer el parámetro \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"No se puede obtener la ruta del directorio de configuración de VNC\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"No se puede codificar el parámetro\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"El fichero de configuración %s tiene un formato inválido\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"Formato inválido\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"Parámetro desconocido\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Se recibió el mensaje (0x%x) de una ventana sin manejar\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Se especificó la ventana 0x%08lx inválida para sujetar el puntero\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Falló al crear el manejador de toque: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"No se puede asociar el manejador de eventos a la ventana (error 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Falló al obtener datos de eventos para eventos X Input\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"Evento X Input para una ventana desconocida\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"La extensión X Input no está disponible.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2 (o más reciente) no está disponible.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2.2 (o más reciente) no está disponible. No se admitirán los gestos de toque.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC v%s\\n\"\n\"Compilado en: %s\\n\"\n\"Copyright (C) 1999-%d Equipo TigerVNC y muchos otros (vea README.rst)\\n\"\n\"Vea https://www.tigervnc.org para más información sobre TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"Acerca de TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Error interno en FLTK. Saliendo.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"¿Se intenta la reconexión?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"Error al iniciar una nueva conexión: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"Se recibió la señal de terminación %d. TigerVNC terminará ahora.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Sí\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Cerrar\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"Acerca de\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Ocultar\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Salir\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Servicios\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Ocultar otros\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Mostrar todos\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Archivo\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Nueva conexión\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Uso: %s [parámetros] [anfitrión][:Numpantalla]\\n\"\n\"     %s [parámetros] [anfitrión][::puerto]\\n\"\n\"     %s [parámetros] [zócalo unix]\\n\"\n\"     %s [parámetros] -listen [puerto]\\n\"\n\"     %s [parámetros] [fichero .tigervnc]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Opciones:\\n\"\n\"\\n\"\n\"  -display Xdisplay   - Especifica el despliegue X para la ventana del visor\\n\"\n\"  -geometry geometría - Posición inicial de la ventana principal de TigerVNC\\n\"\n\"                        Consulte la página del manual para más detalles.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Los parámetros se pueden activar con -<param> o desactivar con -<param>=0\\n\"\n\"Los parámetros que admiten un valor se pueden especificar como -<param> <valor>\\n\"\n\"Otras formas válidas son <param>=<valor> -<param>=<valor> --<param>=<valor>\\n\"\n\"Los nombres de parámetro no distinguen entre mayúsculas y minúsculas.\\n\"\n\"Los parámetros son:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors es obsoleto, en su lugar defina FullScreenMode a 'all'\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor es obsoleto, en su lugar defina AlwaysCursor a 1 y CursorType a 'Dot'\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc es obsoleto, por favor consulte 'man vncviewer' para conocer rutas de migración.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc es obsoleto, por favor cambie a la ubicación %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"No se puede crear el directorio de inicio VNC \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"No se puede crear el directorio de datos VNC\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"No se puede crear el directorio de datos VNC \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"No se puede crear el directorio de estado VNC \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: No se reconoce la opción '%s'\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"Vea '%s --help' para más información.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Argumento '%s' extra\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Los parámetros -listen y -via son incompatibles\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"No se pueden escuchar las conexiones entrantes\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Escuchando en el puerto %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Falló al esperar una conexión VNC entrante:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Falló al configurar el túnel cifrado:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"Visor de escritorio eemoto\"\n\n#, c-format\n#~ msgid \"(server default %s)\"\n#~ msgstr \"(servidor pred. %s)\"\n\n#, c-format\n#~ msgid \"SetDesktopSize failed: %d\"\n#~ msgstr \"Error en SetDesktopSize: %d\"\n\n#~ msgid \"Invalid SetColourMapEntries from server!\"\n#~ msgstr \"¡SetColourMapEntries inválida del servidor!\"\n\n#, c-format\n#~ msgid \"Invalid configuration specified for %s\"\n#~ msgstr \"Se especificó una configuración inválida para %s\"\n\n#, c-format\n#~ msgid \"Invalid monitor index '%s'\"\n#~ msgstr \"Índice de monitor '%s' inválido\"\n\n#, c-format\n#~ msgid \"Unexpected character '%c'\"\n#~ msgstr \"Carácter '%c' inesperado\"\n\n#~ msgid \"Pass system keys directly to server (full screen)\"\n#~ msgstr \"Pasa las teclas del sistema directamente al servidor (pantalla completa)\"\n\n#~ msgid \"Menu key\"\n#~ msgstr \"Tecla Menú\"\n\n#~ msgid \"VNC viewer: Connection details\"\n#~ msgstr \"Visor VNC: Datos de conexión\"\n\n#, c-format\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Send %s\"\n#~ msgstr \"Enviar %s\"\n\n#~ msgid \"TigerVNC viewer\"\n#~ msgstr \"Visor TigerVNC\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"Muestra punto cuando no hay cursor\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"Falló al actualizar el estado de LED del teclado: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"No se especificó un código de tecla al presionar la tecla\"\n\n#, c-format\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"No hay un símbolo para el código de tecla 0x%02x (en el estado actual)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"Parámetro de tipo desconocido\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"Visor VNC: Opciones de conexión\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"Misc.\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"Falló al obtener el nombre del monitor porque no se encuentra X11 RandR\"\n\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"Falló al obtener la información sobre el CRTC %d\"\n\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"Falló al obtener información acerca de la salida %d para el CRTC %d\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"Pantalla\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"Redimensiona sesión remota al conectar\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"Cambia el tamaño de la sesión remota para adaptarlo a la ventana local\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"Activar el modo de pantalla completa\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Permitir actualizaciones continuas\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"desactivado\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"activado\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Utilizando codificación %s\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"No suficiente memoria para marco de búfer\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"Completa (todos los colores disponibles)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"Medio (256 colores)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"Bajo (64 colores)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"Muy bajo (8 colores)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"nivel (1=rápido, 6=mejor [4-6 se emplea raramente])\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"Modo de pantalla completa\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"&Salir visor\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"&Menú rechazado\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"Fallado para escribir parámetro %s de tipo %s al registro: %ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"El nombre del parámetro %s fue demasiado grande para leer desde el registro\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"El parámetro %s fue demasiado grande para leer desde el registro\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"Fallaba al escribir el directorio de configuración, no se puede obtener la ruta del directorio de inicio.\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"Fallaba al escribir el fichero de configuración, no puede abrir %s: %s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"Fallaba al leer fichero de configuración, no puede obtener ruta de directorio inicial.\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"Parámetro desconocido %s en línea %d en fichero %s\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"No se ha podido crear el directorio de inicio de VNC: no se puede obtener la ruta del directorio de inicio.\"\n\n#~ msgid \"Multiple characters given for key code %d (0x%04x): '%s'\"\n#~ msgstr \"Se han dado múltiples caracteres para el código clave %d (0x%04x): '%s'\"\n\n#~ msgid \"Unknown FLTK key code %d (0x%04x)\"\n#~ msgstr \"Código clave FLTK desconocido %d (0x%04x)\"\n\n#~ msgid \"Unknown decimal separator: '%s'\"\n#~ msgstr \"Separador de decimales desconocido: '%s'\"\n\n#, fuzzy\n#~ msgid \"Unknown escape sequence at character %d\"\n#~ msgstr \"Separador de decimales desconocido: '%s'\"\n\n#, fuzzy\n#~ msgid \"\"\n#~ \"Desktop name: %.80s\\n\"\n#~ \"Host: %.80s port: %d\\n\"\n#~ \"Size: %d x %d\\n\"\n#~ \"Pixel format: %s\\n\"\n#~ \"(server default %s)\\n\"\n#~ \"Requested encoding: %s\\n\"\n#~ \"Last used encoding: %s\\n\"\n#~ \"Line speed estimate: %d kbit/s\\n\"\n#~ \"Protocol version: %d.%d\\n\"\n#~ \"Security method: %s\\n\"\n#~ msgstr \"\"\n#~ \"Nombre del escritorio: %.80s\\n\"\n#~ \"Tamaño: %d x %d\\n\"\n#~ \"Formato en píxeles: %s\\n\"\n#~ \"(por defecto del servidor %s)\\n\"\n#~ \"Codificación solicitada: %s\\n\"\n#~ \"Última codificación utilizada: %s\\n\"\n#~ \"Velocidad de línea estimada: %d kbit/s\\n\"\n"
  },
  {
    "path": "po/fi.po",
    "content": "# Finnish messages for tigervnc.\n# Copyright © 2019 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Jorma Karvonen <karvonen.jorma@gmail.com>, 2015.\n# Lauri Nurmi <lanurmi@iki.fi>, 2019, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.14.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-01-14 16:15+0100\\n\"\n\"PO-Revision-Date: 2025-01-22 23:21+0200\\n\"\n\"Last-Translator: Lauri Nurmi <lanurmi@iki.fi>\\n\"\n\"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\\n\"\n\"Language: fi\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.5\\n\"\n\n#: vncviewer/CConn.cxx:102\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Yhdistetty sokettiin %s\"\n\n#: vncviewer/CConn.cxx:109\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Yhdistetty koneeseen %s porttiin %d\"\n\n#: vncviewer/CConn.cxx:114\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Yhteyden muodostaminen epäonnistui kohteeseen ”%s”:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:151\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Työpöydän nimi: %.80s\"\n\n#: vncviewer/CConn.cxx:154\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Kone: %.80s portti: %d\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Koko: %d × %d\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Pikselimuoto: %s\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(palvelimen oletus %s)\"\n\n#: vncviewer/CConn.cxx:173\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Pyydetty koodaus: %s\"\n\n#: vncviewer/CConn.cxx:177\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Viimeksi käytetty koodaus: %s\"\n\n#: vncviewer/CConn.cxx:181\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Rivinopeusarvio: %d kilobittiä/s\"\n\n#: vncviewer/CConn.cxx:185\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Yhteyskäytäntöversio: %d.%d\"\n\n#: vncviewer/CConn.cxx:189\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Turvamenetelmä: %s\"\n\n#: vncviewer/CConn.cxx:250 vncviewer/CConn.cxx:252\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Palvelin pudotti yhteyden ennen kuin istuntoa voitiin muodostaa.\"\n\n#: vncviewer/CConn.cxx:262\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Todennus epäonnistui: %s\"\n\n#: vncviewer/CConn.cxx:263\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Todennus palvelimelle epäonnistui. Palvelimen ilmoittama syy:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:335\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"SetDesktopSize epäonnistui: %d\"\n\n#: vncviewer/CConn.cxx:408\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"Virheellisiä SetColourMapEntries-tietueita palvelimelta!\"\n\n#: vncviewer/CConn.cxx:516\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Läpisyöttö %d kilobittiä/s - vaihdetaan laaduksi %d\"\n\n#: vncviewer/CConn.cxx:538\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Läpisyöttö %d kilobittiä/s - täysvärit ovat nyt käytössä\"\n\n#: vncviewer/CConn.cxx:541\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Läpisyöttö %d kilobittiä/s - täysvärit ovat nyt pois käytöstä\"\n\n#: vncviewer/CConn.cxx:567\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Käytetään pikselimuotoa %s\"\n\n#: vncviewer/DesktopWindow.cxx:146\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Virheellinen geometria määritelty!\"\n\n#: vncviewer/DesktopWindow.cxx:167\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Pienennetään ikkunan kokoa nykyiseen näyttöön sovittamiseksi\"\n\n#: vncviewer/DesktopWindow.cxx:646\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Säädetään ikkunakokoa tahattomien kokonäyttöpyyntöjen välttämiseksi\"\n\n#: vncviewer/DesktopWindow.cxx:694\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"%s avaa ponnahdusvalikon\"\n\n#: vncviewer/DesktopWindow.cxx:1094 vncviewer/DesktopWindow.cxx:1102\n#: vncviewer/DesktopWindow.cxx:1122\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Häiriö näppäimistöön tarttumisessa\"\n\n#: vncviewer/DesktopWindow.cxx:1411\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Virheellinen näyttöasettelu laskettu koonmuuttamispyynnölle!\"\n\n#: vncviewer/EmulateMB.cxx:226 vncviewer/EmulateMB.cxx:289\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Virheellinen tila kolmen painikkeen jäljittelylle\"\n\n#: vncviewer/KeyboardWin32.cxx:242\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Ei toimintakoodia laajennetulle virtuaalinäppäimelle 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:244\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Ei toimintakoodia virtuaalinäppäimelle 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Virheellinen toimintakoodi 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:262\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Laajennetulle virtuaalinäppäimelle 0x%02x ei ole symbolia\"\n\n#: vncviewer/KeyboardWin32.cxx:264\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Virtuaalinäppäimelle 0x%02x ei ole symbolia\"\n\n#: vncviewer/KeyboardWin32.cxx:423\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Näppäimistön LED-tilan päivittäminen epäonnistui: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:104\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Näppäinkoodille %d ei ole symbolia (nykyisessä tilassa)\"\n\n#: vncviewer/KeyboardX11.cxx:129\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Näppäimistön LED-tilan noutaminen epäonnistui: %d\"\n\n#: vncviewer/KeyboardX11.cxx:174\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Näppäimistön LED-tilan päivittäminen epäonnistui\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:52\n#: vncviewer/MonitorIndicesParameter.cxx:100\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Järjestelmän näyttökokoonpanon selvittäminen epäonnistui\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:79\n#, c-format\nmsgid \"Invalid configuration specified for %s\"\nmsgstr \"%s:lle määritetty virheellinen arvo\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:86\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Näyttöä numero %d ei ole olemassa\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:162\n#: vncviewer/MonitorIndicesParameter.cxx:182\n#, c-format\nmsgid \"Invalid monitor index '%s'\"\nmsgstr \"Virheellinen näytön numero ”%s”\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:170\n#, c-format\nmsgid \"Unexpected character '%c'\"\nmsgstr \"Odottamaton merkki ”%c”\"\n\n#: vncviewer/OptionsDialog.cxx:64\nmsgid \"TigerVNC options\"\nmsgstr \"TigerVNC-asetukset\"\n\n#: vncviewer/OptionsDialog.cxx:97 vncviewer/ServerDialog.cxx:107\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Peru\"\n\n#: vncviewer/OptionsDialog.cxx:102 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"Valmis\"\n\n#: vncviewer/OptionsDialog.cxx:514\nmsgid \"Compression\"\nmsgstr \"Tiivistys\"\n\n#: vncviewer/OptionsDialog.cxx:530\nmsgid \"Auto select\"\nmsgstr \"Automaattivalinta\"\n\n#: vncviewer/OptionsDialog.cxx:541\nmsgid \"Preferred encoding\"\nmsgstr \"Ensisijainen koodaus\"\n\n#: vncviewer/OptionsDialog.cxx:602\nmsgid \"Color level\"\nmsgstr \"Väritaso\"\n\n#: vncviewer/OptionsDialog.cxx:614\nmsgid \"Full\"\nmsgstr \"Täysi\"\n\n#: vncviewer/OptionsDialog.cxx:621\nmsgid \"Medium\"\nmsgstr \"Keskilaatu\"\n\n#: vncviewer/OptionsDialog.cxx:628\nmsgid \"Low\"\nmsgstr \"Matala\"\n\n#: vncviewer/OptionsDialog.cxx:635\nmsgid \"Very low\"\nmsgstr \"Hyvin matala\"\n\n#: vncviewer/OptionsDialog.cxx:657\nmsgid \"Custom compression level:\"\nmsgstr \"Oma tiivistystaso:\"\n\n#: vncviewer/OptionsDialog.cxx:664\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"laatu (0=nopea, 9=paras)\"\n\n#: vncviewer/OptionsDialog.cxx:671\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Salli JPEG-tiivistys:\"\n\n#: vncviewer/OptionsDialog.cxx:678\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"laatu (0=heikko, 9=paras)\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Security\"\nmsgstr \"Turvallisuus\"\n\n#: vncviewer/OptionsDialog.cxx:703\nmsgid \"Encryption\"\nmsgstr \"Salaus\"\n\n#: vncviewer/OptionsDialog.cxx:715 vncviewer/OptionsDialog.cxx:782\n#: vncviewer/OptionsDialog.cxx:905\nmsgid \"None\"\nmsgstr \"Ei mitään\"\n\n#: vncviewer/OptionsDialog.cxx:722\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS anonyymeilla varmenteilla\"\n\n#: vncviewer/OptionsDialog.cxx:728\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS X509-varmenteilla\"\n\n#: vncviewer/OptionsDialog.cxx:735\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Polku X509 CA-varmenteeseen\"\n\n#: vncviewer/OptionsDialog.cxx:742\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Polku X509 CRL-tiedostoon\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Authentication\"\nmsgstr \"Todennus\"\n\n#: vncviewer/OptionsDialog.cxx:788\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Standardi-VNC (turvaton salauksetta)\"\n\n#: vncviewer/OptionsDialog.cxx:794\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Käyttäjätunnus ja salasana (turvaton salauksetta)\"\n\n#: vncviewer/OptionsDialog.cxx:822\nmsgid \"Input\"\nmsgstr \"Syöte\"\n\n#: vncviewer/OptionsDialog.cxx:835\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Vain katselu (hiirtä ja näppäimistöä ei huomioida)\"\n\n#: vncviewer/OptionsDialog.cxx:842\nmsgid \"Mouse\"\nmsgstr \"Hiiri\"\n\n#: vncviewer/OptionsDialog.cxx:854\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Jäljittele hiiren keskipainiketta\"\n\n#: vncviewer/OptionsDialog.cxx:860\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Näytä paikallinen kohdistin, kun palvelin ei tarjoa kohdistinta\"\n\n#: vncviewer/OptionsDialog.cxx:865\nmsgid \"Cursor type\"\nmsgstr \"Kohdistimen tyyppi\"\n\n#: vncviewer/OptionsDialog.cxx:867\nmsgid \"Dot\"\nmsgstr \"Piste\"\n\n#: vncviewer/OptionsDialog.cxx:868\nmsgid \"System\"\nmsgstr \"Järjestelmä\"\n\n#: vncviewer/OptionsDialog.cxx:888\nmsgid \"Keyboard\"\nmsgstr \"Näppäimistö\"\n\n#: vncviewer/OptionsDialog.cxx:900\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Välitä järjestelmänäppäimet suoraan palvelimelle (kokonäyttö)\"\n\n#: vncviewer/OptionsDialog.cxx:903\nmsgid \"Menu key\"\nmsgstr \"Valikkonäppäin\"\n\n#: vncviewer/OptionsDialog.cxx:926\nmsgid \"Clipboard\"\nmsgstr \"Leikepöytä\"\n\n#: vncviewer/OptionsDialog.cxx:938\nmsgid \"Accept clipboard from server\"\nmsgstr \"Hyväksy leikepöytä palvelimelta\"\n\n#: vncviewer/OptionsDialog.cxx:946\nmsgid \"Also set primary selection\"\nmsgstr \"Aseta myös ensisijainen valinta\"\n\n#: vncviewer/OptionsDialog.cxx:953\nmsgid \"Send clipboard to server\"\nmsgstr \"Lähetä leikepöytä palvelimelle\"\n\n#: vncviewer/OptionsDialog.cxx:961\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Lähetä ensisijainen valinta leikepöytänä\"\n\n#: vncviewer/OptionsDialog.cxx:982\nmsgid \"Display\"\nmsgstr \"Näyttö\"\n\n#: vncviewer/OptionsDialog.cxx:996\nmsgid \"Display mode\"\nmsgstr \"Näyttötila\"\n\n#: vncviewer/OptionsDialog.cxx:1009\nmsgid \"Windowed\"\nmsgstr \"Ikkunoitu\"\n\n#: vncviewer/OptionsDialog.cxx:1017\nmsgid \"Full screen on current monitor\"\nmsgstr \"Kokonäyttö nykyisellä näytöllä\"\n\n#: vncviewer/OptionsDialog.cxx:1025\nmsgid \"Full screen on all monitors\"\nmsgstr \"Kokonäyttö kaikilla näytöillä\"\n\n#: vncviewer/OptionsDialog.cxx:1033\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Kokonäyttö valituilla näytöillä\"\n\n#: vncviewer/OptionsDialog.cxx:1062\nmsgid \"Miscellaneous\"\nmsgstr \"Sekalaiset\"\n\n#: vncviewer/OptionsDialog.cxx:1070\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Jaettu (älä katkaise muiden katselimien yhteyksiä)\"\n\n#: vncviewer/OptionsDialog.cxx:1076\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Pyydä uudelleenyhdistämään yhteysvirheen sattuessa\"\n\n#: vncviewer/ServerDialog.cxx:63\nmsgid \"VNC viewer: Connection details\"\nmsgstr \"VNC-katselin: Yhteyden yksityiskohdat\"\n\n#: vncviewer/ServerDialog.cxx:73\nmsgid \"VNC server:\"\nmsgstr \"VNC-palvelin:\"\n\n#: vncviewer/ServerDialog.cxx:80\nmsgid \"Options...\"\nmsgstr \"Valinnat...\"\n\n#: vncviewer/ServerDialog.cxx:84\nmsgid \"Load...\"\nmsgstr \"Lataa...\"\n\n# Nappi ei skaalaudu tekstin leveyden mukaan.\n#: vncviewer/ServerDialog.cxx:88\nmsgid \"Save as...\"\nmsgstr \"Tall. nimellä...\"\n\n#: vncviewer/ServerDialog.cxx:102\nmsgid \"About...\"\nmsgstr \"Tietoja...\"\n\n#: vncviewer/ServerDialog.cxx:111\nmsgid \"Connect\"\nmsgstr \"Yhdistä\"\n\n#: vncviewer/ServerDialog.cxx:147\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Palvelinhistoriaa ei voi ladata:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:176 vncviewer/ServerDialog.cxx:216\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"TigerVNC-asetukset (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:177\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Valitse TigerVNC-asetustiedosto\"\n\n#: vncviewer/ServerDialog.cxx:199 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Annetun asetustiedoston lataaminen ei onnistu:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:217\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Tallenna TigerVNC-asetukset tiedostoon\"\n\n#: vncviewer/ServerDialog.cxx:243\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s on jo olemassa. Haluatko korvata sen?\"\n\n#: vncviewer/ServerDialog.cxx:244 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Ei\"\n\n#: vncviewer/ServerDialog.cxx:244\nmsgid \"Overwrite\"\nmsgstr \"Korvaa\"\n\n#: vncviewer/ServerDialog.cxx:260\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Annetun asetustiedoston tallentaminen ei onnistu:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:294\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Oletusasetuksia ei voi tallentaa:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:306\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Palvelinhistoriaa ei voi tallentaa:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:429\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"VNC-tilahakemiston polkua ei saatu selvitettyä\"\n\n#: vncviewer/ServerDialog.cxx:363 vncviewer/ServerDialog.cxx:437\n#: vncviewer/parameters.cxx:671 vncviewer/parameters.cxx:752\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"Tiedoston ”%s” avaaminen epäonnistui\"\n\n#: vncviewer/ServerDialog.cxx:378 vncviewer/ServerDialog.cxx:387\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:773\n#: vncviewer/parameters.cxx:807 vncviewer/parameters.cxx:837\n#: vncviewer/parameters.cxx:844\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Rivin %d lukeminen tiedostosta ”%s” epäonnistui\"\n\n#: vncviewer/ServerDialog.cxx:390 vncviewer/parameters.cxx:776\nmsgid \"Line too long\"\nmsgstr \"Liian pitkä rivi\"\n\n#: vncviewer/UserDialog.cxx:123\nmsgid \"Opening password file failed\"\nmsgstr \"Salasanatiedoston avaaminen epäonnistui\"\n\n#: vncviewer/UserDialog.cxx:143\nmsgid \"VNC authentication\"\nmsgstr \"VNC-todennus\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"This connection is secure\"\nmsgstr \"Tämä yhteys on turvallinen\"\n\n#: vncviewer/UserDialog.cxx:154\nmsgid \"This connection is not secure\"\nmsgstr \"Tämä yhteys ei ole turvallinen\"\n\n#: vncviewer/UserDialog.cxx:176\nmsgid \"Username:\"\nmsgstr \"Käyttäjätunnus:\"\n\n#: vncviewer/UserDialog.cxx:189\nmsgid \"Password:\"\nmsgstr \"Salasana:\"\n\n#: vncviewer/UserDialog.cxx:197\nmsgid \"Keep password for reconnect\"\nmsgstr \"Säilytä salasana yhteyden uudelleenmuodostamiseen\"\n\n#: vncviewer/Viewport.cxx:695\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"Ka&tkaise yhteys\"\n\n#: vncviewer/Viewport.cxx:698\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Kokonäyttö\"\n\n#: vncviewer/Viewport.cxx:701\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Pi&enennä\"\n\n#: vncviewer/Viewport.cxx:703\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"&Sovita ikkunan koko istuntoon\"\n\n#: vncviewer/Viewport.cxx:708\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:711\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:717\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"Lähetä %s\"\n\n#: vncviewer/Viewport.cxx:724\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Lähetä Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:727\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Vi&rkistä näyttö\"\n\n#: vncviewer/Viewport.cxx:730\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Valinnat...\"\n\n#: vncviewer/Viewport.cxx:732\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Yh&teyden tiedot...\"\n\n#: vncviewer/Viewport.cxx:734\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"Tietoa &TigerVNC:stä...\"\n\n#: vncviewer/Viewport.cxx:830\nmsgid \"VNC connection info\"\nmsgstr \"VNC-yhteyden tiedot\"\n\n#: vncviewer/Win32TouchHandler.cxx:48\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Ikkuna on rekisteröity kosketuksille eikä eleille\"\n\n#: vncviewer/Win32TouchHandler.cxx:83\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Eleasetusten asettaminen epäonnistui (virhe 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:95\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Eletietojen saaminen epäonnistui (virhe 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:360\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Virheellinen hiiren painike %d, ei ole välillä 1 – 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:425\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Käsittelemätön näppäin 0x%x - ei voi luoda näppäimistötapahtumaa.\"\n\n#: vncviewer/XInputTouchHandler.cxx:102 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"X Input 2 -tapahtumapeitettä ei saada ikkunalle 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:104\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Ikkunalla 0x%08lx ei ole X Input 2 -tapahtumapeitettä\"\n\n#: vncviewer/XInputTouchHandler.cxx:112 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Ikkunalla 0x%08lx on useampi X Input 2 -tapahtumapeite\"\n\n#: vncviewer/XInputTouchHandler.cxx:143\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Häiriö laitteeseen %i tarttumisessa\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\nmsgid \"TigerVNC Viewer\"\nmsgstr \"TigerVNC-katselin\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Yhdistä VNC-palvelimeen ja näytä etätyöpöytä\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC) on etänäyttöjärjestelmä, jonka avulla voi katsella ja ohjata toisessa verkon koneessa toimivaa virtuaalista työpöytäympäristöä. VNC:n avulla voi suorittaa graafisia sovelluksia etäkoneella ja lähettää näistä sovelluksista vain näytön paikalliseen laitteeseen. Tämä paketti sisältää asiakasohjelman, jolla voi muodostaa yhteyden muihin työpöytiin, joilla on VNC-palvelin. VNC on alustariippumaton ja tukee erilaisia käyttöjärjestelmiä ja arkkitehtuureja sekä palvelimina että asiakasohjelmina.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC on RealVNC 4- ja X.org koodikantoihin perustuva nopea versio VNC:stä. TigerVNC aloitettiin uuteen sukupolveen tähtäävänä TightVNC:n kehitystyönä Unix- ja Linux-alustoilla, mutta se erosi emoprojektistaan vuoden 2009 alussa, jotta TightVNC voisi keskittyä Windows-alustoihin. TigerVNC tukee Tight-koodauksen muunnosta, jota libjpeg-turbo-JPEG-koodekin käyttö nopeuttaa huomattavasti.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC viewer connection to a CentOS machine\"\nmsgstr \"TigerVNC-katselimen yhteys CentOS-koneeseen\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC viewer connection to a macOS machine\"\nmsgstr \"TigerVNC-katselimen yhteys macOS-koneeseen\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC viewer connection to a Windows machine\"\nmsgstr \"TigerVNC-katselimen yhteys Windows-koneeseen\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"TigerVNC-ryhmä\"\n\n#: vncviewer/parameters.cxx:319 vncviewer/parameters.cxx:344\n#: vncviewer/parameters.cxx:361 vncviewer/parameters.cxx:401\n#: vncviewer/parameters.cxx:421\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Parametrin nimi on liian suuri\"\n\n#: vncviewer/parameters.cxx:323 vncviewer/parameters.cxx:328\n#: vncviewer/parameters.cxx:379\nmsgid \"The parameter is too large\"\nmsgstr \"Parametri on liian suuri\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:712\n#: vncviewer/parameters.cxx:822\nmsgid \"Invalid format or too large value\"\nmsgstr \"Virheellinen muoto tai liian suuri arvo\"\n\n#: vncviewer/parameters.cxx:440 vncviewer/parameters.cxx:473\nmsgid \"Failed to create registry key\"\nmsgstr \"Rekisteriavaimen luominen epäonnistui\"\n\n#: vncviewer/parameters.cxx:461 vncviewer/parameters.cxx:528\n#: vncviewer/parameters.cxx:571 vncviewer/parameters.cxx:638\nmsgid \"Failed to close registry key\"\nmsgstr \"Rekisteriavaimen sulkeminen epäonnistui\"\n\n#: vncviewer/parameters.cxx:479 vncviewer/parameters.cxx:506\n#: vncviewer/parameters.cxx:680 vncviewer/parameters.cxx:692\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Tiedoston ”%s” tallentaminen epäonnistui: %s\"\n\n#: vncviewer/parameters.cxx:489 vncviewer/parameters.cxx:520\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Tiedoston ”%s” poistaminen epäonnistui: %s\"\n\n#: vncviewer/parameters.cxx:544 vncviewer/parameters.cxx:616\nmsgid \"Failed to open registry key\"\nmsgstr \"Rekisteriavaimen avaaminen epäonnistui\"\n\n#: vncviewer/parameters.cxx:561\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Palvelinhistorian merkinnän %d lukeminen epäonnistui: %s\"\n\n#: vncviewer/parameters.cxx:597 vncviewer/parameters.cxx:627\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Parametrin ”%s” lukeminen epäonnistui: %s\"\n\n#: vncviewer/parameters.cxx:661 vncviewer/parameters.cxx:740\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"VNC-setushakemiston polkua ei saatu selvitettyä\"\n\n#: vncviewer/parameters.cxx:682 vncviewer/parameters.cxx:694\nmsgid \"Could not encode parameter\"\nmsgstr \"Parametria ei voitu koodata\"\n\n#: vncviewer/parameters.cxx:785\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Asetustiedosto %s on virheellisessä muodossa\"\n\n#: vncviewer/parameters.cxx:809\nmsgid \"Invalid format\"\nmsgstr \"Virheellinen muoto\"\n\n#: vncviewer/parameters.cxx:846\nmsgid \"Unknown parameter\"\nmsgstr \"Tuntematon parametri\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Saatiin viesti (0x%x) käsittelemättömälle ikkunalle\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Virheellinen ikkuna 0x%08lx annettu osoittimeen tarttumiselle\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Kosketuskäsittelimen luominen epäonnistui: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Tapahtumakäsittelintä ei voitu liittää ikkunaan (virhe 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"X Input -tapahtuman tapahtumatietodon noutaminen epäonnistui\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"X Input -tapahtuma tuntemattomalle ikkunalle\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"X Input -laajennos ei ole saatavilla.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2 (tai uudempi) ei ole saatavilla.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2.2 (tai uudempi) ei ole saatavilla. Kosketuseleitä ei tueta.\"\n\n#: vncviewer/vncviewer.cxx:104\n#, c-format\nmsgid \"\"\n\"TigerVNC viewer v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC-katselin v%s\\n\"\n\"Koontihetki: %s\\n\"\n\"Copyright © 1999-%d TigerVNC-ryhmä ja monet muut (ks. README.rst)\\n\"\n\"Lisätietoja TigerVNC:stä osoitteessa https://www.tigervnc.org.\"\n\n#: vncviewer/vncviewer.cxx:158\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Odottamaton virhe muodostettaessa yhteyttä palvelimeen:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:174\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"Tietoa &TigerVNC:stä\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Sisäinen FLTK-virhe. Poistutaan.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Yritetäänkö uudelleenyhdistämistä?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Virhe käynnistettäessä uutta TigerVNC-katselinta: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC viewer will now exit.\"\nmsgstr \"Päättämissignaali %d on vastaanotettu. TigerVNC-katselin sulkeutuu.\"\n\n#: vncviewer/vncviewer.cxx:391 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC viewer\"\nmsgstr \"TigerVNC-katselin\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Kyllä\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Sulje\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"Tietoja\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Piilota\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Poistu\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Palvelut\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Piilota muut\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Näytä kaikki\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Tiedosto\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Uusi yhteys\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Usage: %s [parametrit] [kone][:näytönNro]\\n\"\n\"       %s [parametrit] [kone][::port]\\n\"\n\"       %s [parametrit] [unix-soketti]\\n\"\n\"       %s [parametrit] -listen [portti]\\n\"\n\"       %s [parametrit] [.tigervnc-tiedosto]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main VNC viewer window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Asetukset:\\n\"\n\"\\n\"\n\"-display Xnäyttö      - Määrittää katselinikkunan X-näytön\\n\"\n\"  -geometry geometria - VNC-katselinohjelman pääikkunan alkusijainti. Katso\\n\"\n\"                        man-sivulta lisätietoja.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Parametrit asetetaan päälle: -<param> tai pois päältä: -<param>=0\\n\"\n\"Arvon saavat parametrit annetaan: -<param> <arvo>\\n\"\n\"Muita kelvollisia muotoja: <param>=<arvo> -<param>=<arvo> --<param>=<arvo>\\n\"\n\"Kirjainkoolla ei ole merkitystä parametrien nimissä. Parametrit ovat:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors on vanhentunut, aseta FullScreenMode-asetukseksi ”all” sen sijaan\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor on vanhentunut, aseta sen sijaan AlwaysCursor-arvoksi 1 ja CursorType-valinnaksi ”Piste”\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc on vanhentunut, katso ”man vncviewer” sisältää lisätietoa korvaavista poluista.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc on vanhentunut, vaihda sijainniksi %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"VNC-asetushakemiston ”%s” luominen epäonnistui: %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"VNC-tietohakemiston polun selvitys epäonnistui\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"VNC-tietohakemiston ”%s” luominen epäonnistui: %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"VNC-tilahakemiston ”%s” luominen epäonnistui: %s\"\n\n#: vncviewer/vncviewer.cxx:703\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: Tuntematon valitsin ”%s”\\n\"\n\n#: vncviewer/vncviewer.cxx:705 vncviewer/vncviewer.cxx:713\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"Lisätietoja komennolla ”%s --help”.\\n\"\n\n#: vncviewer/vncviewer.cxx:712\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Ylimääräinen argumentti ”%s”\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:748 vncviewer/vncviewer.cxx:749\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Parametrit -listen ja -via ovat yhteensopimattomia\"\n\n#: vncviewer/vncviewer.cxx:763\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Saapuvia yhteyksiä ei voi kuunnella\"\n\n#: vncviewer/vncviewer.cxx:765\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Kuunnellaan portissa %d\"\n\n#: vncviewer/vncviewer.cxx:794\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Virhe odotettaessa saapuvaa VNC-yhteyttä:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:815\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Virhe salatun tunnelin muodostamisessa:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote desktop viewer\"\nmsgstr \"Etätyöpöytäkatselin\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"Näytä piste kohdistimen puuttuessa\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"Näppäimistön LED-tilan päivittäminen epäonnistui: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"Näppäimenpainalluksella ei tuotettu näppäinkoodia\"\n\n#, c-format\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"Näppäinkoodille 0x%02x ei ole symbolia (nykyisessä tilassa)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"Tuntematon parametrityyppi\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"VNC-katselin: Yhteysvalinnat\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"Sekalaiset\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"Näytön nimen noutaminen epäonnistui, koska X11:n RandR:ää ei löytynyt\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"Näyttö\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"Sovita etäistunnon koko yhdistettäessä\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"Sovita etäistunto paikalliseen ikkunaan\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"Ota käyttöön kokonäyttötila\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"Täysi (kaikki saatavilla olevat värit)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"Keskilaatuinen (256 väriä)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"Alhainen (64 väriä)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"Hyvin alhainen (8 väriä)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"taso (1=nopea, 6=paras [4-6 ovat harvoin hyödyllisiä])\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"Kokonäyttötila\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"P&oistu katselimesta\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"Sul&je valikko\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"Parametrin %s (tyyppiä %s) kirjoittaminen rekisteriin epäonnistui: %ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"Parametrin %s nimi oli liian suuri luettavaksi rekisteristä\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"Parametri %s oli liian suuri luettavaksi rekisteristä\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"Asetustiedoston kirjoittaminen epäonnistui, kotihakemiston polun selvittäminen epäonnistui.\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"Asetustiedoston kirjoittaminen epäonnistui, tiedostn %s avaaminen epäonnistui: %s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"Asetustiedoston lukeminen epäonnistui, kotihakemiston polun selvittäminen epäonnistui.\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"Tuntematon parametri %s rivillä %d tiedostossa %s\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"VNC-kotihakemiston luominen epäonnistui: kotihakemiston polun selvittäminen epäonnistui.\"\n\n#~ msgid \"tigervnc\"\n#~ msgstr \"tigervnc\"\n\n#~ msgid \"Unknown encoding %d\"\n#~ msgstr \"Tuntematon koodaus %d\"\n\n#~ msgid \"Unknown encoding\"\n#~ msgstr \"Tuntematon koodaus\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Otetaan käyttöön jatkuvat päivitykset\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"poistettu käytöstä\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"otettu käyttöön\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Käytetään %s-koodausta\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"Muisti ei riitä framebufferille\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"Framebuffer-laitteen luominen epäonnistui\"\n\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"Framebuffer-bittikartan luominen epäonnistui\"\n\n#~ msgid \"Unable to create platform specific framebuffer: %s\"\n#~ msgstr \"Alustakohtaisen framebuffer-puskurin luominen epäonnistui: %s\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"Käytetään alustariippumatonta framebuffer-puskuria\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"lohkon DIB luominen epäonnistui\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"CreateCompatibleDC epäonnistui\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"SelectObject epäonnistui\"\n\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"BitBlt epäonnistui\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"Näytöltä puuttuu pikselikarttamuoto oletussyvyydelle\"\n\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"Sopivan pikselikarttamuodon löytäminen epäonnistui\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"Tuetaan vain true color-näyttöjä\"\n\n#~ msgid \"Using default colormap and visual, TrueColor, depth %d.\"\n#~ msgstr \"Käytetään oletusvärikarttaa ja visuaalisuutta, TrueColor, syvyys %d.\"\n\n#~ msgid \"Alt\"\n#~ msgstr \"Alt\"\n\n#~ msgid \"Bad Name/Value pair on line: %d in file: %s\"\n#~ msgstr \"Väärä nimi/arvo-pari rivillä: %d tiedostossa: %s\"\n\n#~ msgid \"CleanupSignalHandler called\"\n#~ msgstr \"CleanupSignalHandler kutsuttu\"\n\n#~ msgid \"Could not convert the parameter-name %s to wchar_t* when reading from the Registry, the buffersize is to small.\"\n#~ msgstr \"Parametrinimen %s muuntaminen wchar_t*-tyypiksi epäonnistui kun luetaan Windows-rekisteristä, puskurikoko on liian pieni.\"\n\n#~ msgid \"Could not convert the parameter-name %s to wchar_t* when writing to the Registry, the buffersize is to small.\"\n#~ msgstr \"Parametrinimen %s muuntaminen wchar_t*-tyypiksi epäonnistui kun kirjoitetaan Windows-rekisteriin, puskurikoko on liian pieni.\"\n\n#~ msgid \"Could not convert the parameter-value %s to wchar_t* when writing to the Registry, the buffersize is to small.\"\n#~ msgstr \"Parametriarvon %s muuntaminen wchar_t*-tyypiksi epäonnistui kun kirjoitetaan Windows-rekisteriin, puskurikoko on liian pieni.\"\n\n#~ msgid \"Could not convert the parameter-value for %s to utf8 char* when reading from the Registry, the buffer dest is to small.\"\n#~ msgstr \"Parametriarvon %s muuntaminen utf8 char*-tyypiksi epäonnistui kun luetaan Windows-rekisteristä, puskurikohde on liian pieni.\"\n\n#~ msgid \"Could not read the line(%d) in the configuration file,the buffersize is to small.\"\n#~ msgstr \"Rivin(%d) lukeminen asetustiedostosta epäonnistui, puskurikoko on liian pieni. \"\n\n#~ msgid \"Decoding: The size of the buffer dest is to small, it needs to be 1 byte bigger.\"\n#~ msgstr \"Koodauksen purku: Puskurikohteen koko on liian pieni, sen on oltava yhden tavun suurempi.\"\n\n#~ msgid \"Encoding backslash: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Koodataan kenoviiva: Puskurikohteen koko on liian pieni, sen on oltava yli %d tavua suurempi.\"\n\n#~ msgid \"Encoding escape sequence: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Koodinvaihtosekvenssin koodaus: Puskurikohteen koko on liian pieni, sen on oltava yli %d tavua suurempi.\"\n\n#~ msgid \"Encoding normal character: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Normaalin merkin koodaus: Puskurikohteen koko on liian pieni, sen on oltava yli %d tavua suurempi.\"\n\n#~ msgid \"Error(%d) closing key:  Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Virhe(%d) suljettaessa avainta:  Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) closing key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Virhe(%d) suljettaessa avainta: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) creating key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Virhe(%d) luotaessa avainta: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) opening key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Virhe(%d) avattaessa avainta: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) reading %s from Registry.\"\n#~ msgstr \"Virhe(%d) luettaessa %s Windows-rekisteristä.\"\n\n#~ msgid \"Error(%d) writing %d(REG_DWORD) to Registry.\"\n#~ msgstr \"Virhe(%d) kirjoitettaessa %d(REG_DWORD) Windows-rekisteriin.\"\n\n#~ msgid \"Error(%d) writing %s(REG_SZ) to Registry.\"\n#~ msgstr \"Virhe(%d) kirjoitettaessa %s(REG_SZ) Windows-rekisteriin.\"\n\n#~ msgid \"\"\n#~ \"Line 1 in file %s\\n\"\n#~ \"must contain the TigerVNC configuration file identifier string:\\n\"\n#~ \"\\\"%s\\\"\"\n#~ msgstr \"\"\n#~ \"Riviin 1 tiedostossa %s\\n\"\n#~ \"on sisällyttävä TigerVNC-asetustiedostotunnistemerkkijono:\\n\"\n#~ \"”%s”\"\n\n#~ msgid \"Multiple characters given for key code %d (0x%04x): '%s'\"\n#~ msgstr \"Avainkoodille %d (0x%04x) on annettu useita merkkejä: ’%s’\"\n\n#~ msgid \"The parameterArray contains a object of a invalid type at line %d.\"\n#~ msgstr \"Komponentti parameterArray sisältää rivillä %d tyypiltään virheellisen objektin.\"\n\n#~ msgid \"The value of the parameter %s on line %d in file %s is invalid.\"\n#~ msgstr \"Parametrin %s arvo rivillä %d tiedostossa %s on virheellinen.\"\n\n#~ msgid \"Unknown FLTK key code %d (0x%04x)\"\n#~ msgstr \"Tuntematon FLTK-avainkoodi %d (0x%04x)\"\n\n#~ msgid \"Unknown decimal separator: '%s'\"\n#~ msgstr \"Tuntematon desimaalierotin: ’%s’\"\n\n#~ msgid \"Unknown escape sequence at character %d\"\n#~ msgstr \"Tuntematon koodinvaihtosekvensssi merkissä %d\"\n\n#~ msgid \"Using default colormap and visual, %sdepth %d.\"\n#~ msgstr \"Käytetään oletusvärikarttaa ja visuaalisuutta, %s-syvyys %d.\"\n\n#~ msgid \"Could not convert the parameter-name %s to wchar_t* when reading from the Registry, the buffersize is too small.\"\n#~ msgstr \"Parametrinimen %s muuntaminen wchar_t*-tyypiksi epäonnistui kun luetaan Registrystä, puskurikoko on liian pieni.\"\n\n#~ msgid \"Could not convert the parameter-name %s to wchar_t* when writing to the Registry, the buffersize is too small.\"\n#~ msgstr \"Parametrinimen %s muuntaminen wchar_t*-tyypiksi epäonnistui kun kirjoitetaan Registryyn, puskurikoko on liian pieni.\"\n\n#~ msgid \"Could not convert the parameter-value %s to wchar_t* when writing to the Registry, the buffersize is too small.\"\n#~ msgstr \"Parametriarvon %s muuntaminen wchar_t*-tyypiksi epäonnistui kun kirjoitetaan Registryyn, puskurikoko on liian pieni.\"\n\n#~ msgid \"Could not convert the parameter-value for %s to utf8 char* when reading from the Registry, the buffer dest is too small.\"\n#~ msgstr \"Parametriarvon %s muuntaminen utf8 char*-tyypiksi epäonnistui kun luetaan Registrystä, puskurikohde on liian pieni.\"\n\n#~ msgid \"Decoding: The size of the buffer dest is too small, it needs to be 1 byte bigger.\"\n#~ msgstr \"Koodauksen purku: Puskurikohteen koko on liian pieni, sen on oltava yhden merkin suurempi.\"\n\n#~ msgid \"Encoding backslash: The size of the buffer dest is too small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Koodataan kenoviiva: Puskurikohteen koko on liian pieni, sen on oltava yli %d merkkiä suurempi.\"\n\n#~ msgid \"Encoding escape sequence: The size of the buffer dest is too small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Koodinvaihtosekvenssin koodaus: Puskurikohteen koko on liian pieni, sen on oltava yli %d merkkiä suurempi.\"\n\n#~ msgid \"Encoding normal character: The size of the buffer dest is too small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Normaalin merkin koodaus: Puskurikohteen koko on liian pieni, sen on oltava yli %d merkkiä suurempi.\"\n\n#~ msgid \"Could not read the line(%d) in the configuration file,the buffersize is too small.\"\n#~ msgstr \"Rivin(%d) lukeminen asetustiedostossa epäonnistui, puskurikoko on liian pieni. \"\n"
  },
  {
    "path": "po/fr.po",
    "content": "# French translation for tigervnc.\n# Copyright (C) 2011 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n#\n# Alain Portal <alain.portal@free.fr>, 2010\n# Stéphane Aulery <lkppo@free.fr>, 2015-2016, 2019-2021.\n#\n# Traduction complète et relecture, S. Aulery, 25-04-2015.\n# Mise à jour, S. Aulery, 23-12-2016, 29-04-2017.\n# Mise à jour, S. Aulery, 12-05-2019.\n# Mise à jour, S. Aulery, 06-05-2020.\n# Mise à jour, S. Aulery, 17-11-2021.\n# Mise à jour, S. Aulery, 15-18-2023.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.12.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2022-12-15 16:35+0100\\n\"\n\"PO-Revision-Date: 2023-08-15 12:33+0200\\n\"\n\"Last-Translator: Stéphane Aulery <lkppo@free.fr>\\n\"\n\"Language-Team: French <traduc@traduc.org>\\n\"\n\"Language: fr\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Lokalize 1.0\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\n#: vncviewer/CConn.cxx:103\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Connecté au socket %s\"\n\n#: vncviewer/CConn.cxx:110\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Connecté à l’hôte %s par le port %d\"\n\n#: vncviewer/CConn.cxx:114\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impossible de se connecter à \\\"%s\\\" :\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:159\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Nom du bureau : %.80s\"\n\n#: vncviewer/CConn.cxx:164\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Hôte : %.80s port : %d\"\n\n#: vncviewer/CConn.cxx:169\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Taille : %d x %d\"\n\n#: vncviewer/CConn.cxx:177\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Format de pixel : %s\"\n\n#: vncviewer/CConn.cxx:184\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(serveur par défaut %s)\"\n\n#: vncviewer/CConn.cxx:189\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Encodage demandé : %s\"\n\n#: vncviewer/CConn.cxx:194\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Dernier encodage utilisé : %s\"\n\n#: vncviewer/CConn.cxx:199\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Vitesse estimée de la connexion : %d kbit/s\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Version du protocol : %d.%d\"\n\n#: vncviewer/CConn.cxx:209\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Méthode de sécurité : %s\"\n\n#: vncviewer/CConn.cxx:270 vncviewer/CConn.cxx:272\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"La connexion à été fermée par le serveur avant la la fin de l'ouverture de la session.\"\n\n#: vncviewer/CConn.cxx:332\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"SetDesktopSize échoué : %d\"\n\n#: vncviewer/CConn.cxx:404\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"Opération SetColourMapEntries du serveur invalide !\"\n\n#: vncviewer/CConn.cxx:512\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Débit %d kbit/s - %d pour une meilleure qualité\"\n\n#: vncviewer/CConn.cxx:534\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Débit %d ko/s - pleine couleur activée\"\n\n#: vncviewer/CConn.cxx:537\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Débit %d ko/s - pleine couleur désactivée\"\n\n#: vncviewer/CConn.cxx:563\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Utilisation du format de pixel %s\"\n\n#: vncviewer/DesktopWindow.cxx:145\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Géométrie spécifiée invalide !\"\n\n#: vncviewer/DesktopWindow.cxx:166\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Réduction de la taille de la fenêtre pour l'adapter au moniteur actuel\"\n\n#: vncviewer/DesktopWindow.cxx:648\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Ajustement de la taille de la fenêtre pour éviter une demande accidentelle de plein écran\"\n\n#: vncviewer/DesktopWindow.cxx:696\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Appuyez sur %s pour ouvrir le menu contextuel\"\n\n#: vncviewer/DesktopWindow.cxx:1083 vncviewer/DesktopWindow.cxx:1091\n#: vncviewer/DesktopWindow.cxx:1111\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Échec de saisie clavier\"\n\n#: vncviewer/DesktopWindow.cxx:1401\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Calcul de sortie d’écran invalide pour la demande de redimensionnement !\"\n\n#: vncviewer/EmulateMB.cxx:226 vncviewer/EmulateMB.cxx:289\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"État invalide pour une émulation à 3 boutons\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:52\n#: vncviewer/MonitorIndicesParameter.cxx:105\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Impossible de lire la configuration de l'écran\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:83\n#, c-format\nmsgid \"Invalid configuration specified for %s\"\nmsgstr \"Configuration incorrecte de %s\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:91\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"L'index d'écran %d n'existe pas\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:169\n#: vncviewer/MonitorIndicesParameter.cxx:189\n#, c-format\nmsgid \"Invalid monitor index '%s'\"\nmsgstr \"index d'écran '%s' incorrecte\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:177\n#, c-format\nmsgid \"Unexpected character '%c'\"\nmsgstr \"Caractère inattendu '%c'\"\n\n#: vncviewer/OptionsDialog.cxx:63\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"Visionneuse VNC : options de la connexion\"\n\n#: vncviewer/OptionsDialog.cxx:89 vncviewer/ServerDialog.cxx:108\n#: vncviewer/vncviewer.cxx:417\nmsgid \"Cancel\"\nmsgstr \"Annuler\"\n\n#: vncviewer/OptionsDialog.cxx:94 vncviewer/vncviewer.cxx:416\nmsgid \"OK\"\nmsgstr \"Ok\"\n\n#: vncviewer/OptionsDialog.cxx:484\nmsgid \"Compression\"\nmsgstr \"Compression\"\n\n#: vncviewer/OptionsDialog.cxx:501\nmsgid \"Auto select\"\nmsgstr \"Sélection automatique\"\n\n#: vncviewer/OptionsDialog.cxx:516\nmsgid \"Preferred encoding\"\nmsgstr \"Encodage préféré\"\n\n#: vncviewer/OptionsDialog.cxx:574\nmsgid \"Color level\"\nmsgstr \"Niveau de couleur\"\n\n#: vncviewer/OptionsDialog.cxx:585\nmsgid \"Full\"\nmsgstr \"Complet\"\n\n#: vncviewer/OptionsDialog.cxx:592\nmsgid \"Medium\"\nmsgstr \"Moyen\"\n\n#: vncviewer/OptionsDialog.cxx:599\nmsgid \"Low\"\nmsgstr \"Bas\"\n\n#: vncviewer/OptionsDialog.cxx:606\nmsgid \"Very low\"\nmsgstr \"Très bas\"\n\n#: vncviewer/OptionsDialog.cxx:624\nmsgid \"Custom compression level:\"\nmsgstr \"Niveau de compression personnalisé :\"\n\n#: vncviewer/OptionsDialog.cxx:630\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"niveau (0=rapide, 9=optimale)\"\n\n#: vncviewer/OptionsDialog.cxx:637\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Autoriser la compression JPEG :\"\n\n#: vncviewer/OptionsDialog.cxx:643\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"qualité (0=faible, 9=optimale)\"\n\n#: vncviewer/OptionsDialog.cxx:654\nmsgid \"Security\"\nmsgstr \"Sécurité\"\n\n#: vncviewer/OptionsDialog.cxx:676\nmsgid \"Encryption\"\nmsgstr \"Cryptage\"\n\n#: vncviewer/OptionsDialog.cxx:687 vncviewer/OptionsDialog.cxx:750\n#: vncviewer/OptionsDialog.cxx:854\nmsgid \"None\"\nmsgstr \"Aucun\"\n\n#: vncviewer/OptionsDialog.cxx:694\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS avec certificats anonymes\"\n\n#: vncviewer/OptionsDialog.cxx:700\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS avec certificat X509\"\n\n#: vncviewer/OptionsDialog.cxx:707\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Certificat du chemin pour X509 CA\"\n\n#: vncviewer/OptionsDialog.cxx:714\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Fichier du chemin pour X509 CRL\"\n\n#: vncviewer/OptionsDialog.cxx:739\nmsgid \"Authentication\"\nmsgstr \"Authentification\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"VNC standard (non sécurisé et sans cryptage)\"\n\n#: vncviewer/OptionsDialog.cxx:762\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Nom d’utilisateur et mot de passe (non sécurisé et sans cryptage)\"\n\n#: vncviewer/OptionsDialog.cxx:781\nmsgid \"Input\"\nmsgstr \"Entrée\"\n\n#: vncviewer/OptionsDialog.cxx:794\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Vue passive (ignorer la souris et le clavier)\"\n\n#: vncviewer/OptionsDialog.cxx:801\nmsgid \"Mouse\"\nmsgstr \"Souris\"\n\n#: vncviewer/OptionsDialog.cxx:815\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Émulation du bouton de souris du milieu\"\n\n#: vncviewer/OptionsDialog.cxx:821\nmsgid \"Show dot when no cursor\"\nmsgstr \"Afficher un point s’il n’y a pas de curseur\"\n\n#: vncviewer/OptionsDialog.cxx:835\nmsgid \"Keyboard\"\nmsgstr \"Clavier\"\n\n#: vncviewer/OptionsDialog.cxx:849\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Donner directement les clefs système au serveur (plein écran)\"\n\n#: vncviewer/OptionsDialog.cxx:852\nmsgid \"Menu key\"\nmsgstr \"Menu clef\"\n\n#: vncviewer/OptionsDialog.cxx:871\nmsgid \"Clipboard\"\nmsgstr \"Presse-papiers\"\n\n#: vncviewer/OptionsDialog.cxx:885\nmsgid \"Accept clipboard from server\"\nmsgstr \"Accepter le presse-papier du serveur\"\n\n#: vncviewer/OptionsDialog.cxx:893\nmsgid \"Also set primary selection\"\nmsgstr \"Définir également la sélection principale\"\n\n#: vncviewer/OptionsDialog.cxx:900\nmsgid \"Send clipboard to server\"\nmsgstr \"Envoyer le presse-papier au serveur\"\n\n#: vncviewer/OptionsDialog.cxx:908\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Envoyer la sélection principale vers le presse-papiers\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Display\"\nmsgstr \"Affichage\"\n\n#: vncviewer/OptionsDialog.cxx:941\nmsgid \"Display mode\"\nmsgstr \"Mode d'affichage\"\n\n#: vncviewer/OptionsDialog.cxx:956\nmsgid \"Windowed\"\nmsgstr \"Fenêtré\"\n\n#: vncviewer/OptionsDialog.cxx:964\nmsgid \"Full screen on current monitor\"\nmsgstr \"Plein écran sur l'écran actuel\"\n\n#: vncviewer/OptionsDialog.cxx:972\nmsgid \"Full screen on all monitors\"\nmsgstr \"Plein écran sur tous les écrans\"\n\n#: vncviewer/OptionsDialog.cxx:980\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Plein écran sur les écrans sélectionnés\"\n\n#: vncviewer/OptionsDialog.cxx:1007\nmsgid \"Misc.\"\nmsgstr \"Divers\"\n\n#: vncviewer/OptionsDialog.cxx:1015\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Partagé (ne pas déconnecter les autres visionneuses)\"\n\n#: vncviewer/OptionsDialog.cxx:1021\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Demander la reconnexion lorsqu'elle est perdue\"\n\n#: vncviewer/ServerDialog.cxx:58\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"Visionneuse VNC : détails de la connexion\"\n\n#: vncviewer/ServerDialog.cxx:65 vncviewer/ServerDialog.cxx:70\nmsgid \"VNC server:\"\nmsgstr \"Serveur VNC :\"\n\n#: vncviewer/ServerDialog.cxx:81\nmsgid \"Options...\"\nmsgstr \"Options…\"\n\n#: vncviewer/ServerDialog.cxx:86\nmsgid \"Load...\"\nmsgstr \"Chargement…\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save As...\"\nmsgstr \"Enregistrer sous…\"\n\n#: vncviewer/ServerDialog.cxx:103\nmsgid \"About...\"\nmsgstr \"À propos…\"\n\n#: vncviewer/ServerDialog.cxx:113\nmsgid \"Connect\"\nmsgstr \"Connexion\"\n\n#: vncviewer/ServerDialog.cxx:145\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impossible de charger l'historique du serveur :\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:173 vncviewer/ServerDialog.cxx:212\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Configuration TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:174\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Sélectionner un fichier de configuration TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:196 vncviewer/vncviewer.cxx:552\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impossible de charger le fichier de configuration :\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:213\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Enregistrer le fichier de configuration TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:239\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s existe déjà. Souhaitez vous l'écraser ?\"\n\n#: vncviewer/ServerDialog.cxx:240 vncviewer/vncviewer.cxx:414\nmsgid \"No\"\nmsgstr \"Non\"\n\n#: vncviewer/ServerDialog.cxx:240\nmsgid \"Overwrite\"\nmsgstr \"Ecraser\"\n\n#: vncviewer/ServerDialog.cxx:256\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impossible d'enregistrer le fichier de configuration :\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:290\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impossible d'enregistrer la configuration par défaut :\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:303\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impossible d'enregistrer l'historique du serveur :\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:320 vncviewer/ServerDialog.cxx:387\n#: vncviewer/parameters.cxx:635 vncviewer/parameters.cxx:740\n#: vncviewer/vncviewer.cxx:459\nmsgid \"Could not obtain the home directory path\"\nmsgstr \"Impossible de détecter le chemin du dossier personnel de l'utilisateur\"\n\n#: vncviewer/ServerDialog.cxx:333 vncviewer/ServerDialog.cxx:396\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:753\n#, c-format\nmsgid \"Could not open \\\"%s\\\": %s\"\nmsgstr \"Impossible d'ouvrir \\\"%s\\\" : %s\"\n\n#: vncviewer/ServerDialog.cxx:348 vncviewer/ServerDialog.cxx:356\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:773\n#: vncviewer/parameters.cxx:804 vncviewer/parameters.cxx:833\n#: vncviewer/parameters.cxx:839\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"Impossible de lire la ligne %d du fichier %s : %s\"\n\n#: vncviewer/ServerDialog.cxx:357 vncviewer/parameters.cxx:774\nmsgid \"Line too long\"\nmsgstr \"Ligne trop longue\"\n\n#: vncviewer/UserDialog.cxx:98\nmsgid \"Opening password file failed\"\nmsgstr \"Échec de l’ouverture du fichier mot de passe\"\n\n#: vncviewer/UserDialog.cxx:118\nmsgid \"VNC authentication\"\nmsgstr \"Authentification VNC\"\n\n#: vncviewer/UserDialog.cxx:125\nmsgid \"This connection is secure\"\nmsgstr \"Cette connexion est sécurisée\"\n\n#: vncviewer/UserDialog.cxx:129\nmsgid \"This connection is not secure\"\nmsgstr \"Cette connexion n'est pas sécurisée\"\n\n#: vncviewer/UserDialog.cxx:146\nmsgid \"Username:\"\nmsgstr \"Nom d’utilisateur :\"\n\n#: vncviewer/UserDialog.cxx:159\nmsgid \"Password:\"\nmsgstr \"Mot de passe :\"\n\n#: vncviewer/UserDialog.cxx:198\nmsgid \"Authentication cancelled\"\nmsgstr \"Authentification annulée\"\n\n#: vncviewer/Viewport.cxx:391\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Échec de la mise à jour de l'état de la LED du clavier : %lu\"\n\n#: vncviewer/Viewport.cxx:397 vncviewer/Viewport.cxx:403\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"Échec de la mise à jour de l'état de la LED du clavier : %d\"\n\n#: vncviewer/Viewport.cxx:433\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Échec de la mise à jour de l'état de la LED du clavier\"\n\n#: vncviewer/Viewport.cxx:460 vncviewer/Viewport.cxx:468\n#: vncviewer/Viewport.cxx:485\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Impossible de récupérer l'état de la LED du clavier : %d\"\n\n#: vncviewer/Viewport.cxx:849\nmsgid \"No key code specified on key press\"\nmsgstr \"Aucun code de touche défini à l'enfoncement de touche\"\n\n#: vncviewer/Viewport.cxx:1008\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Pas de scan code pour la clef virtuelle étendue 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1010\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Pas de scan code pour la clef virtuelle 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1016\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Scan code 0x%02x invalide\"\n\n#: vncviewer/Viewport.cxx:1046\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Pas de symbole pour la clef virtuelle étendue 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1048\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Pas de symbole pour la clef virtuelle 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1154\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"Pas de scan code pour le code clef 0x%02x (en l'état actuel)\"\n\n#: vncviewer/Viewport.cxx:1187\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Pas de scan code pour le code clef %d (en l'état actuel)\"\n\n#: vncviewer/Viewport.cxx:1247\nmsgctxt \"ContextMenu|\"\nmsgid \"Dis&connect\"\nmsgstr \"Dé&connecter\"\n\n#: vncviewer/Viewport.cxx:1250\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Plein écran\"\n\n#: vncviewer/Viewport.cxx:1253\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"&Réduire\"\n\n#: vncviewer/Viewport.cxx:1255\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Redimensionner la &fenêtre pour la session\"\n\n#: vncviewer/Viewport.cxx:1260\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"Ctr&l\"\n\n#: vncviewer/Viewport.cxx:1263\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1269\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"Envoyer %s\"\n\n#: vncviewer/Viewport.cxx:1275\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Envoyer Ctrl-Alt-&Sup\"\n\n#: vncviewer/Viewport.cxx:1278\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Rafraîc&hir l’écran\"\n\n#: vncviewer/Viewport.cxx:1281\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Options…\"\n\n#: vncviewer/Viewport.cxx:1283\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&Informations de connexion…\"\n\n#: vncviewer/Viewport.cxx:1285\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"À propos de la visionneuse &TigerVNC…\"\n\n#: vncviewer/Viewport.cxx:1374\nmsgid \"VNC connection info\"\nmsgstr \"Informations de la connexion VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:47\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"La fenêtre est enregistrée pour le tactile au lieu des mouvements\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Impossible de modifier la configuration des mouvements (erreur 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Impossible de lire la configuration des mouvements (erreur 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:358\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Bouton de souris %d incorrecte (doit être un chiffre entre 1 et 7).\"\n\n#: vncviewer/Win32TouchHandler.cxx:423\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Touche inconnue 0x%x - impossible de générer un évênement clavier\"\n\n#: vncviewer/XInputTouchHandler.cxx:102 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Impossible de lire le masque d'événement X Input 2 pour la fenêtre 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:104\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"La fenêtre 0x%08lx n'a pas de masque d'événement X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:112 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"La fenêtre 0x%08lx a plus d'un masque d'événement X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:143\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Échec de saisie souris %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.cxx:406 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"Visionneuse TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Se connecter à un serveur VNC et afficher le bureau à distance\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC) est un système d'affichage à distance qui permet de visualiser et d'interagir avec un environnement de bureau virtuel exécuté sur un autre ordinateur du réseau. À l'aide de VNC, vous pouvez exécuter des applications graphiques sur une machine distante et envoyer uniquement l'affichage de ces applications à votre périphérique local. Ce package contient un client qui vous permettra de vous connecter à d'autres bureaux exécutant un serveur VNC. VNC est indépendant de la plate-forme et prend en charge divers systèmes d'exploitation et architectures en tant que serveurs et clients.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC est une version optimisée pour la vitesse de VNC basée sur le code de RealVNC 4 et X.org. TigerVNC a commencé comme une réécriture de TightVNC pour les plates-formes Unix et Linux, puis il a pris son autonomie début de 2009 afin que TightVNC puisse se concentrer sur les plates-formes Windows. TigerVNC prend en charge une variante de l'encodage Tight qui tire sa rapidité de l'utilisation du codec JPEG libjpeg-turbo.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC Viewer connection to a CentOS machine\"\nmsgstr \"Connexion de TigerVNC Viewer à une machine CentOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC Viewer connection to a macOS machine\"\nmsgstr \"Connexion de TigerVNC Viewer à une machine macOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC Viewer connection to a Windows machine\"\nmsgstr \"Connexion de TigerVNC Viewer à une machine Windows\"\n\n#: vncviewer/parameters.cxx:308 vncviewer/parameters.cxx:333\n#: vncviewer/parameters.cxx:350 vncviewer/parameters.cxx:390\n#: vncviewer/parameters.cxx:410\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Le nom du paramètre était trop long\"\n\n#: vncviewer/parameters.cxx:312 vncviewer/parameters.cxx:317\n#: vncviewer/parameters.cxx:368\nmsgid \"The parameter is too large\"\nmsgstr \"Le paramètre est trop long\"\n\n#: vncviewer/parameters.cxx:375 vncviewer/parameters.cxx:696\n#: vncviewer/parameters.cxx:818\nmsgid \"Invalid format or too large value\"\nmsgstr \"Format invalide ou valeur trop grande\"\n\n#: vncviewer/parameters.cxx:429 vncviewer/parameters.cxx:460\nmsgid \"Failed to create registry key\"\nmsgstr \"Impossible de créer la clef de registre\"\n\n#: vncviewer/parameters.cxx:448 vncviewer/parameters.cxx:503\n#: vncviewer/parameters.cxx:545 vncviewer/parameters.cxx:612\nmsgid \"Failed to close registry key\"\nmsgstr \"Impossible de fermer la clef de registre\"\n\n#: vncviewer/parameters.cxx:466 vncviewer/parameters.cxx:483\n#: vncviewer/parameters.cxx:654 vncviewer/parameters.cxx:664\n#: vncviewer/parameters.cxx:675\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Échec de l'enregistrement de \\\"%s\\\" : %s\"\n\n#: vncviewer/parameters.cxx:479 vncviewer/parameters.cxx:567\n#: vncviewer/parameters.cxx:677 vncviewer/parameters.cxx:714\nmsgid \"Unknown parameter type\"\nmsgstr \"Type de paramètre inconnu\"\n\n#: vncviewer/parameters.cxx:496\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Échec de la suppression de \\\"%s\\\" : %s\"\n\n#: vncviewer/parameters.cxx:518 vncviewer/parameters.cxx:590\nmsgid \"Failed to open registry key\"\nmsgstr \"Impossible d’ouvrir la clef de registre\"\n\n#: vncviewer/parameters.cxx:535\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Impossible de lire l'entrée de l'historique du serveur %d : %s\"\n\n#: vncviewer/parameters.cxx:571 vncviewer/parameters.cxx:601\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Impossible de lire le paramètre \\\"%s\\\" : %s\"\n\n#: vncviewer/parameters.cxx:655 vncviewer/parameters.cxx:666\nmsgid \"Could not encode parameter\"\nmsgstr \"Impossible d'encoder le paramètre\"\n\n#: vncviewer/parameters.cxx:783\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Fichier de configuration %s dans un format invalide\"\n\n#: vncviewer/parameters.cxx:805\nmsgid \"Invalid format\"\nmsgstr \"Format invalide\"\n\n#: vncviewer/parameters.cxx:840\nmsgid \"Unknown parameter\"\nmsgstr \"Paramètre inconnu\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Message reçu (0x%x) pour une fenêtre non gérée\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Fenêtre 0x%08lx incorrecte spécifiée pour le traking du pointeur\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Impossible de créer le gestionnaire de touche : %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Impossible d'attacher le gestionnaire d'événement à la fenêtre (erreur 0x%x)\"\n\n#: vncviewer/touch.cxx:212\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Impossible de lire les données d'un évènement X Input\"\n\n#: vncviewer/touch.cxx:225\nmsgid \"X Input event for unknown window\"\nmsgstr \"Événement X Input pour une fenêtre inconnue\"\n\n#: vncviewer/touch.cxx:251\nmsgid \"X Input extension not available.\"\nmsgstr \"Extension X Input indisponible\"\n\n#: vncviewer/touch.cxx:258\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2 indisponible ou de version incompatible\"\n\n#: vncviewer/touch.cxx:263\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2 indisponible ou de version incompatible. Le tactile ne sera pas pris en charge.\"\n\n#: vncviewer/vncviewer.cxx:107\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"Visionneuse TigerVNC v%s\\n\"\n\"Compilé sur : %s\\n\"\n\"Copyright © 1999-%d L’équipe de TigerVNC et beaucoup d’autres (voir README.rst)\\n\"\n\"Voir https://www.tigervnc.org pour plus d’informations sur TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:161\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Une erreur inattendue s'est produite pendant la communication avec le serveur :\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:177\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"À propos de la visionneuse TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:198\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Erreur FLTK interne. Procédure de sortie.\"\n\n#: vncviewer/vncviewer.cxx:217\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Se reconnecter ?\"\n\n#: vncviewer/vncviewer.cxx:248 vncviewer/vncviewer.cxx:260\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Une erreur a démarré une nouvelle visionneuse TigerVNC : %s\"\n\n#: vncviewer/vncviewer.cxx:269\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"Signal de fin %d reçu. La visionneuse TigerVNC va se fermer.\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Yes\"\nmsgstr \"Oui\"\n\n#: vncviewer/vncviewer.cxx:418\nmsgid \"Close\"\nmsgstr \"Fermer\"\n\n#: vncviewer/vncviewer.cxx:423\nmsgid \"About\"\nmsgstr \"À propos\"\n\n#: vncviewer/vncviewer.cxx:426\nmsgid \"Hide\"\nmsgstr \"Cacher\"\n\n#: vncviewer/vncviewer.cxx:429\nmsgid \"Quit\"\nmsgstr \"Quitter\"\n\n#: vncviewer/vncviewer.cxx:433\nmsgid \"Services\"\nmsgstr \"Services\"\n\n#: vncviewer/vncviewer.cxx:434\nmsgid \"Hide Others\"\nmsgstr \"Cacher les autres\"\n\n#: vncviewer/vncviewer.cxx:435\nmsgid \"Show All\"\nmsgstr \"Afficher tout\"\n\n#: vncviewer/vncviewer.cxx:444\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Fichier\"\n\n#: vncviewer/vncviewer.cxx:447\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Nouvelle connexion\"\n\n#: vncviewer/vncviewer.cxx:463\n#, c-format\nmsgid \"Could not create VNC home directory: %s\"\nmsgstr \"Impossible de créer le répertoire VNC de départ : %s\"\n\n#: vncviewer/vncviewer.cxx:562\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors est obsolète, définissez FullScreenMode avec la valeur 'all' à la place\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:768 vncviewer/vncviewer.cxx:769\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Les paramètres -listen et -via sont incompatibles\"\n\n#: vncviewer/vncviewer.cxx:783\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Écoute du port %d\"\n\n#: vncviewer/vncviewer.cxx:816\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Échec pendant l'établissement de la connexion VNC entrante :\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"Visionneuse de bureau à distance\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"Impossible de lire le nom de l'écran car X11 RandR est introuvable\"\n\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"Impossible de lire les informations de l'écran cathodique %d\"\n\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"Impossible de lire les informations à propos de %d sur l'écran cathodique %d\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"Écran\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"Redimensionner la session distance à la connexion\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"Redimensionner la session distante pour la fenêtre locale\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"Activer le mode plein écran\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"Complet (toutes les couleurs disponibles)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"Moyen (256 couleurs)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"Faible (64 couleurs)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"Très faible (8 couleurs)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"niveau (1=rapide, 6=optimal [4-6 sont rarement utiles])\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"Mode plein écran\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"&Quitte la visionneuse\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"Masquer le &menu\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"Impossible d’écrire le paramètre %s de type %s dans le registre : %ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"Le nom du paramètre %s était trop long pour lire le registre\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"Le paramètre %s était trop long pour le lire depuis le registre\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"Impossible d'écrire le fichier de configuration, impossible d'obtenir le chemin du répertoire personnel.\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"Impossible d'écrire le fichier de configuration, impossible d’ouvrir %s : %s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"Impossible de lire le fichier de configuration, impossible d’obtenir le chemin du répertoire personnel.\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"Paramètre %s inconnu à la ligne %d du fichier %s\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"Impossible de créer le répertoire VNC de départ : impossible d’obtenir le chemin du répertoire de départ.\"\n\n#~ msgid \"tigervnc\"\n#~ msgstr \"tigervnc\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Autorisation de mises à jour en continu\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"désactivé\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"activé\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Utilise l’encodage %s\"\n"
  },
  {
    "path": "po/fur.po",
    "content": "# Friulian translation for tigervnc.\n# Copyright (C) 2017 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Fabio Tomat <f.t.public@gmail.com>, 2023.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.13.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2024-06-20 15:01+0200\\n\"\n\"PO-Revision-Date: 2024-10-03 17:59+0000\\n\"\n\"Last-Translator: Fabio T. <f.t.public@gmail.com>\\n\"\n\"Language-Team: Friulian <f.t.public@gmail.com>\\n\"\n\"Language: fur\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Editor: HaiPO 2.0 beta\\n\"\n\"X-Generator: Poedit 1.8.12\\n\"\n\n#: vncviewer/CConn.cxx:99\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Conetût al socket %s\"\n\n#: vncviewer/CConn.cxx:106\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Conetût al host %s puarte %d\"\n\n#: vncviewer/CConn.cxx:111\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nol è stât pussibil conetisi a \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:155\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Non scritori: %.80s\"\n\n#: vncviewer/CConn.cxx:160\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Host: %.80s puarte: %d\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Dimension: %d × %d\"\n\n#: vncviewer/CConn.cxx:173\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Formât pixel: %s\"\n\n#: vncviewer/CConn.cxx:180\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(predefinît dal servidôr %s)\"\n\n#: vncviewer/CConn.cxx:185\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Codifiche domandade: %s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Ultime codifiche doprade: %s\"\n\n#: vncviewer/CConn.cxx:195\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Stime velocitât linie: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:200\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Version protocol: %d.%d\"\n\n#: vncviewer/CConn.cxx:205\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Metodi sigurece: %s\"\n\n#: vncviewer/CConn.cxx:266 vncviewer/CConn.cxx:268\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"La conession e je stade molade dal servidôr prime che la session e fos stade stabilide.\"\n\n#: vncviewer/CConn.cxx:326\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"SetDesktopSize falît: %d\"\n\n#: vncviewer/CConn.cxx:399\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"SetColourMapEntries no valit dal servidôr!\"\n\n#: vncviewer/CConn.cxx:507\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Puartade %d kbit/s - si passe ae cualitât %d\"\n\n#: vncviewer/CConn.cxx:529\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Puartade %d kbit/s - plen colôr al è cumò abilitât\"\n\n#: vncviewer/CConn.cxx:532\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Puartade %d kbit/s - plen colôr al è cumò disabilitât\"\n\n#: vncviewer/CConn.cxx:558\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Si dopre il formât pixel %s\"\n\n#: vncviewer/DesktopWindow.cxx:146\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Gjeometrie specificade no valide!\"\n\n#: vncviewer/DesktopWindow.cxx:167\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Daûr a ridusi la dimension dal barcon par adatâle al visôr atuâl\"\n\n#: vncviewer/DesktopWindow.cxx:648\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Daûr a justâ la dimension dal barcon par evitâ richiestis acidentâls di plen visôr\"\n\n#: vncviewer/DesktopWindow.cxx:696\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Frache %s par vierzi il menù contestuâl\"\n\n#: vncviewer/DesktopWindow.cxx:1097 vncviewer/DesktopWindow.cxx:1105\n#: vncviewer/DesktopWindow.cxx:1125\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Nol è stât pussibil caturâ la tastiere\"\n\n#: vncviewer/DesktopWindow.cxx:1415\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Disposizion dal schermi elaborade no valide pe richieste di ridimensionament!\"\n\n#: vncviewer/EmulateMB.cxx:226 vncviewer/EmulateMB.cxx:289\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Stât no valit pe emulazion dai 3 botons\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:52\n#: vncviewer/MonitorIndicesParameter.cxx:102\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Impussibil otignî la configurazion dal visôr di sisteme\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:80\n#, c-format\nmsgid \"Invalid configuration specified for %s\"\nmsgstr \"E je stade specificade une configurazion no valide par %s\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:88\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"La tabele dal visôr %d no esist\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:166\n#: vncviewer/MonitorIndicesParameter.cxx:186\n#, c-format\nmsgid \"Invalid monitor index '%s'\"\nmsgstr \"Tabele dal visôr '%s' no valide\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:174\n#, c-format\nmsgid \"Unexpected character '%c'\"\nmsgstr \"Caratar '%c' inspietât\"\n\n#: vncviewer/OptionsDialog.cxx:64\nmsgid \"TigerVNC Options\"\nmsgstr \"Opzions di TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:97 vncviewer/ServerDialog.cxx:102\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Cancel\"\nmsgstr \"Anule\"\n\n#: vncviewer/OptionsDialog.cxx:102 vncviewer/vncviewer.cxx:394\nmsgid \"OK\"\nmsgstr \"Va ben\"\n\n#: vncviewer/OptionsDialog.cxx:502\nmsgid \"Compression\"\nmsgstr \"Compression\"\n\n#: vncviewer/OptionsDialog.cxx:518\nmsgid \"Auto select\"\nmsgstr \"Selezione in automatic\"\n\n#: vncviewer/OptionsDialog.cxx:529\nmsgid \"Preferred encoding\"\nmsgstr \"Codifiche preferide\"\n\n#: vncviewer/OptionsDialog.cxx:590\nmsgid \"Color level\"\nmsgstr \"Nivel colôr\"\n\n#: vncviewer/OptionsDialog.cxx:602\nmsgid \"Full\"\nmsgstr \"Totâl\"\n\n#: vncviewer/OptionsDialog.cxx:609\nmsgid \"Medium\"\nmsgstr \"Medi\"\n\n#: vncviewer/OptionsDialog.cxx:616\nmsgid \"Low\"\nmsgstr \"Bas\"\n\n#: vncviewer/OptionsDialog.cxx:623\nmsgid \"Very low\"\nmsgstr \"Une vore bas\"\n\n#: vncviewer/OptionsDialog.cxx:645\nmsgid \"Custom compression level:\"\nmsgstr \"Nivel compression personalizât:\"\n\n#: vncviewer/OptionsDialog.cxx:652\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"nivel (0=svelt, 9=miôr)\"\n\n#: vncviewer/OptionsDialog.cxx:659\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Permet compression JPEG:\"\n\n#: vncviewer/OptionsDialog.cxx:666\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"cualitât (0=puore, 9=miore)\"\n\n#: vncviewer/OptionsDialog.cxx:677\nmsgid \"Security\"\nmsgstr \"Sigurece\"\n\n#: vncviewer/OptionsDialog.cxx:691\nmsgid \"Encryption\"\nmsgstr \"Cifradure\"\n\n#: vncviewer/OptionsDialog.cxx:703 vncviewer/OptionsDialog.cxx:770\n#: vncviewer/OptionsDialog.cxx:876\nmsgid \"None\"\nmsgstr \"Nissun\"\n\n#: vncviewer/OptionsDialog.cxx:710\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS cun certificâts anonims\"\n\n#: vncviewer/OptionsDialog.cxx:716\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS cun certificâts X509\"\n\n#: vncviewer/OptionsDialog.cxx:723\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Percors pal certificât X509 CA\"\n\n#: vncviewer/OptionsDialog.cxx:730\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Percors pal file X509 CRL\"\n\n#: vncviewer/OptionsDialog.cxx:758\nmsgid \"Authentication\"\nmsgstr \"Autenticazion\"\n\n#: vncviewer/OptionsDialog.cxx:776\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"VNC standard (no sigûr cence cifradure)\"\n\n#: vncviewer/OptionsDialog.cxx:782\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Non utent e password (no sigûr cence cifradure)\"\n\n#: vncviewer/OptionsDialog.cxx:805\nmsgid \"Input\"\nmsgstr \"Input\"\n\n#: vncviewer/OptionsDialog.cxx:818\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Viôt e vonde (ignore mouse e tastiere)\"\n\n#: vncviewer/OptionsDialog.cxx:825\nmsgid \"Mouse\"\nmsgstr \"Mouse\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Emule boton centrâl dal mouse\"\n\n#: vncviewer/OptionsDialog.cxx:843\nmsgid \"Show dot when no cursor\"\nmsgstr \"Mostre un pont se nol è il cursôr\"\n\n#: vncviewer/OptionsDialog.cxx:859\nmsgid \"Keyboard\"\nmsgstr \"Tastiere\"\n\n#: vncviewer/OptionsDialog.cxx:871\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Mande i tascj di sisteme drets al servidôr (plen visôr)\"\n\n#: vncviewer/OptionsDialog.cxx:874\nmsgid \"Menu key\"\nmsgstr \"Tast Menù\"\n\n#: vncviewer/OptionsDialog.cxx:895\nmsgid \"Clipboard\"\nmsgstr \"Notis\"\n\n#: vncviewer/OptionsDialog.cxx:907\nmsgid \"Accept clipboard from server\"\nmsgstr \"Acete notis dal servidôr\"\n\n#: vncviewer/OptionsDialog.cxx:915\nmsgid \"Also set primary selection\"\nmsgstr \"Stabilìs ancje la selezion primarie\"\n\n#: vncviewer/OptionsDialog.cxx:922\nmsgid \"Send clipboard to server\"\nmsgstr \"Invie lis notis al servidôr\"\n\n#: vncviewer/OptionsDialog.cxx:930\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Invie la selezion primarie come notis\"\n\n#: vncviewer/OptionsDialog.cxx:951\nmsgid \"Display\"\nmsgstr \"Schermi\"\n\n#: vncviewer/OptionsDialog.cxx:965\nmsgid \"Display mode\"\nmsgstr \"Modalitât schermi\"\n\n#: vncviewer/OptionsDialog.cxx:978\nmsgid \"Windowed\"\nmsgstr \"In barcon\"\n\n#: vncviewer/OptionsDialog.cxx:986\nmsgid \"Full screen on current monitor\"\nmsgstr \"Plen schermi sul visôr corint\"\n\n#: vncviewer/OptionsDialog.cxx:994\nmsgid \"Full screen on all monitors\"\nmsgstr \"Plen-schermi su ducj i visôrs\"\n\n#: vncviewer/OptionsDialog.cxx:1002\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Plen scermi sui visôrs selezionâts\"\n\n#: vncviewer/OptionsDialog.cxx:1031\nmsgid \"Miscellaneous\"\nmsgstr \"Variis\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Condividût (no sta disconeti chei altris visualizadôrs)\"\n\n#: vncviewer/OptionsDialog.cxx:1045\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Domande di tornâ a coneti ai erôrs di conession\"\n\n#: vncviewer/ServerDialog.cxx:58\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"Visualizadôr VNC: Detais conession\"\n\n#: vncviewer/ServerDialog.cxx:68\nmsgid \"VNC server:\"\nmsgstr \"Servidôr VNC:\"\n\n#: vncviewer/ServerDialog.cxx:75\nmsgid \"Options...\"\nmsgstr \"Opzions...\"\n\n#: vncviewer/ServerDialog.cxx:79\nmsgid \"Load...\"\nmsgstr \"Cjarie...\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Save As...\"\nmsgstr \"Salve come...\"\n\n#: vncviewer/ServerDialog.cxx:97\nmsgid \"About...\"\nmsgstr \"Informazions...\"\n\n#: vncviewer/ServerDialog.cxx:106\nmsgid \"Connect\"\nmsgstr \"Conet\"\n\n#: vncviewer/ServerDialog.cxx:143\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impussibil cjamâ la cronologjie dal servidôr:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:172 vncviewer/ServerDialog.cxx:212\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Configurazion di TigerVNC (*.tighervnc)\"\n\n#: vncviewer/ServerDialog.cxx:173\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Selezione un file di configurazion di TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:195 vncviewer/vncviewer.cxx:515\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impussibil cjariâ il file di configurazion specificât:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:213\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Save la configurazion di TigerVNC su file\"\n\n#: vncviewer/ServerDialog.cxx:239\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s al esist za. Sorescrivilu?\"\n\n#: vncviewer/ServerDialog.cxx:240 vncviewer/vncviewer.cxx:392\nmsgid \"No\"\nmsgstr \"No\"\n\n#: vncviewer/ServerDialog.cxx:240\nmsgid \"Overwrite\"\nmsgstr \"Sorescrîf\"\n\n#: vncviewer/ServerDialog.cxx:256\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impussibil salvâ il file di configurazion specificât:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:290\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impussibil salvâ la configurazion predefinide:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:303\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impussibil salvâ la cronologjie dal servidôr:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:320 vncviewer/ServerDialog.cxx:386\nmsgid \"Could not obtain the state directory path\"\nmsgstr \"Impussibil otignî il percors de cartele dal stât\"\n\n#: vncviewer/ServerDialog.cxx:332 vncviewer/ServerDialog.cxx:394\n#: vncviewer/parameters.cxx:644 vncviewer/parameters.cxx:750\n#, c-format\nmsgid \"Could not open \\\"%s\\\": %s\"\nmsgstr \"Impussibil vierzi \\\"%s\\\": %s\"\n\n#: vncviewer/ServerDialog.cxx:347 vncviewer/ServerDialog.cxx:355\n#: vncviewer/parameters.cxx:764 vncviewer/parameters.cxx:770\n#: vncviewer/parameters.cxx:801 vncviewer/parameters.cxx:830\n#: vncviewer/parameters.cxx:836\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"No si è rivâts a lei la rie %d intal file %s: %s\"\n\n#: vncviewer/ServerDialog.cxx:356 vncviewer/parameters.cxx:771\nmsgid \"Line too long\"\nmsgstr \"Rie masse lungje\"\n\n#: vncviewer/UserDialog.cxx:99\nmsgid \"Opening password file failed\"\nmsgstr \"No si è rivâts a vierzi il file de password\"\n\n#: vncviewer/UserDialog.cxx:118\nmsgid \"VNC authentication\"\nmsgstr \"Autenticazion VNC\"\n\n#: vncviewer/UserDialog.cxx:125\nmsgid \"This connection is secure\"\nmsgstr \"Cheste conession e je sigure\"\n\n#: vncviewer/UserDialog.cxx:129\nmsgid \"This connection is not secure\"\nmsgstr \"Cheste conession no je sigure\"\n\n#: vncviewer/UserDialog.cxx:151\nmsgid \"Username:\"\nmsgstr \"Non utent:\"\n\n#: vncviewer/UserDialog.cxx:164\nmsgid \"Password:\"\nmsgstr \"Password:\"\n\n#: vncviewer/UserDialog.cxx:207\nmsgid \"Authentication cancelled\"\nmsgstr \"Autenticazion anulade\"\n\n#: vncviewer/Viewport.cxx:390\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Impussibil inzornâ il stât dai LEDs de tastiere: %lu\"\n\n#: vncviewer/Viewport.cxx:396 vncviewer/Viewport.cxx:402\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"Nol è stât pussibil inzornâ il stât dai LEDs de tastiere: %d\"\n\n#: vncviewer/Viewport.cxx:432\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Impussibil inzornâ il stât dai LEDs de tastiere\"\n\n#: vncviewer/Viewport.cxx:459 vncviewer/Viewport.cxx:467\n#: vncviewer/Viewport.cxx:484\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Nol è stât pussibil otignî il stât dai LEDs de tastiere: %d\"\n\n#: vncviewer/Viewport.cxx:839\nmsgid \"No key code specified on key press\"\nmsgstr \"Nissun codiç di tast specificât ae pression dal tast\"\n\n#: vncviewer/Viewport.cxx:990\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Nissun codiç di scansion pal tast virtuâl estindût 0x%02x\"\n\n#: vncviewer/Viewport.cxx:992\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Nissun codic di scansion pal tast virtuâl 0x%02x\"\n\n#: vncviewer/Viewport.cxx:998\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Codiç di scansion 0x%02x no valit\"\n\n#: vncviewer/Viewport.cxx:1028\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Nissun simbul pal tast virtuâl estindût 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1030\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Nissun simbul pal tast virtuâl 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1136\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"Nissun simbul pal codiç dal tast 0x%02x (tal stât atuâl)\"\n\n#: vncviewer/Viewport.cxx:1169\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Nissun simbul pal codiç dal tast %d (tal stât atuâl)\"\n\n#: vncviewer/Viewport.cxx:1229\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"Discon&et\"\n\n#: vncviewer/Viewport.cxx:1232\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Plen visôr\"\n\n#: vncviewer/Viewport.cxx:1235\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Im&piçulìs\"\n\n#: vncviewer/Viewport.cxx:1237\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Cambie dimension al &barcon ae session\"\n\n#: vncviewer/Viewport.cxx:1242\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:1245\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1251\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"Invie %s\"\n\n#: vncviewer/Viewport.cxx:1257\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Invie Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:1260\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Inzo&rne schermi\"\n\n#: vncviewer/Viewport.cxx:1263\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Opzions...\"\n\n#: vncviewer/Viewport.cxx:1265\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&Informazions conession...\"\n\n#: vncviewer/Viewport.cxx:1267\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"Informazions su Visualizadôr &TigerVNC\"\n\n#: vncviewer/Viewport.cxx:1356\nmsgid \"VNC connection info\"\nmsgstr \"Informazions conession VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:47\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Windows al è regjistrât pes tocjadis invezit dai mots\"\n\n#: vncviewer/Win32TouchHandler.cxx:82\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Nol è stât pussibil stabilî la configurazion dai mots (erôr 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:94\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Nol è stât pussibil otignî informazions dai mots (erôr 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:359\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Boton %d dal mouse no valit, al scugne sei un numar tra 1 e 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:424\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Tast 0x%x no gjestît - impussibil gjenerâ un event di tastiere.\"\n\n#: vncviewer/XInputTouchHandler.cxx:102 vncviewer/touch.cxx:108\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Impussibil otignî la mascare dai events X Input 2 pal barcon 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:104\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Il barcon 0x%08lx nol à une mascare dai events X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:112 vncviewer/touch.cxx:115\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Il barcon 0x%08lx al à plui di une mascare dai events X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:143\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Nol è stât pussibil caturâ il dispositîf %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.cxx:389 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"Visualizadôr TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Conet a un servidôr VNC e visualize il scritori lontan\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC) al è un sisteme par visualizâ di lontan che ti permet di viodi e interagjî cuntun ambient di scritori virtuâl che al zire suntun altri computer in rêt. Doprant VNC tu puedis eseguî aplicazions grafichis suntune machine lontane e inviâ dome la visualizazion di chestis aplicazions al to dispositîf locâl. Chest pachet al conten un client che ti permetarà di fâti coneti a un altri scritori che al eseguìs un servidôr VNC. VNC al è indipendent des plateformis e al supuarte varis sistemis operatîfs e architeturis, sedi come servidôrs che come clients.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC e je une version a alte velocitât di VNC, basade su RealVNC 4 e lis basis dal codiç di X.org. TigerVNC al è scomençât tant che tentatîf di svilup de prossime gjenerazion di TightVNC pes plateformis Unix e Linux, ma si è separât dal so progjet gjenitôr sul scomençâ dal 2009. In cheste maniere TightVNC al à podût concentrâsi su lis plateformis Windows. TigerVNC al supuarte une variante de codifiche Tight che e je une vore acelerade dal ûs dal codificadôr JPEG llibjpeg-turbo.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC Viewer connection to a CentOS machine\"\nmsgstr \"Conession di Visualizadôr TigerVNC a une machine CentOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC Viewer connection to a macOS machine\"\nmsgstr \"Conession di Visualizadôr TigerVNC a une machine macOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC Viewer connection to a Windows machine\"\nmsgstr \"Conession di Visualizadôr TigerVNC a une machine Windows\"\n\n#: vncviewer/parameters.cxx:307 vncviewer/parameters.cxx:332\n#: vncviewer/parameters.cxx:349 vncviewer/parameters.cxx:389\n#: vncviewer/parameters.cxx:409\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Il non dal parametri al è masse grant\"\n\n#: vncviewer/parameters.cxx:311 vncviewer/parameters.cxx:316\n#: vncviewer/parameters.cxx:367\nmsgid \"The parameter is too large\"\nmsgstr \"Il parametri al è masse grant\"\n\n#: vncviewer/parameters.cxx:374 vncviewer/parameters.cxx:694\n#: vncviewer/parameters.cxx:815\nmsgid \"Invalid format or too large value\"\nmsgstr \"Formât no valit o valôr masse larc\"\n\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:459\nmsgid \"Failed to create registry key\"\nmsgstr \"Nol è stât pussibil creâ clâf dal regjistri\"\n\n#: vncviewer/parameters.cxx:447 vncviewer/parameters.cxx:502\n#: vncviewer/parameters.cxx:544 vncviewer/parameters.cxx:611\nmsgid \"Failed to close registry key\"\nmsgstr \"Nol è stât pussibil sierâ la clâf dal regjistri\"\n\n#: vncviewer/parameters.cxx:465 vncviewer/parameters.cxx:482\n#: vncviewer/parameters.cxx:652 vncviewer/parameters.cxx:662\n#: vncviewer/parameters.cxx:673\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Nol è stât pussibil salvâ \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:478 vncviewer/parameters.cxx:566\n#: vncviewer/parameters.cxx:675 vncviewer/parameters.cxx:712\nmsgid \"Unknown parameter type\"\nmsgstr \"Gjenar di parametri no cognossût\"\n\n#: vncviewer/parameters.cxx:495\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Nol è stât pussibil gjavâ \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:517 vncviewer/parameters.cxx:589\nmsgid \"Failed to open registry key\"\nmsgstr \"Nol è stât pussibil vierzi la clâf dal regjistri\"\n\n#: vncviewer/parameters.cxx:534\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Nol è stât pussibil lei la vôs %d de cronologjie dal servidôr: %s\"\n\n#: vncviewer/parameters.cxx:570 vncviewer/parameters.cxx:600\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Nol è stât pussibil lei il parametri \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:634 vncviewer/parameters.cxx:738\nmsgid \"Could not obtain the config directory path\"\nmsgstr \"Impussibil otignî il percors de cartele di configurazion\"\n\n#: vncviewer/parameters.cxx:653 vncviewer/parameters.cxx:664\nmsgid \"Could not encode parameter\"\nmsgstr \"Impussibil codificâ il parametri\"\n\n#: vncviewer/parameters.cxx:780\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Il file di configurazion %s al è intun formât no valit\"\n\n#: vncviewer/parameters.cxx:802\nmsgid \"Invalid format\"\nmsgstr \"Formât no valit\"\n\n#: vncviewer/parameters.cxx:837\nmsgid \"Unknown parameter\"\nmsgstr \"Parametri no cognossût\"\n\n#: vncviewer/touch.cxx:76\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Ricevût messaç (0x%x) par un barcon no gjestît\"\n\n#: vncviewer/touch.cxx:139 vncviewer/touch.cxx:161\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Specificât barcon 0x%08lx no valit pe cature dal pontadôr\"\n\n#: vncviewer/touch.cxx:184 vncviewer/touch.cxx:185\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Nol è stât pussibil creâ un gjestôr pes tocjadis: %s\"\n\n#: vncviewer/touch.cxx:189\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Nol è stât pussibil zontâ al barcon il gjestôr dai events (erôr 0x%x)\"\n\n#: vncviewer/touch.cxx:216\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Impussibil otignî i dâts dai events pal event X Input\"\n\n#: vncviewer/touch.cxx:229\nmsgid \"X Input event for unknown window\"\nmsgstr \"Event X Input par un barcon no cognossût\"\n\n#: vncviewer/touch.cxx:255\nmsgid \"X Input extension not available.\"\nmsgstr \"Estension di X Input no disponibile.\"\n\n#: vncviewer/touch.cxx:262\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2 (o plui resint) nol è disponibil.\"\n\n#: vncviewer/touch.cxx:267\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2.2 (o plui resint) nol è disponibil. I mots tatii no saran supuartâts.\"\n\n#: vncviewer/vncviewer.cxx:104\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"Visualizadôr TigerVNC v%s\\n\"\n\"Compilât su: %s\\n\"\n\"Copyright (C) 1999-%d Il grup di TigerVNC e tancj altris (viôt README.rst)\\n\"\n\"Viôt https://www.tigervnc.org par informazions su TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:158\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Al è capitât un erôr inspietât tal comunicâ cul servidôr:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:174\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"Informazions su Visualizadôr TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Erôr FLTK interni. Daûr a jessî.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Cirî di tornâ a coneti?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Erôr tal inviâ un gnûf Visualizadôr TigerVNC: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"Il segnâl di terminazion %d al è stât ricevût. Il visualizadôr TigerVNC al jessarà cumò.\"\n\n#: vncviewer/vncviewer.cxx:393\nmsgid \"Yes\"\nmsgstr \"Sì\"\n\n#: vncviewer/vncviewer.cxx:396\nmsgid \"Close\"\nmsgstr \"Siere\"\n\n#: vncviewer/vncviewer.cxx:401\nmsgid \"About\"\nmsgstr \"Informazions\"\n\n#: vncviewer/vncviewer.cxx:404\nmsgid \"Hide\"\nmsgstr \"Plate\"\n\n#: vncviewer/vncviewer.cxx:407\nmsgid \"Quit\"\nmsgstr \"Jes\"\n\n#: vncviewer/vncviewer.cxx:411\nmsgid \"Services\"\nmsgstr \"Servizis\"\n\n#: vncviewer/vncviewer.cxx:412\nmsgid \"Hide Others\"\nmsgstr \"Plate altris\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Show All\"\nmsgstr \"Mostre dut\"\n\n#: vncviewer/vncviewer.cxx:422\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&File\"\n\n#: vncviewer/vncviewer.cxx:425\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Gnove conession\"\n\n#: vncviewer/vncviewer.cxx:525\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors al è deplorât, al so puest met FullScreenMode a 'all'\"\n\n#: vncviewer/vncviewer.cxx:721\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc al è deplorât, consulte 'man vncviewer' pai percors dulà lâ a migrâ.\"\n\n#: vncviewer/vncviewer.cxx:725\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc al è deplorât, passe ae posizion %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:730\n#, c-format\nmsgid \"Could not create VNC config directory: %s\"\nmsgstr \"Impussibil creâ la cartele di configurazion di VNC: %s\"\n\n#: vncviewer/vncviewer.cxx:735\n#, c-format\nmsgid \"Could not create VNC data directory: %s\"\nmsgstr \"Impussibil creâ la cartele dai dâts di VNC: %s\"\n\n#: vncviewer/vncviewer.cxx:740\n#, c-format\nmsgid \"Could not create VNC state directory: %s\"\nmsgstr \"Impussibil creâ la cartele dal stât di VNC: %s\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:755 vncviewer/vncviewer.cxx:756\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Parametris -listen e -via no son compatibii\"\n\n#: vncviewer/vncviewer.cxx:770\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Impussibil scoltâ lis conessions in jentrade\"\n\n#: vncviewer/vncviewer.cxx:772\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"In scolte su la puarte %d\"\n\n#: vncviewer/vncviewer.cxx:805\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Impussibil spietâ lis conessions VNC in jentrade:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"Visualizadôr di scritori lontan\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"Visualizadôr VNC: Opzions conession\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"Variis\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Daûr a abilitâ i inzornaments continuis\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"disabilitât\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"abilitât\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Si dopre la codifiche %s\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"No vonde memorie pal framebuffer\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"Impussibil creâ il dispositîf framebuffer\"\n\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"Impussibil creâ il bitmap dal framebuffer\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"Plen (ducj i colôrs disponibii)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"Medi (256 colôrs)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"Bas (64 colôrs)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"Une vore bas (8 colôrs)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"nivel (1=veloç, 6=miôr [4-6 a son di râr utii])\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"Schermi\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \" Ae conession cambie dimension ae session rimote\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"Cambie dimension ae session rimote al barcon locâl\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"Si dopre il framebuffer indipendent de plateforme\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"&Jes dal visualizadôr\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"Dismet &menù\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"impussibil creâ sezion DIB\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"CreateCompatibleDC falît\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"SelectObject falît\"\n\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"BitBlt falît\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"Il display al mancje di un formât pixmap pe profonditât predefinide\"\n\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"Impussibil cjatâ un formât pixmap adat\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"Nome i visôrs a colôrs vêrs a son supuartâts\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"No si è rivâts a scrivi il parametri %s di gjenar %s sul regjistri: %ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"Il non dal parametri %s al jere masse larc par lei dal regjistri\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"Il parametri %s al jere masse larc par lei dal regjistri\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"No si è rivâts a scrivi il file di configurazion, impussibil otignî il percors de cartele cjase.\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"No si è rivâts a scrivi il file di configurazion, impussibil vierzi %s: %s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"No si è rivâts a lei il file di configurazion, impussibil otignî il percors de cartele cjase.\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"Parametri %s no cognossût ae rie %d intal file %s\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"Impussibil creâ la cartele cjase di VNC: Impussibil otignî il percors de cartele cjase.\"\n"
  },
  {
    "path": "po/he.po",
    "content": "# Hebrew translation of TigerVNC.\n# Copyright (C) 2019 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Yaron Shahrabani <sh.yaron@gmail.com>, 2025\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc-1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2025-11-13 18:22+0200\\n\"\n\"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\\n\"\n\"Language-Team: Hebrew <heb-bugzap@hamakor.org.il>\\n\"\n\"Language: he\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n==2 ? 1 : n>10 && n%10==0 ? 2 : 3);\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.8\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"מחובר לשקע %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"מחובר למארח %s פתחה %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"ההתחברות אל „%s” נכשלה:\\n\"\n\"‬\\n\"\n\"‏‫\\n\"\n\"‬\\n\"\n\"‏‫%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"שם שולחן העבודה %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"מארח: %.80s פתחה: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"גודל: %d x %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"תצורת פיקסלים: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"קידוד נדרש: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"קידוד אחרון: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"הערכת מהירות הקו: %d קסל״ש\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"גרסת פרוטוקול: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"שיטת אבטחה: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"החיבור נקטע מצד השרת בטרם יצירת החיבור הראשוני.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"האימות נכשל: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"האימות מול השרת נכשל. הסיבה שהשרת סיפק:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"תפוקה %d קסל״ש - האיכות תוחלף לכדי %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"‫תפוקה %d קסל״ש - צבע מלא פעיל מעתה\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"‫תפוקה %d קסל״ש - צבע מלא מושבת מעתה\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"נעשה שימוש בתצורת פיקסלים %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"הממדים שצוינו שגויים!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"החלון מוקטן כדי להתאים לגודל המסך הנוכחי\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"לחיצה על %sM תפתח את תפריט ההקשר\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s - TigerVNC (מקלדת לכודה)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s - TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Adjusting window size to avoid accidental full-screen request\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"לחיצה על %sEnter תקטין את המסך\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"לכידת השליטה במקלדת נכשלה\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"לחיצה על %s תשחרר את שליטת המקלדת מההפעלה\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"חושבה פריסת מסך שגויה לבקשת שינוי הגודל!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"מצב שגוי להדמיית 3 כפתורים\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"אין קוד סריקה למקש הווירטואלי המורחב 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"‫אין קוד סריקה למקש הווירטואלי 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"קוד סריקה שגוי 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"אין סימן למקש הווירטואלי המורחב 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"אין סימן למקש הווירטואלי 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"עדכון מצב נורית המקלדת נכשל: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"אין סימן לקוד המקש %d (במצב הנוכחי)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"קבלת מצב נורית המקלדת נכשלה: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"עדכון מצב נורית המקלדת נכשל\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"קבלת הגדרות צג המערכת נכשלה\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"מפתח צג %d לא קיים\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"אפשרויות TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"ביטול\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"אישור\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"דחיסה\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"בחירה אוטומטית\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"לאפשר דחיסת JPEG\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"קידוד מועדף\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"רמת צבע\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"מלאה\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"בינונית\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"נמוכה\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"נמוכה מאוד\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"רמת דחיסה מותאמת אישית\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"רמה (0=מהירה, 9=מיטבית)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"רמת איכות\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"איכות (0=עלובה, 9=מיטבית)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"אבטחה\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"הצפנה\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"ללא\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"‫TLS עם אישורים אלמוניים\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"‫TLS עם אישורי X509\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"נתיב לאישורי X509 של רשות אישורים\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"נתיב לקובץ X509 CRL\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"אימות\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"רגיל של VNC (בלתי מאובטח וללא הצפנה)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"שם משתמש וססמה (בלתי מאובטח וללא הצפנה)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"קלט\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"להציג בלבד (להתעלם מהעכבר ומהמקלדת)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"עכבר\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"הדמיית כפתור עכבר אמצעי\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"להציג את הסמן המקומי כשהשרת לא מספק כזה\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"סוג סמן\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"נקודה\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"כמו המערכת\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"מקלדת\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"תמיד לשלוח את כל קלט המקלדת במסך מלא\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"לוח גזירים\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"לקבל לוח גזירים מהשרת\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"להגדיר גם את הבחירה העיקרית\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"לשלוח לוח גזירים לשרת\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"לשלוח את הבחירה העיקרית כלוח כזירים\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"קיצורי מקשים\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"מקשי החלפה לקיצורי מקלדת:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Shift\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Shift\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Option\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"תצוגה\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"מצב תצוגה\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"בחלון\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"מסך מלא בצג הנוכחי\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"מסך מלא על כל הצגים\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"מסך מלא בצגים נבחרים\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"שונות\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"משותף (לא לנתק צופים אחרים)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"לבקש להתחבר מחדש כשיש תקלות חיבור\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"כל קיצורי המקלדת מושבתים.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"כדי לשחרר שליטה על המקלדת מההפעלה, יש ללחוץ על %s.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"כדי להעביר את כל קלט המקלדת להפעלה, יש ללחוץ על %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"כדי להגדיל/להקטן מסך מלא, יש ללחוץ על %sEnter.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"כדי לפתוח את תפריט ההקשר של ההפעלה, יש ללחוץ על %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"כדי לשלוח צירוף מקשים שכולל את %s ישירות להפעלה, יש ללחוץ על %sרווח, לשחרר את מקש הרווח מבלי לשחרר את %s וללחוץ על המקש הרצוי.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"שרת VNC:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"אפשרויות…\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"לטעון…\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"לשמור בשם…\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"על אודות…\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"התחברות\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"לא ניתן לטעון את היסטוריית השרת:\\n\"\n\"‬\\n\"\n\"‏‫\\n\"\n\"‬\\n\"\n\"‏‫%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"הגדרות TigerVNC‏ (‎*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"נא לבחור קובץ הגדרות של TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"לא ניתן לטעון את קובץ ההגדרות שצוין:\\n\"\n\"‬\\n\"\n\"‏‫\\n\"\n\"‬\\n\"\n\"‏‫%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"לשמור את הגדרות ה־TigerVNC לקובץ\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"‫%s כבר קיים. לשכתב עליו?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"לא\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"לשכתב\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"לא ניתן לשמור את קובץ ההגדרות שצוין:\\n\"\n\"‬\\n\"\n\"‏‫\\n\"\n\"‬\\n\"\n\"‏‫%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"לא ניתן לשמור את הגדרות בררת המחדל:\\n\"\n\"‬\\n\"\n\"‏‫\\n\"\n\"‬\\n\"\n\"‏‫%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"לא ניתן לשמור את היסטוריית השרת:\\n\"\n\"‬\\n\"\n\"‏‫\\n\"\n\"‬\\n\"\n\"‏‫%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"לא ניתן לקבוע מה נתיב תיקיית המצב\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"לא ניתן לפתוח את „%s”\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"קריאת השורה %d בקובץ „%s” נכשלה\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"השורה ארוכה מדי\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"פתיחת קובץ הססמה נכשלה\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"אימות VNC\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"החיבור מאובטח\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"החיבור אינו מאובטח\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"שם משתמש:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"ססמה:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"לשמור את הסיסמה להתחברות מחדש\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"אירעה שגיאה בלתי צפויה בעת ההתקשרות עם השרת:\\n\"\n\"‬\\n\"\n\"‏‫\\n\"\n\"‬\\n\"\n\"‏‫%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"&ניתוק\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"מ&סך מלא\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"מ&זעור\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"שינוי &גודל החלון להפעלה\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"לשלוח Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&רענון המסך\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&אפשרויות…\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&פרטי ההתחברות…\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"&על TigerVNC…\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"פרטי חיבור VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"החלון רשום למגע במקום למחוות\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"קביעת הגדרות המחוות נכשלה (שגיאה 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"קבלת פרטי המחווה נכשלה (שגיאה 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"כפתור העכבר %d שגוי, חייב להיות מספר בין 1 ל־7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"מקש 0x%x לא מטופל - לא ניתן לייצר אירוע מקלדת.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"לא ניתן לקבל מסכת אירועים של X Input 2 לחלון 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"לחלון 0x%08lx אין מסכת אירועים של X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"לחלון 0x%08lx יש יותר ממסכת אירועים אחת של X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"לכידת ההתקן %i נכשלה\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"התחברות לשרת VNC והצגת שולחן עבודה מרוחק\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"מחשוב רשת וירטואלי (VNC) היא מערכת תצוגה מרחוק שמאפשרת לצפות ולתפעל סביבת שולחן עבודה וירטואלית שרצה על גבי מחשב אחר ברשת. באמצעות VNC אפשר להריץ יישומים גרפיים על מכונה מרוחקת ולשלוח רק את התצוגה מהיישומים האלה למכשיר המקומי שלך. החבילה הזאת מכילה לקוח שיאפשר לך להתחבר לשולחנות עבודה אחרים שמריצים שרת VNC. ל־VNC אין תלות במערכת הפעלה כזאת או אחרת והיא תומכת במגוון מערכות הפעלה וסוגי מעבדים הן מצד השרת והן מצד הלקוח.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"שTigerVNC היא גרסה מהירה של VNC שמבוססת ביסודה על קוד המקור של RealVNC ושל X.Org. מיזם TigerVNC החל כמאמץ פיתוח לדור הבא של TightVNC לפלטפורמות יוניקס ולינוקס אך הוא פוצל ממיזם ההורה שלו בתחילת 2009 כדי לאפשר ל־TightVNC להתמקד בתמיכה ב־Windows. ב־TigerVNC יש תמיכה במגוון של הצפנות Tight שמואצות על ידי השימוש במפענח JPEG בשם libjpeg-turbo.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"חיבור TigerVNC למכונת CentOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"חיבור TigerVNC למכונת macOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"חיבור TigerVNC למכונת Windows\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"צוות TigerVNC\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"שם המשתנה גדול מדי\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"המשתנה גדול מדי\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"תצורה שגויה או שהערך גדול מדי\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"יצירת המפתח ברשומות נכשלה\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"סגירת מפתח הרשומות נכשלה\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"השמירה של „%s” נכשלה: %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"ההסרה של „%s” נכשלה: %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"פתיחת מפתח הרשומות נכשלה\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"קריאת רשומה %d בהיסטוריית השרת נכשלה: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"קריאת המשתנה „%s” נכשלה: %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"לא ניתן לקבוע מה נתיב תיקיית ההגדרות\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"לא ניתן לקודד את המשתנים\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"המבנה של קובץ ההגדרות %s שגוי\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"תצורה שגויה\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"משתנה לא ידוע\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"התקבלה הודעה (0x%x) לחלון לא מטופל\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"צוין חלון שגוי 0x%08lx ללכידת סמן\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"יצירת המטפל באירועי מגע נכשלה: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"הצמדת מטפל האירועים לחלון לא צלחה (שגיאה 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"קבלת נתוני האירוע של אירוע X Input נכשלה\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"אירוע X Input לחלון בלתי מוכר\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"הרחבת X Input אינה זמינה.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"‫X Input 2 (ומעלה) אינו זמין.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"‫X Input 2.2 (ומעלה) אינו זמין. לא תהיה תמיכה במחוות מגע.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"‏TigerVNC‏ גרסה %s\\n\"\n\"‫נבנה על גבי: %s\\n\"\n\"‫כל הזכויות שמורות (C) 1999‏-%d לצוות TigerVNC ועוד רבים וטובים (ניתן לעיין ב־README.rst)\\n\"\n\"‬‫למידע על TigerVNC מומלץ לפנות אל https://www.tigervnc.org.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"על TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"שגיאת FLTK פנימית. מתבצעת יציאה.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"‫%s\\n\"\n\"‬\\n\"\n\"‏‫\\n\"\n\"‬\\n\"\n\"‫לנסות להתחבר מחדש?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"שגיאה בהקמת חיבור חדש: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"התקבל אות חיסול %d.‏ TigerVNC יסתיים כעת.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"כן\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"סגירה\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"על אודות\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"להסתיר\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"יציאה\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"שירותים\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"להסתיר אחרים\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"להציג הכול\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&קובץ\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&התחברות חדשה\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"שימוש: ‎%s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [שקע יוניקס]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [קובץ ‎.tigervnc]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"אפשרויות:\\n\"\n\"\\n\"\n\"‏  ‎-display Xdisplay  - בחירת תצוגת ה־X לחלון המציג\\n\"\n\"‏  ‎-geometry geometry - המקום ההתחלתי לחלון המציג הראשי של TigerVNC. בהנחיות שב־man\\n\"\n\"                       יש פרטים נוספים.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"את המשתנים אפשר להדליק עם ‎-<param>‎ או לכבות עם ‎-<param>=0\\n\"\n\"משתנים שמקבלים ערך אפשר לציין בתור ‎-<param> <value>\\n\"\n\"הצורות התקפות הנוספות הן ‎<param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"שמות המשתנים תלויי רישיות (אותיות גדולות וקטנות אינן זהות).  המשתנים הם:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"השימוש בהגדרה FullScreenAllMonitors הופסק, יש להגדיר את FullScreenMode לערך ‚all’ במקום\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"השימוש ב־DotWhenNoCursor הופסק, יש להגדיר את AlwaysCursor ל־1 ואת CursorType ל־‚Dot’ (נקודה) במקום\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"השימוש ב־‎~/.vnc הופסק, נא לפנות למדריך ‚man vncviewer’ לאיתור הנתיבים שיש לעבור אליהם.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"השימוש ב־%%APPDATA%%\\\\vnc הופסק, נא לעבור למקום %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"לא ניתן ליצור תיקיית הגדרות של VNC‏ „%s”:‏ %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"לא ניתן לקבוע מה תיקיית הנתונים של VNC\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"לא ניתן ליצור תיקיית נתונים של VNC‏ „%s”:‏ %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"לא ניתן ליצור תיקיית מצב של VNC ‏„%s”:‏ %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: האפשרות ‚%s’ לא מזוהה\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"יש להקליד ‚‎%s --help’ למידע נוסף.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: ארגומנט נוסף ‚%s’\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"המשתנים ‎-listen ו־‎-via לא מתאימים יחד\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"לא ניתן להאזין לחיבורים נכנסים\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"בהאזנה בפתחה %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"ההמתנה לחיבור VNC נכנס נכשלה:\\n\"\n\"‬\\n\"\n\"‏‫\\n\"\n\"‬\\n\"\n\"‏‫%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"הקמת ערוץ תקשורת מוצפן נכשלה:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"מציג שולחנות עבודה מרוחקים\"\n\n#, c-format\n#~ msgid \"(server default %s)\"\n#~ msgstr \"(בררת המחדל של השרת %s)\"\n\n#, c-format\n#~ msgid \"SetDesktopSize failed: %d\"\n#~ msgstr \"‫SetDesktopSize נכשלה: %d\"\n\n#~ msgid \"Invalid SetColourMapEntries from server!\"\n#~ msgstr \"‫SetColourMapEntries שגוי מהשרת!\"\n\n#, c-format\n#~ msgid \"Invalid configuration specified for %s\"\n#~ msgstr \"צוינו הגדרות שגויות עבור %s\"\n\n#, c-format\n#~ msgid \"Invalid monitor index '%s'\"\n#~ msgstr \"מפתח הצג ‚%s’ שגוי\"\n\n#, c-format\n#~ msgid \"Unexpected character '%c'\"\n#~ msgstr \"התו ‚%c’ אינו צפוי\"\n\n#~ msgid \"Pass system keys directly to server (full screen)\"\n#~ msgstr \"להעביר את מקשי המערכת ישירות לשרת (מסך מלא)\"\n\n#~ msgid \"Menu key\"\n#~ msgstr \"מקש תפריט\"\n\n#~ msgid \"VNC viewer: Connection details\"\n#~ msgstr \"מציג VNC: פרטי התחברות\"\n\n#, c-format\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Send %s\"\n#~ msgstr \"לשלוח %s\"\n\n#~ msgid \"TigerVNC viewer\"\n#~ msgstr \"מציג TigerVNC\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"להציג נקודה כשאין סמן\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"עדכון מצב נורית המקלדת נכשל: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"לא צוין קוד מקש עם לחיצה על מקש\"\n\n#, c-format\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"אין סימן לקוד המקש 0x%02x (במצב הנוכחי)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"סוג המשתנה אינו ידוע\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"מציג VNC: אפשרויות התחברות\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"שונות\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"קבלת שם הצג נכשלה כיוון שלא ניתן למצוא את X11 RandR\"\n\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"קבלת מידע על CRTC %d נכשלה\"\n\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"קבלת מידע על פלט %d עבור CRTC %d נכשלה\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"מסך\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"לשנות את גודל ההפעלה המרוחקת עם ההתחברות\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"לשנות את גודל ההפעלה המרוחקת לחלון המקומי\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"הפעלת מסך מלא\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"מלאה (כל הצבעים הזמינים)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"בינונית (256 צבעים)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"נחותה (64 צבעים)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"נחותה במיוחד (8 צבעים)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"רמה (1=מהירה, 6=מיטבית [4-6 אינן הכרחיות בדרך כלל])\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"מצב מסך מלא\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"י&ציאה מהמציג\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"הת&עלמות מהתפריט\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"כתיבת המשתנה %s מסוג %s ברשומות נכשלה: %ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"שם המשתנה %s היה ארוך מכדי לקרוא אותו מהרשומות\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"המשתנה %s היה גדול מכדי לקרוא מהרשומות\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"כתיבת קובץ ההגדרות נכשלה, אי אפשר לקבל את נתיב תיקיית הבית.\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"כתיבת קובץ ההגדרות נכשלה, אי אפשר לפתוח את %s:‏ %s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"קריאת קובץ ההגדרות נכשלה, אי אפשר לקבל את נתיב תיקיית הבית.\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"משתנה לא ידוע %s בשורה %d בקובץ %s\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"לא ניתן ליצור תיקיית בית VNC: לא ניתן לקבל את נתיב תיקיית הבית.\"\n\n#~ msgid \"tigervnc\"\n#~ msgstr \"tigervnc\"\n"
  },
  {
    "path": "po/hu.po",
    "content": "# Hungarian translation for TigerVNC.\n# Copyright (C) 2017, 2019 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n#\n# Balázs Úr <ur.balazs@fsf.hu>, 2017, 2019.\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.9.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2019-10-18 10:14+0200\\n\"\n\"PO-Revision-Date: 2019-11-23 23:25+0100\\n\"\n\"Last-Translator: Balázs Úr <ur.balazs@fsf.hu>\\n\"\n\"Language-Team: Hungarian <translation-team-hu@lists.sourceforge.net>\\n\"\n\"Language: hu\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Lokalize 19.04.3\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: vncviewer/CConn.cxx:99\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Kapcsolódva a(z) %s foglalathoz\"\n\n#: vncviewer/CConn.cxx:106\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Kapcsolódva a(z) %s géphez a következő porton: %d\"\n\n#: vncviewer/CConn.cxx:157\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Asztal neve: %.80s\"\n\n#: vncviewer/CConn.cxx:162\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Gép: %.80s port: %d\"\n\n#: vncviewer/CConn.cxx:167\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Méret: %d x %d\"\n\n#: vncviewer/CConn.cxx:175\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Képpontformátum: %s\"\n\n#: vncviewer/CConn.cxx:182\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(kiszolgáló alapértéke: %s)\"\n\n#: vncviewer/CConn.cxx:187\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Kért kódolás: %s\"\n\n#: vncviewer/CConn.cxx:192\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Legutóbb használt kódolás: %s\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Vonali sebesség becslés: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:202\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Protokollverzió: %d.%d\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Biztonsági módszer: %s\"\n\n#: vncviewer/CConn.cxx:324\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"Az asztal méretének beállítása sikertelen: %d\"\n\n#: vncviewer/CConn.cxx:372\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"Érvénytelen színtérkép-bejegyzések beállítás a kiszolgálóról!\"\n\n#: vncviewer/CConn.cxx:480\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Áteresztőképesség %d kbit/s – váltás a(z) %d. minőségre\"\n\n#: vncviewer/CConn.cxx:502\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Áteresztőképesség %d kbit/s – a teljes szín most engedélyezve\"\n\n#: vncviewer/CConn.cxx:505\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Áteresztőképesség %d kbit/s – a teljes szín most letiltva\"\n\n#: vncviewer/CConn.cxx:531\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"%s képpontformátum használata\"\n\n#: vncviewer/DesktopWindow.cxx:122\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Érvénytelen geometria lett megadva!\"\n\n#: vncviewer/DesktopWindow.cxx:495\nmsgid \"Adjusting window size to avoid accidental full screen request\"\nmsgstr \"Ablakméret igazítása az esetleges teljes képernyős kérés elkerüléséhez\"\n\n#: vncviewer/DesktopWindow.cxx:539\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Nyomja meg a(z) %s billentyűt a helyi menü megnyitásához\"\n\n#: vncviewer/DesktopWindow.cxx:836 vncviewer/DesktopWindow.cxx:844\n#: vncviewer/DesktopWindow.cxx:864\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"A billentyűzet elfogása sikertelen\"\n\n#: vncviewer/DesktopWindow.cxx:938\nmsgid \"Failure grabbing mouse\"\nmsgstr \"Az egér elfogása sikertelen\"\n\n#: vncviewer/DesktopWindow.cxx:1162\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Érvénytelen számított képernyő elrendezés az átméretezési kérésnél!\"\n\n#: vncviewer/OptionsDialog.cxx:57\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"VNC megjelenítő: kapcsolat beállításai\"\n\n#: vncviewer/OptionsDialog.cxx:83 vncviewer/ServerDialog.cxx:91\n#: vncviewer/vncviewer.cxx:282\nmsgid \"Cancel\"\nmsgstr \"Mégse\"\n\n#: vncviewer/OptionsDialog.cxx:88 vncviewer/vncviewer.cxx:281\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: vncviewer/OptionsDialog.cxx:423\nmsgid \"Compression\"\nmsgstr \"Tömörítés\"\n\n#: vncviewer/OptionsDialog.cxx:439\nmsgid \"Auto select\"\nmsgstr \"Automatikus kiválasztás\"\n\n#: vncviewer/OptionsDialog.cxx:451\nmsgid \"Preferred encoding\"\nmsgstr \"Előnyben részesített kódolás\"\n\n#: vncviewer/OptionsDialog.cxx:499\nmsgid \"Color level\"\nmsgstr \"Színszint\"\n\n#: vncviewer/OptionsDialog.cxx:510\nmsgid \"Full (all available colors)\"\nmsgstr \"Teljes (az összes elérhető szín)\"\n\n#: vncviewer/OptionsDialog.cxx:517\nmsgid \"Medium (256 colors)\"\nmsgstr \"Közepes (256 szín)\"\n\n#: vncviewer/OptionsDialog.cxx:524\nmsgid \"Low (64 colors)\"\nmsgstr \"Alacsony (64 szín)\"\n\n#: vncviewer/OptionsDialog.cxx:531\nmsgid \"Very low (8 colors)\"\nmsgstr \"Nagyon alacsony (8 szín)\"\n\n#: vncviewer/OptionsDialog.cxx:548\nmsgid \"Custom compression level:\"\nmsgstr \"Egyéni tömörítési szint:\"\n\n#: vncviewer/OptionsDialog.cxx:554\nmsgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\nmsgstr \"szint (1=gyors, 6=legjobb [4-6 ritkán hasznos])\"\n\n#: vncviewer/OptionsDialog.cxx:561\nmsgid \"Allow JPEG compression:\"\nmsgstr \"JPEG tömörítés engedélyezése:\"\n\n#: vncviewer/OptionsDialog.cxx:567\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"minőség (0=szegényes, 9=legjobb)\"\n\n#: vncviewer/OptionsDialog.cxx:578\nmsgid \"Security\"\nmsgstr \"Biztonság\"\n\n#: vncviewer/OptionsDialog.cxx:593\nmsgid \"Encryption\"\nmsgstr \"Titkosítás\"\n\n#: vncviewer/OptionsDialog.cxx:604 vncviewer/OptionsDialog.cxx:657\n#: vncviewer/OptionsDialog.cxx:737\nmsgid \"None\"\nmsgstr \"Nincs\"\n\n#: vncviewer/OptionsDialog.cxx:610\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS névtelen tanúsítványokkal\"\n\n#: vncviewer/OptionsDialog.cxx:616\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS X509 tanúsítványokkal\"\n\n#: vncviewer/OptionsDialog.cxx:623\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Útvonal az X509 CA tanúsítványhoz\"\n\n#: vncviewer/OptionsDialog.cxx:630\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Útvonal az X509 CRL fájlhoz\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Authentication\"\nmsgstr \"Hitelesítés\"\n\n#: vncviewer/OptionsDialog.cxx:663\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Szabványos VNC (titkosítás nélkül nem biztonságos)\"\n\n#: vncviewer/OptionsDialog.cxx:669\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Felhasználónév és jelszó (titkosítás nélkül nem biztonságos)\"\n\n#: vncviewer/OptionsDialog.cxx:688\nmsgid \"Input\"\nmsgstr \"Bemenet\"\n\n#: vncviewer/OptionsDialog.cxx:696\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Csak megtekintés (egér és billentyűzet mellőzése)\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"Accept clipboard from server\"\nmsgstr \"Vágólap elfogadása a kiszolgálóról\"\n\n#: vncviewer/OptionsDialog.cxx:710\nmsgid \"Also set primary selection\"\nmsgstr \"Elsődleges kijelölés beállítása\"\n\n#: vncviewer/OptionsDialog.cxx:717\nmsgid \"Send clipboard to server\"\nmsgstr \"Vágólap küldése a kiszolgálónak\"\n\n#: vncviewer/OptionsDialog.cxx:725\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Elsődleges kijelölés küldése vágólapként\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Rendszerbillentyűk közvetlen átadása a kiszolgálónak (teljes képernyő)\"\n\n#: vncviewer/OptionsDialog.cxx:735\nmsgid \"Menu key\"\nmsgstr \"Menü billentyű\"\n\n#: vncviewer/OptionsDialog.cxx:751\nmsgid \"Screen\"\nmsgstr \"Képernyő\"\n\n#: vncviewer/OptionsDialog.cxx:759\nmsgid \"Resize remote session on connect\"\nmsgstr \"Távoli munkamenet átméretezése kapcsolódáskor\"\n\n#: vncviewer/OptionsDialog.cxx:772\nmsgid \"Resize remote session to the local window\"\nmsgstr \"Távoli munkamenet átméretezése a helyi ablakhoz\"\n\n#: vncviewer/OptionsDialog.cxx:778\nmsgid \"Full-screen mode\"\nmsgstr \"Teljes képernyős mód\"\n\n#: vncviewer/OptionsDialog.cxx:784\nmsgid \"Enable full-screen mode over all monitors\"\nmsgstr \"Teljes képernyős mód engedélyezése az összes kijelzőn\"\n\n#: vncviewer/OptionsDialog.cxx:793\nmsgid \"Misc.\"\nmsgstr \"Egyéb\"\n\n#: vncviewer/OptionsDialog.cxx:801\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Megosztott (ne válassza le a többi nézőt)\"\n\n#: vncviewer/OptionsDialog.cxx:807\nmsgid \"Show dot when no cursor\"\nmsgstr \"Pont megjelenítése, ha nincs kurzor\"\n\n#: vncviewer/ServerDialog.cxx:42\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"VNC megjelenítő: kapcsolat részletei\"\n\n#: vncviewer/ServerDialog.cxx:49 vncviewer/ServerDialog.cxx:54\nmsgid \"VNC server:\"\nmsgstr \"VNC kiszolgáló:\"\n\n#: vncviewer/ServerDialog.cxx:64\nmsgid \"Options...\"\nmsgstr \"Beállítások…\"\n\n#: vncviewer/ServerDialog.cxx:69\nmsgid \"Load...\"\nmsgstr \"Betöltés…\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"Save As...\"\nmsgstr \"Mentés másként…\"\n\n#: vncviewer/ServerDialog.cxx:86\nmsgid \"About...\"\nmsgstr \"Névjegy…\"\n\n#: vncviewer/ServerDialog.cxx:96\nmsgid \"Connect\"\nmsgstr \"Kapcsolódás\"\n\n#: vncviewer/ServerDialog.cxx:137 vncviewer/ServerDialog.cxx:171\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"TigerVNC-beállítás (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:138\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Válasszon egy TigerVNC-beállítófájlt\"\n\n#: vncviewer/ServerDialog.cxx:172\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"A TigerVNC-beállítás mentése fájlba\"\n\n#: vncviewer/ServerDialog.cxx:197\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"A(z) %s már létezik. Szeretné felülírni?\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:279\nmsgid \"No\"\nmsgstr \"Nem\"\n\n#: vncviewer/ServerDialog.cxx:198\nmsgid \"Overwrite\"\nmsgstr \"Felülírás\"\n\n#: vncviewer/UserDialog.cxx:85\nmsgid \"Opening password file failed\"\nmsgstr \"A jelszófájl megnyitása sikertelen\"\n\n#: vncviewer/UserDialog.cxx:105\nmsgid \"VNC authentication\"\nmsgstr \"VNC hitelesítés\"\n\n#: vncviewer/UserDialog.cxx:112\nmsgid \"This connection is secure\"\nmsgstr \"Ez a kapcsolat biztonságos\"\n\n#: vncviewer/UserDialog.cxx:116\nmsgid \"This connection is not secure\"\nmsgstr \"Ez a kapcsolat nem biztonságos\"\n\n#: vncviewer/UserDialog.cxx:133\nmsgid \"Username:\"\nmsgstr \"Felhasználónév:\"\n\n#: vncviewer/UserDialog.cxx:146\nmsgid \"Password:\"\nmsgstr \"Jelszó:\"\n\n#: vncviewer/UserDialog.cxx:185\nmsgid \"Authentication cancelled\"\nmsgstr \"Hitelesítés megszakítva\"\n\n#: vncviewer/Viewport.cxx:389\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Nem sikerült frissíteni a billentyűzet LED állapotát: %lu\"\n\n#: vncviewer/Viewport.cxx:395 vncviewer/Viewport.cxx:401\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"Nem sikerült frissíteni a billentyűzet LED állapotát: %d\"\n\n#: vncviewer/Viewport.cxx:431\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Nem sikerült frissíteni a billentyűzet LED állapotát\"\n\n#: vncviewer/Viewport.cxx:458 vncviewer/Viewport.cxx:466\n#: vncviewer/Viewport.cxx:483\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Nem sikerült lekérni a billentyűzet LED állapotát: %d\"\n\n#: vncviewer/Viewport.cxx:833\nmsgid \"No key code specified on key press\"\nmsgstr \"Nincs billentyűkód megadva a billentyűzetlenyomáskor\"\n\n#: vncviewer/Viewport.cxx:982\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Nincs keresőkód a kiterjesztett virtuális billentyűhöz: 0x%02x\"\n\n#: vncviewer/Viewport.cxx:984\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Nincs keresőkód a virtuális billentyűhöz: 0x%02x\"\n\n#: vncviewer/Viewport.cxx:990\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Érvénytelen keresőkód: 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1020\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Nincs szimbólum a kiterjesztett virtuális billentyűhöz: 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1022\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Nincs szimbólum a virtuális billentyűhöz: 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1115\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"Nincs szimbólum a billentyűkódhoz: 0x%02x (a jelenlegi állapotban)\"\n\n#: vncviewer/Viewport.cxx:1148\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Nincs szimbólum a billentyűkódhoz: %d (a jelenlegi állapotban)\"\n\n#: vncviewer/Viewport.cxx:1199\nmsgctxt \"ContextMenu|\"\nmsgid \"E&xit viewer\"\nmsgstr \"&Kilépés a megjelenítőből\"\n\n#: vncviewer/Viewport.cxx:1202\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Teljes képernyő\"\n\n#: vncviewer/Viewport.cxx:1205\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Minimali&zálás\"\n\n#: vncviewer/Viewport.cxx:1207\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"&Ablak átméretezése a munkamenethez\"\n\n#: vncviewer/Viewport.cxx:1212\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:1215\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1221\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"%s küldése\"\n\n#: vncviewer/Viewport.cxx:1227\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Ctrl+Alt+&Del küldése\"\n\n#: vncviewer/Viewport.cxx:1230\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Képernyő &frissítése\"\n\n#: vncviewer/Viewport.cxx:1233\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Beállítások…\"\n\n#: vncviewer/Viewport.cxx:1235\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Kapcsolat&információk…\"\n\n#: vncviewer/Viewport.cxx:1237\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"A &TigerVNC megjelenítő névjegye…\"\n\n#: vncviewer/Viewport.cxx:1240\nmsgctxt \"ContextMenu|\"\nmsgid \"Dismiss &menu\"\nmsgstr \"&Menü eltüntetése\"\n\n#: vncviewer/Viewport.cxx:1329\nmsgid \"VNC connection info\"\nmsgstr \"VNC kapcsolatinformációk\"\n\n#: vncviewer/parameters.cxx:278 vncviewer/parameters.cxx:312\n#, c-format\nmsgid \"The name of the parameter %s was too large to write to the registry\"\nmsgstr \"A(z) %s paraméter neve túl nagy volt a regisztrációs adatbázisba történő íráshoz\"\n\n#: vncviewer/parameters.cxx:284 vncviewer/parameters.cxx:291\n#, c-format\nmsgid \"The parameter %s was too large to write to the registry\"\nmsgstr \"A(z) %s paraméter túl nagy volt a regisztrációs adatbázisba történő íráshoz\"\n\n#: vncviewer/parameters.cxx:297 vncviewer/parameters.cxx:318\n#, c-format\nmsgid \"Failed to write parameter %s of type %s to the registry: %ld\"\nmsgstr \"Nem sikerült a(z) %2$s típusú %1$s paraméter írása a regisztrációs adatbázisba: %3$ld\"\n\n#: vncviewer/parameters.cxx:334 vncviewer/parameters.cxx:377\n#, c-format\nmsgid \"The name of the parameter %s was too large to read from the registry\"\nmsgstr \"A(z) %s paraméter neve túl nagy volt a regisztrációs adatbázisból történő olvasáshoz\"\n\n#: vncviewer/parameters.cxx:346 vncviewer/parameters.cxx:386\n#, c-format\nmsgid \"Failed to read parameter %s from the registry: %ld\"\nmsgstr \"Nem sikerült a(z) %s paraméter olvasása a regisztrációs adatbázisból: %ld\"\n\n#: vncviewer/parameters.cxx:357\n#, c-format\nmsgid \"The parameter %s was too large to read from the registry\"\nmsgstr \"A(z) %s paraméter túl nagy volt a regisztrációs adatbázisból történő olvasáshoz\"\n\n#: vncviewer/parameters.cxx:406\n#, c-format\nmsgid \"Failed to create registry key: %ld\"\nmsgstr \"Nem sikerült létrehozni a regisztrációs adatbázis kulcsot: %ld\"\n\n#: vncviewer/parameters.cxx:420 vncviewer/parameters.cxx:469\n#: vncviewer/parameters.cxx:532 vncviewer/parameters.cxx:666\n#, c-format\nmsgid \"Unknown parameter type for parameter %s\"\nmsgstr \"Ismeretlen paramétertípus a(z) %s paraméternél\"\n\n#: vncviewer/parameters.cxx:427 vncviewer/parameters.cxx:476\n#, c-format\nmsgid \"Failed to close registry key: %ld\"\nmsgstr \"Nem sikerült lezárni a regisztrációs adatbázis kulcsot: %ld\"\n\n#: vncviewer/parameters.cxx:443\n#, c-format\nmsgid \"Failed to open registry key: %ld\"\nmsgstr \"Nem sikerült megnyitni a regisztrációs adatbázis kulcsot: %ld\"\n\n#: vncviewer/parameters.cxx:500\nmsgid \"Failed to write configuration file, can't obtain home directory path.\"\nmsgstr \"Nem sikerült kiírni a beállítófájlt, nem lehet megszerezni a saját könyvtár útvonalát.\"\n\n#: vncviewer/parameters.cxx:514\n#, c-format\nmsgid \"Failed to write configuration file, can't open %s: %s\"\nmsgstr \"Nem sikerült kiírni a beállítófájlt, nem lehet megnyitni: %s: %s\"\n\n#: vncviewer/parameters.cxx:559\nmsgid \"Failed to read configuration file, can't obtain home directory path.\"\nmsgstr \"Nem sikerült beolvasni a beállítófájlt, nem lehet megszerezni a saját könyvtár útvonalát.\"\n\n#: vncviewer/parameters.cxx:573\n#, c-format\nmsgid \"Failed to read configuration file, can't open %s: %s\"\nmsgstr \"Nem sikerült beolvasni a beállítófájlt, nem lehet megnyitni: %s: %s\"\n\n#: vncviewer/parameters.cxx:586 vncviewer/parameters.cxx:591\n#: vncviewer/parameters.cxx:616 vncviewer/parameters.cxx:629\n#: vncviewer/parameters.cxx:645\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"Nem sikerült a(z) %d. sort olvasni a(z) %s fájlban: %s\"\n\n#: vncviewer/parameters.cxx:592\nmsgid \"Line too long\"\nmsgstr \"Túl hosszú sor\"\n\n#: vncviewer/parameters.cxx:599\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"A(z) %s beállítófájl érvénytelen formátumú\"\n\n#: vncviewer/parameters.cxx:617\nmsgid \"Invalid format\"\nmsgstr \"Érvénytelen formátum\"\n\n#: vncviewer/parameters.cxx:630 vncviewer/parameters.cxx:646\nmsgid \"Invalid format or too large value\"\nmsgstr \"Érvénytelen formátum vagy túl nagy érték\"\n\n#: vncviewer/parameters.cxx:673\n#, c-format\nmsgid \"Unknown parameter %s on line %d in file %s\"\nmsgstr \"Ismeretlen %s paraméter a(z) %d. sornál a(z) %s fájlban\"\n\n#: vncviewer/vncviewer.cxx:100\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer %d-bit v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC megjelenítő: %d bites, %s verzió\\n\"\n\"Összeállítva: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC csapat és sokan mások (lásd: README.rst)\\n\"\n\"Nézze meg a https://www.tigervnc.org oldalt a TigerVNC információiért.\"\n\n#: vncviewer/vncviewer.cxx:127\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"A TigerVNC megjelenítő névjegye\"\n\n#: vncviewer/vncviewer.cxx:140\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Belső FLTK hiba. Kilépés.\"\n\n#: vncviewer/vncviewer.cxx:158 vncviewer/vncviewer.cxx:170\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Hiba az új TigerVNC megjelenítő indításakor: %s\"\n\n#: vncviewer/vncviewer.cxx:179\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"%d befejezési szignál érkezett. A TigerVNC megjelenítő most ki fog lépni.\"\n\n#: vncviewer/vncviewer.cxx:271 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"TigerVNC megjelenítő\"\n\n#: vncviewer/vncviewer.cxx:280\nmsgid \"Yes\"\nmsgstr \"Igen\"\n\n#: vncviewer/vncviewer.cxx:283\nmsgid \"Close\"\nmsgstr \"Bezárás\"\n\n#: vncviewer/vncviewer.cxx:288\nmsgid \"About\"\nmsgstr \"Névjegy\"\n\n#: vncviewer/vncviewer.cxx:291\nmsgid \"Hide\"\nmsgstr \"Elrejtés\"\n\n#: vncviewer/vncviewer.cxx:294\nmsgid \"Quit\"\nmsgstr \"Kilépés\"\n\n#: vncviewer/vncviewer.cxx:298\nmsgid \"Services\"\nmsgstr \"Szolgáltatások\"\n\n#: vncviewer/vncviewer.cxx:299\nmsgid \"Hide Others\"\nmsgstr \"Egyebek elrejtése\"\n\n#: vncviewer/vncviewer.cxx:300\nmsgid \"Show All\"\nmsgstr \"Összes megjelenítése\"\n\n#: vncviewer/vncviewer.cxx:309\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Fájl\"\n\n#: vncviewer/vncviewer.cxx:312\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"Új &kapcsolat\"\n\n#: vncviewer/vncviewer.cxx:324\nmsgid \"Could not create VNC home directory: can't obtain home directory path.\"\nmsgstr \"Nem sikerült létrehozni a VNC saját könyvtárát: nem lehet megszerezni a saját könyvtár útvonalát.\"\n\n#: vncviewer/vncviewer.cxx:329\n#, c-format\nmsgid \"Could not create VNC home directory: %s.\"\nmsgstr \"Nem sikerült létrehozni a VNC saját könyvtárát: %s\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:602 vncviewer/vncviewer.cxx:604\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"A -listen és a -via paraméterek összeférhetetlenek\"\n\n#: vncviewer/vncviewer.cxx:619\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Figyelés ezen a porton: %d\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"Távoli asztal megjelenítő\"\n\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Kapcsolódás VNC-kiszolgálóhoz és távoli asztal megjelenítése\"\n\n#: vncviewer/vncviewer.desktop.in.in:7\nmsgid \"tigervnc\"\nmsgstr \"tigervnc\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Folyamatos frissítések engedélyezése\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"letiltva\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"engedélyezve\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"%s kódolás használata\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"Nincs elég memória a keretpufferhez\"\n"
  },
  {
    "path": "po/id.po",
    "content": "# Indonesian translation of TigerVNC\n# Copyright (C) 2018 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Andika Triwidada <andika@gmail.com>, 2018, 2020-2022, 2024, 2025.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2026-01-07 16:08+0700\\n\"\n\"Last-Translator: Andika Triwidada <andika@gmail.com>\\n\"\n\"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\\n\"\n\"Language: id\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.8\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Terhubung ke soket %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Terhubung ke host %s port %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Gagal menyambung ke \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Nama desktop: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Host: %.80s port: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Ukuran: %d × %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Format piksel: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Pengkodean yang diminta: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Pengkodean yang terakhir dipakai: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Estimasi kecepatan saluran: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Versi protokol: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Metode keamanan: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Koneksi diputus oleh server sebelum sesi dapat dijalin.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Autentikasi gagal: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Gagal mengautentikasi dengan server. Alasan yang diberikan oleh server:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Throughput %d kbit/s - mengubah ke kualitas %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Throughput %d kbit/s - warna penuh sekarang difungsikan\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Throughput %d kbit/s - warna penuh sekarang dinonaktifkan\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Memakai format piksel %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Geometri yang dinyatakan tidak valid!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Mengurangi ukuran jendela agar pas di monitor saat ini\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"Tekan %sM untuk membuka menu konteks\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s - TigerVNC (papan tik diambil alih)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s - TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Menyesuaikan ukuran jendela untuk menghindari permintaan layar penuh yang tidak disengaja\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"Tekan %sEnter untuk keluar dari mode layar penuh\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"Kegagalan dalam mengambil alih kendali papan ketik\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"Tekan %s untuk melepaskan kendali papan tik dari sesi\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Tata letak layar yang tidak valid dihitung untuk permintaan ubah ukuran!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Keadaan yang tidak valid untuk emulasi 3 tombol\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Tidak ada kode pindai untuk tombol virtual yang diperluas 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Tidak ada kode pindai untuk tombol virtual 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Kode pindai tidak valid 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Tidak ada simbol untuk tombol virtual yang diperluas 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Tidak ada simbol untuk tombol virtual 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Gagal memperbarui keadaan LED papan tik: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Tidak ada simbol untuk kode tombol %d (dalam keadaan saat ini)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Gagal mendapatkan keadaan LED papan tik: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Gagal memperbarui keadaan LED papan tik\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Gagal mendapatkan konfigurasi monitor sistem\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Indeks monitor %d tidak ada\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"Opsi TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Batal\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"Kompresi\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"Pilih otomatis\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"Izinkan kompresi JPEG\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"Pengkodean yang disukai\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"Tingkat warna\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"Penuh\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"Sedang\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"Rendah\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"Sangat rendah\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"Tingkat kompresi ubahan\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"tingkat (0=buruk, 9=terbaik)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"Tingkat kualitas\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"kualitas (0=buruk, 9=terbaik)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"Keamanan\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"Enkripsi\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"Nihil\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS dengan sertifikat anonim\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS dengan sertifikat X509\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Path ke sertifikat CA X509\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Path ke berkas CRL X509\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"Otentikasi\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"VNC standar (tidak aman tanpa enkripsi)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Nama pengguna dan kata sandi (tidak aman tanpa enkripsi)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"Masukan\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Hanya melihat (mengabaikan tetikus dan papan ketik)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"Tetikus\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Emulasikan tombol tengah tetikus\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Tampilkan kursor lokal ketika tidak disediakan oleh server\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"Tipe kursor\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"Titik\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"Sistem\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"Papan Tik\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"Selalu kirim semua masukan papan tik dalam mode layar penuh\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"Papan Klip\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"Terima papan klip dari server\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"Juga atur pemilihan primer\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"Kirim papan klip ke server\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Kirim pilihan primer sebagai papan klip\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"Pintasan papan tik\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"Tombol pengubah untuk pintasan papan tik:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Shift\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Shift\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Option\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"Tampilan\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"Mode tampilan\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"Berjendela\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"Layar penuh pada monitor saat ini\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"Layar penuh di semua monitor\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Layar penuh pada monitor yang dipilih\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"Rupa-rupa\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Bersama (jangan putuskan pemirsa lain)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Minta untuk menyambungkan kembali saat kesalahan koneksi\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"Semua pintasan papan tik dinonaktifkan.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"Untuk melepaskan kendali papan tik dari sesi, tekan %s.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"Untuk meneruskan semua masukan papan tik ke sesi, tekan %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"Untuk menjungkitkan mode layar penuh, tekan %sEnter.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"Untuk membuka menu konteks sesi, tekan %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"Untuk mengirim kombinasi tombol yang mencakup %s langsung ke sesi, tekan %sSpasi, lepaskan bilah spasi tanpa melepaskan %s, dan tekan tombol yang diinginkan.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"Server VNC:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"Opsi...\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"Muat...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"Simpan sebagai...\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"Tentang...\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"Sambung\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Tak bisa memuat riwayat server:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Konfigurasi TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Pilih berkas konfigurasi TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Tak bisa memuat berkas konfigurasi yang ditentukan:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Simpan konfigurasi TigerVNC ke berkas\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s sudah ada. Apakah Anda ingin menimpa?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Tidak\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"Timpa\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Tak bisa menyimpan berkas konfigurasi yang ditentukan:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Tak bisa menyimpan konfigurasi baku:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Tak bisa menyimpan riwayat server:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"Tidak bisa menentukan path direktori keadaan VNC\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"Tak bisa membuka \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Gagal membaca baris %d dalam berkas \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"Baris terlalu panjang\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"Membuka berkas kata sandi gagal\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"Otentikasi VNC\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"Sambungan ini aman\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"Sambungan ini tidak aman\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"Nama Pengguna:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"Kata Sandi:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"Simpan sandi untuk penyambungan ulang\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Timbul galat tak terduga saat berkomunikasi dengan server:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"Putuskan &Sambungan\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"Layar &Penuh\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Mi&nimalkan\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Ubah ukuran &jendela ke sesi\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Kirim Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Sega&rkan layar\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Opsi...\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&Info koneksi...\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"Tentang &TigerVNC...\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"Informasi sambungan VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Jendela terdaftar untuk sentuhan, bukan gestur\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Gagal mengatur konfigurasi gestur (galat 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Gagal mendapatkan informasi gestur (error 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Tombol tetikus yang tidak valid %d, harus angka antara 1 dan 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Tombol 0x%x yang tidak ditangani - tidak dapat menghasilkan kejadian papan ketik.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Tidak bisa mendapatkan mask kejadian X Input 2 untuk jendela 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Jendela 0x%08lx tidak memiliki mask kejadian X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Window 0x%08lx memiliki lebih dari satu mask kejadian X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Kegagalan saat meng-grab perangkat %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Sambungkan ke server VNC dan tampilkan desktop jarak jauh\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC) adalah sistem tampilan jarak jauh yang memungkinkan Anda untuk melihat dan berinteraksi dengan lingkungan desktop virtual yang berjalan di komputer lain di jaringan. Menggunakan VNC, Anda dapat menjalankan aplikasi grafis pada mesin jarak jauh dan hanya mengirim tampilan dari aplikasi ini ke perangkat lokal Anda. Paket ini berisi klien yang akan memungkinkan Anda untuk terhubung ke desktop lain yang menjalankan server VNC. VNC adalah platform-independen dan mendukung berbagai sistem operasi dan arsitektur sebagai server dan klien.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC adalah versi VNC berkecepatan tinggi berdasarkan basis kode RealVNC 4 dan X.org. TigerVNC dimulai sebagai upaya pengembangan generasi berikutnya untuk TightVNC pada platform Unix dan Linux, tetapi terpisah dari proyek induknya pada awal 2009 sehingga TightVNC dapat fokus pada platform Windows. TigerVNC mendukung varian Pengodean ketat yang sangat dipercepat dengan penggunaan kodek JPEG libjpeg-turbo.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"Koneksi TigerVNC ke mesin CentOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"Koneksi TigerVNC ke mesin macOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"Koneksi TigerVNC ke mesin Windows\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"Tim TigerVNC\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Nama parameter terlalu besar\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"Parameter terlalu besar\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"Format tidak valid atau nilai terlalu besar\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"Gagal membuat kunci registry\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"Gagal menutup kunci registry\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Gagal menyimpan \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Gagal menghapus \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"Gagal membuka kunci registry\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Gagal membaca entri riwayat server %d: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Gagal membaca parameter \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"Tidak bisa menentukan path direktori konfig VNC\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"Tak bisa meng-enkode parameter\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Berkas konfigurasi %s berada dalam format yang tidak valid\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"Format tidak valid\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"Parameter tidak dikenal\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Mendapat pesan (0x%x) untuk jendela yang tidak tertangani\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Jendela tidak valid 0x%08lx ditentukan untuk pengambilan penunjuk\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Gagal membuat penangan sentuh: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Tak bisa melampirkan penangan kejadian ke jendela (galat 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Gagal mendapatkan data kejadian untuk kejadian X Input\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"Kejadian X Input untuk jendela yang tidak diketahui\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"Ekstensi X Input tidak tersedia.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2 (atau yang lebih baru) tidak tersedia.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2.2 (atau yang lebih baru) tidak tersedia. Gestur sentuh tidak akan didukung.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC v%s\\n\"\n\"Dibangun pada: %s\\n\"\n\"Hak Cipta (C) 1999-%d Tim TigerVNC dan banyak lainnya (lihat README.rst)\\n\"\n\"Lihat https://www.tigervnc.org untuk informasi tentang TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"Tentang TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Kesalahan FLTK internal. Keluar.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Mencoba untuk menyambung kembali?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"Kesalahan saat memulai koneksi baru: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"Sinyal pengakhiran %d telah diterima. TigerVNC sekarang akan keluar.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Ya\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Tutup\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"Tentang\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Sembunyikan\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Keluar\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Layanan\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Sembunyikan lainnya\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Tampilkan semua\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Berkas\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"Ko&neksi Baru\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Cara pakai: %s [parameter] [host][:displayNum]\\n\"\n\"            %s [parameter] [host][::port]\\n\"\n\"            %s [parameter] [unix socket]\\n\"\n\"            %s [parameter] -listen [port]\\n\"\n\"            %s [parameter] [.tigervnc file]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Opsi:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Menyatakan display X bagi jendela penampil\\n\"\n\"  -geometry geometri - Posisi awal dari jendela penampil TigerVNC utama. Lihat\\n\"\n\"                       halaman man untuk rincian.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Parameter dapat dinyalakan dengan -<param> atau dimatikan dengan -<param>=0\\n\"\n\"Parameter yang menerima nilai dapat dinyatakan sebagai -<param> <value>\\n\"\n\"Bentuk valid lain adalah <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Nama parameter tidak peka huruf besar kecil.  Parameternya adalah:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors sudah usang, atur FullScreenMode ke 'all' sebagai gantinya\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor usang, tata AlwaysCursor ke 1 dan CursorType ke 'Dot' sebagai pengganti\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc usang, harap baca 'man vncviewer' untuk migrasi ke path mana.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc usang, harap beralih ke lokasi %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"Tidak bisa membuat direktori konfig VNC \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"Tidak bisa menentukan path direktori data VNC\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"Tidak bisa membuat direktori data VNC \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"Tidak bisa membuat direktori keadaan VNC \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: Opsi tidak dikenal '%s'\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"Lihat '%s --help' untuk informasi lebih lanjut.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Argumen ekstra '%s'\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Parameter -listen dan -via tidak kompatibel\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Tidak bisa mendengarkan koneksi masuk\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Mendengarkan pada port %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Kegagalan saat menunggu koneksi VNC yang masuk:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Kegagalan menyiapkan tunnel terenkripsi:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"Penampil desktop jarak jauh\"\n"
  },
  {
    "path": "po/it.po",
    "content": "# Copyright (C) TigerVNC Team\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: TigerVNC 1.3.80\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2014-09-22 11:15+0000\\n\"\n\"Language: it\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:194\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:227\nmsgid \"About\"\nmsgstr \"Informazioni\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:103\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1086\nmsgid \"About TigerVNC viewer...\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:86\nmsgid \"About...\"\nmsgstr \"Informazioni...\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:704\nmsgid \"Accept clipboard from server\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:327\nmsgid \"Adjusting window size to avoid accidental full screen request\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:563\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Consenti la compressione JPEG:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1070\nmsgid \"Alt\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:648\nmsgid \"Authentication\"\nmsgstr \"Autenticazione\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:89\nmsgid \"Authentication cancelled\"\nmsgstr \"Autenticazione annullata\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:437\nmsgid \"Auto select\"\nmsgstr \"Selezione auto\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:651\n#, c-format\nmsgid \"Bad Name/Value pair on line: %d in file: %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Win32PixelBuffer.cxx:92\nmsgid \"BitBlt failed\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:91\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:221\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:83\nmsgid \"Cancel\"\nmsgstr \"Annulla\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:116\nmsgid \"CleanupSignalHandler called\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:222\nmsgid \"Close\"\nmsgstr \"Chiudi\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:499\nmsgid \"Color level\"\nmsgstr \"Livello del colore\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:421\n#, fuzzy\nmsgid \"Compression\"\nmsgstr \"Compressione SSH\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:96\nmsgid \"Connect\"\nmsgstr \"Connettiti\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1085\nmsgid \"Connection info...\"\nmsgstr \"Info connessione...\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:362\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:404\n#, c-format\nmsgid \"\"\n\"Could not convert the parameter-name %s to wchar_t* when reading from the \"\n\"Registry, the buffersize is to small.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:302\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:340\n#, c-format\nmsgid \"\"\n\"Could not convert the parameter-name %s to wchar_t* when writing to the \"\n\"Registry, the buffersize is to small.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:318\n#, c-format\nmsgid \"\"\n\"Could not convert the parameter-value %s to wchar_t* when writing to the \"\n\"Registry, the buffersize is to small.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:381\n#, c-format\nmsgid \"\"\n\"Could not convert the parameter-value for %s to utf8 char* when reading from \"\n\"the Registry, the buffer dest is to small.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:256\n#, c-format\nmsgid \"Could not create VNC home directory: %s.\"\nmsgstr \"Impossibile creare la home directory VNC: %s.\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:251\nmsgid \"Could not create VNC home directory: can't obtain home directory path.\"\nmsgstr \"\"\n\"Impossibile creare la home directory VNC: impossibile ottenere il percorso \"\n\"della home directory.\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:310\n#, c-format\nmsgid \"Could not encode the parameter-value %s when writing to the Registry.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:613\n#, c-format\nmsgid \"\"\n\"Could not read the line(%d) in the configuration file,the buffersize is to \"\n\"small.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Win32PixelBuffer.cxx:80\nmsgid \"CreateCompatibleDC failed\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1068\nmsgid \"Ctrl\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:550\nmsgid \"Custom compression level:\"\nmsgstr \"Livello di compressione:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:283\nmsgid \"\"\n\"Decoding: The size of the buffer dest is to small, it needs to be 1 byte \"\n\"bigger.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:172\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1088\nmsgid \"Dismiss menu\"\nmsgstr \"Ignora menu\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:778\n#, fuzzy\nmsgid \"Enable full-screen mode over all monitors\"\nmsgstr \"Abilita modalità schermo intero su tutti i monitor\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:469\nmsgid \"Enabling continuous updates\"\nmsgstr \"Abilitazione aggiornamenti continui\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:200\n#, c-format\nmsgid \"\"\n\"Encoding backslash: The size of the buffer dest is to small, it needs to be \"\n\"more than %d bytes bigger.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:214\n#, c-format\nmsgid \"\"\n\"Encoding escape sequence: The size of the buffer dest is to small, it needs \"\n\"to be more than %d bytes bigger.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:234\n#, c-format\nmsgid \"\"\n\"Encoding normal character: The size of the buffer dest is to small, it needs \"\n\"to be more than %d bytes bigger.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:595\nmsgid \"Encryption\"\nmsgstr \"Crittografia\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:503\n#, c-format\nmsgid \"Error(%d) closing key:  Software\\\\TigerVNC\\\\vncviewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:455\n#, c-format\nmsgid \"Error(%d) closing key: Software\\\\TigerVNC\\\\vncviewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:434\n#, c-format\nmsgid \"Error(%d) creating key: Software\\\\TigerVNC\\\\vncviewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:471\n#, c-format\nmsgid \"Error(%d) opening key: Software\\\\TigerVNC\\\\vncviewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:373\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:415\n#, c-format\nmsgid \"Error(%d) reading %s from Registry.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:348\n#, c-format\nmsgid \"Error(%d) writing %d(REG_DWORD) to Registry.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:326\n#, c-format\nmsgid \"Error(%d) writing %s(REG_SZ) to Registry.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OSXPixelBuffer.cxx:50\n#: /home/ossman/devel/tigervnc/vncviewer/FLTKPixelBuffer.cxx:33\nmsgid \"Error: Not enough memory for framebuffer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/X11PixelBuffer.cxx:69\nmsgid \"Error: couldn't find suitable pixmap format\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/X11PixelBuffer.cxx:60\nmsgid \"Error: display lacks pixmap format for default depth\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/X11PixelBuffer.cxx:78\nmsgid \"Error: only true colour displays supported\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1056\nmsgid \"Exit viewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:588\n#, fuzzy\nmsgid \"Failed to read configuration file, can't obtain home directory path.\"\nmsgstr \"\"\n\"Impossibile creare la home directory VNC: impossibile ottenere il percorso \"\n\"della home directory.\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:602\n#, c-format\nmsgid \"Failed to read configuration file, can't open %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:621\n#, c-format\nmsgid \"Failed to read line %d in file %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:528\n#, fuzzy\nmsgid \"Failed to write configuration file, can't obtain home directory path.\"\nmsgstr \"\"\n\"Impossibile creare la home directory VNC: impossibile ottenere il percorso \"\n\"della home directory.\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:542\n#, c-format\nmsgid \"Failed to write configuration file, can't open %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:526\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:538\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:551\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Errore di raccolta della tastiera\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:563\nmsgid \"Failure grabbing mouse\"\nmsgstr \"Errore di raccolta del mouse\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:512\nmsgid \"Full (all available colors)\"\nmsgstr \"Pieno (tutti i colori disponibili)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1059\nmsgid \"Full screen\"\nmsgstr \"Schermo intero\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:770\n#, fuzzy\nmsgid \"Full-screen mode\"\nmsgstr \"Modalità schermo intero\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:230\nmsgid \"Hide\"\nmsgstr \"Nascondi\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:238\nmsgid \"Hide Others\"\nmsgstr \"Nascondi altri\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:177\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:690\nmsgid \"Input\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:510\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Errore FLTK interno. Uscita in corso.\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:384\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:106\nmsgid \"Invalid geometry specified!\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Invalid parameter name on line: %d in file: %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:797\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:204\n#, fuzzy, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Utilizzo codifica %s\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:631\n#, c-format\nmsgid \"\"\n\"Line 1 in file %s\\n\"\n\"must contain the TigerVNC configuration file identifier string:\\n\"\n\"\\\"%s\\\"\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:209\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:478\n#, c-format\nmsgid \"Listening on port %d\\n\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:69\nmsgid \"Load...\"\nmsgstr \"Carica...\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:526\nmsgid \"Low (64 colors)\"\nmsgstr \"Basso (64 colori)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:519\nmsgid \"Medium (256 colors)\"\nmsgstr \"Medio (256 colori)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:725\n#, fuzzy\nmsgid \"Menu key\"\nmsgstr \"Tasto di menu a comparsa\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:791\nmsgid \"Misc.\"\nmsgstr \"Varie\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1026\n#, c-format\nmsgid \"Multiple characters given for key code %d (0x%04x): '%s'\"\nmsgstr \"Caratteri multipli forniti per il codice chiave %d (0x%04x): '%s'\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:218\nmsgid \"No\"\nmsgstr \"No\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:688\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:690\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:701\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:765\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:739\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:703\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:606\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:659\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:727\nmsgid \"None\"\nmsgstr \"Nessuno\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:220\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:88\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:74\nmsgid \"Opening password file failed\"\nmsgstr \"Apertura del file di password non riuscita\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1084\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:64\nmsgid \"Options...\"\nmsgstr \"Opzioni...\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:463\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:464\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:722\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:87\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:102\nmsgid \"Password:\"\nmsgstr \"Password:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:625\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Percorso del certificato X509 CA\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:632\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Percorso del file X509 CRL\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:188\n#, fuzzy, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Utilizzo del formato pixel %s\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:449\nmsgid \"Preferred encoding\"\nmsgstr \"Codifica preferita\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:214\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:233\nmsgid \"Quit\"\nmsgstr \"Esci\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1082\nmsgid \"Refresh screen\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:199\n#, fuzzy, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Codifica preferita\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:749\n#, fuzzy\nmsgid \"Resize remote session on connect\"\nmsgstr \"Ridimensiona la sessione remota alla finestra locale\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:762\nmsgid \"Resize remote session to the local window\"\nmsgstr \"Ridimensiona la sessione remota alla finestra locale\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1062\nmsgid \"Resize window to session\"\nmsgstr \"Ridimensiona la finestra alla sessione\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:74\nmsgid \"Save As...\"\nmsgstr \"Salva con nome...\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:741\nmsgid \"Screen\"\nmsgstr \"Schermo\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:580\nmsgid \"Security\"\nmsgstr \"Sicurezza\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Win32PixelBuffer.cxx:83\nmsgid \"SelectObject failed\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1075\n#, c-format\nmsgid \"Send %s\"\nmsgstr \"Invia %s\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1080\nmsgid \"Send Ctrl-Alt-Del\"\nmsgstr \"Invia Ctrl-Alt-Del\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:710\nmsgid \"Send clipboard to server\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:716\nmsgid \"Send primary selection and cut buffer as clipboard\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:237\nmsgid \"Services\"\nmsgstr \"Servizi\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:319\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"Impostazioni dimensioni desktop non riuscita: %d\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:799\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:239\nmsgid \"Show All\"\nmsgstr \"Mostra tutto\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:805\nmsgid \"Show dot when no cursor\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:182\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:665\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"VNC standard (non protetto senza crittografia)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:618\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS con certificati X509\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:612\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS con certificati anonimi\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:448\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:497\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:561\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:701\n#, c-format\nmsgid \"The parameterArray contains a object of a invalid type at line %d.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:664\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:680\n#, c-format\nmsgid \"The value of the parameter %s on line %d in file %s is invalid.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:539\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Velocità effettiva %d kbit/s - passaggio alla qualità %d\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:561\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now %s\"\nmsgstr \"Velocità effettiva %d kbit/s - tutti i colori sono ora %s\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:210\nmsgid \"TigerVNC Viewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:80\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer %d-bit v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.txt)\\n\"\n\"See http://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1004\n#, c-format\nmsgid \"Unknown FLTK key code %d (0x%04x)\"\nmsgstr \"Codice chiave FLTK sconosciuto %d (0x%04x)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:878\n#, c-format\nmsgid \"Unknown decimal separator: '%s'\"\nmsgstr \"Separatore decimale sconosciuto: '%s'\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:271\n#, fuzzy, c-format\nmsgid \"Unknown escape sequence at character %d\"\nmsgstr \"Separatore decimale sconosciuto: '%s'\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:430\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:437\n#, fuzzy\nmsgid \"Unknown rect encoding\"\nmsgstr \"Utilizzo codifica %s\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:429\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:436\n#, c-format\nmsgid \"Unknown rect encoding %d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:671\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Nome utente e password (non protetti senza crittografia)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:99\nmsgid \"Username:\"\nmsgstr \"Nome utente:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:573\n#, c-format\nmsgid \"Using %s encoding\"\nmsgstr \"Utilizzo codifica %s\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/X11PixelBuffer.cxx:80\n#, c-format\nmsgid \"Using default colormap and visual, %sdepth %d.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:620\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Utilizzo del formato pixel %s\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:42\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"VNC Viewer: dettagli di connessione\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:57\n#, fuzzy\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"VNC Viewer: dettagli di connessione\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:86\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:96\nmsgid \"VNC authentication\"\nmsgstr \"Autenticazione VNC\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1176\n#, fuzzy\nmsgid \"VNC connection info\"\nmsgstr \"Info connessione...\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:49\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:54\nmsgid \"VNC server:\"\nmsgstr \"Server VNC:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:533\nmsgid \"Very low (8 colors)\"\nmsgstr \"Molto bassa (8 colori)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:698\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:219\nmsgid \"Yes\"\nmsgstr \"Sì\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:111\n#, c-format\nmsgid \"connected to host %s port %d\"\nmsgstr \"connesso all'host %s porta %d\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:563\nmsgid \"disabled\"\nmsgstr \"disabilitato\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:563\nmsgid \"enabled\"\nmsgstr \"abilitato\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:556\nmsgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\nmsgstr \"livello (1=veloce, 6=ottimale [4-6 sono raramente utili])\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:569\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"qualità (0=scadente, 9=ottimale)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Win32PixelBuffer.cxx:63\nmsgid \"unable to create DIB section\"\nmsgstr \"\"\n\n#, fuzzy\n#~ msgid \"\"\n#~ \"Desktop name: %.80s\\n\"\n#~ \"Host: %.80s port: %d\\n\"\n#~ \"Size: %d x %d\\n\"\n#~ \"Pixel format: %s\\n\"\n#~ \"(server default %s)\\n\"\n#~ \"Requested encoding: %s\\n\"\n#~ \"Last used encoding: %s\\n\"\n#~ \"Line speed estimate: %d kbit/s\\n\"\n#~ \"Protocol version: %d.%d\\n\"\n#~ \"Security method: %s\\n\"\n#~ msgstr \"\"\n#~ \"Nome del desktop: %.80s \\n\"\n#~ \"Dimensioni: %d x %d \\n\"\n#~ \"Formato dei pixel: %s \\n\"\n#~ \"(impostazione predefinita del server %s) \\n\"\n#~ \"Codifica richiesta: %s \\n\"\n#~ \"Ultima codifica utilizzata: %s \\n\"\n#~ \"Stima velocità linea: %d kbit/s\\n\"\n"
  },
  {
    "path": "po/ka.po",
    "content": "# Georgian translation for tigervnc\n# Copyright (C) 2022 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2022-2025\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2026-01-24 10:48+0100\\n\"\n\"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\\n\"\n\"Language-Team: Georgian <(nothing)>\\n\"\n\"Language: ka\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.8\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"მიერთება სოკეტთან %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"მიერთებულია ჰოსტთან %s პორტი %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"%s-თან მიერთების შეცდომა:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"სამუშაო მაგიდის სახელი: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"პოსტი: %.80s პორტი: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"ზომა: %d x %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"პიქსელის ფორმატი: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"მოთხოვნილი კოდირება: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"ბოლოს გამოყენებული კოდირება: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"კავშირის დაახლოებითი სიჩქარე: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"პროტოკოლის ვერსია: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"უსაფრთხოების მეთოდი: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"კავშირი გაითიშა სერვერის მიერ სანამ სესია დადგებოდა.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"ავთენტიკაციის შეცდომა: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"სერვერთან ავთენტიკაცია ჩავარდა. სერვერის მიერ მოწოდებული მიზეზია:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"გამტარობა %d კბიტ/წმ - ხარისხი შეიცვლება: %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"გამტარობა %d კბიტ/წმ - ფერთა სრული გამა ჩართულია\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"გამტარობა %d კბიტ/წმ - ფერთა სრული გამა გამორთულია\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"პიქსელის ფორმატი: %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"მითითებული გეომეტრია არასწორია!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"ფანჯრის ზომის შეცვლა მიმდინარე ეკრანზე დასატევად\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"კონტექსტური მენიუს გასახსნელად დააწექით: %sM\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s - TigerVNC (კლავიატურა ჩაჭერილია)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s - TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"ეკრანის ზომის მორგება შემთხვევით სრულ ეკრანზე გაშლის თავიდან ასარიდებლად\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"სრულეკრანიანი რეჟიმიდან გასასვლელად დააწექით %sEnter\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"კლავიატურის მართვის ჩაჭერის შეცდომა\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"კლავიატურის კონტროლის სესიიდან გასათავისუფლებლად დააწექით %s\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"ზომის შესაცვლელად გამოთვლილი ფანჯრების განლაგება არასწორია!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"არასწორი მდგომარეობა 3 ღილაკის ემულაციისთვის\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"გაფართოებული ვირტუალური ღილაკისთვის სკანირების კოდი არ არსებობს: 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"სკანირების კოდი ვირტუალური ღილაკისთვის არსებობს: 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"სკანირების არასწორი კოდი: 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"გაფართოებული ვირტუალური ღილაკის სიმბოლო ნაპოვნი არაა:0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"ვირტუალური ღილაკის სიმბოლო ნაპოვნი არაა: 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"კლავიატურის LED-ის მდგომარეობის განახლების შეცდომა: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"ღილაკის კოდისთვის %d (მიმდინარე მდგომარეობაში) სიმბოლო აღმოჩენილი არაა\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"კლავიატურის LED-ის მდგომარეობის მიღების შეცდომა: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"კლავიატურის LED-ის მდგომარეობის განახლების შეცდომა\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"სისტემური მონიტორის ინფორმაციის მიღება შეუძლებელია\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"ეკრანის ინდექსი %d არ არსებობს\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"TigerVNC-ის მორგება\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"გაუქმება\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"დიახ\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"შეკუმშვა\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"ავტომატური არჩევა\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"JPEG შეკუმშვის ჩართვა\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"სასურველი კოდირებ\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"ფერის დონე\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"მთლიანი\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"საშუალო\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"დაბალი\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"ძალიან დაბალი\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"მორგებული შეკუმშვის დონე\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"დონე (0=სწრაფი, 9=საუკეთესო)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"ხარისხის დონე\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"ხარისხი (0=ცუდი, 9=საუკეთესო)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"უსაფრთხოება\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"დაშიფრვა\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"არაფერი\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS ანონიმური სერტიფიკატებით\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS X509 სერტიფიკატებით\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"X509 CA სერტიფიკატის ბილიკი\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"X509 CRL ფაილის ბილიკი\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"ავთენტიფიკაცია\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"VNC-ის სტანდარტი (დაუცველი, დაშიფვრის გარეშე)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"მომხმარებელი და პაროლი (დაუცველი, დაშიფვრის გარეშე)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"შეყვანა\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"მხოლოდ ნახვა (თაგუნას და კლავიატურის იგნორირება)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"თაგუნა\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"თაგუნას შუა ღილიკის ემულაცია\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"ლოკალური კურსორის ჩვენება, როცა ის მოწოდებული არაა სერვერის მიერ\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"კურსორის ტიპი\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"წერტილი\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"სისტემა\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"კლავიატურა\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"კლავიატურის ყველა ღილაკის გაგზავნა სრულეკრანიან რეჟიმში\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"გაცვლის ბუფერი\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"სერვერიდან გაცვლის ბუფერის მიღება\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"ძირითადი არჩევანის დაყენება\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"გაცვლის ბაფერის სერვერზე გაგზავნა\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"ძირითადი არჩევანის გაცვლის ბუფერით გაგზავნა\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"კლავიატურის მალსახმობები\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"მოდიფიკატორი ღილაკები კლავიატურის მალსახმობისთვის:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Shift\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Shift\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ პარამეტრი\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"ჩვენება\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"ჩვენების რეჟიმი\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"ფანჯარაში\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"სრულ ეკრანზე მიმდინარე მონიტორზე\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"სრულ ეკრანზე ყველა მონიტორზე\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"სრულ ეკრანზე მონიშნულ მონიტორ(ებ)-ზე\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"სხვადასხვა\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"გაზიარებული (სხვა მაყურებლები არ გამოიყრებიან)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"კავშირის დაკარგვისას თავიდან შეერთების შესახებ კითხვა\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"ყველა კლავიატურის მალსახმობი გამორთულია.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"კლავიატურის კონტროლის სესიიდან გასათავისუფლებლად დააწექით %s.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"კლავიატურის ყველა ღილაკის დაჭერის სესიაზე გადასაცემად დააჭირეთ %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"სრულეკრანიანი რეჟიმის გადასართავად დააწექით %sEnter.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"სესიის კონტექსტური მენიუს გასახსნელად დააწექით: %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"%s-ის შემცველი ღილაკების კომბინაციის პირდაპირ სესიაში გასაგზავნად დააჭირეთ %sჰაეს, აუშვით ჰარეს %s-ის გაშვების გარეშე და დააჭირეთ სასურველ ღილაკს.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"VNC სერვერი:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"პარამეტრები...\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"ჩატვირთვა...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"შენახვა, როგორც...\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"შესახებ...\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"დაკავშირება\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"სერვერის ისტორიის ჩატვირთვის შეცდომა:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"TigerVNC-ის კონფიგურაცია (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"აირჩიეთ TigerVNC-ის კონფიგურაციის ფაილი\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"კონფიგურაციის მითითებული ფაილის ჩატვირთვა შეუძლებელია:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"TigerVNC-ის კონფიგურაციის ფაილის შენახვა\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"'%s' უკვე არსებობს. გნებავთ გადააწეროთ?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"არა\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"თავზე გადაწერა\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"კონფიგურაციის მითითებული ფაილის შენახვა შეუძლებელია:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"ნაგულისხმები კონფიგურაციის შენახვა შეუძლებელია:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"სერვერის ისტორიის შენახვა შეუძლებელია:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"VNC-ის მდგომარეობის საქაღალდის ბილიკის დადგენა შეუძლებელია\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"\\\"%s\\\"-ის გახსნის შეცდომა\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"შეუძლებელია %d-ე ხაზის წაკითხვა ფაილში \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"ხაზი ძალიან გრძელია\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"ფაილის გახსნის შეცდომა\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"VNC ავთენტიფიკაცია\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"შეერთება დაცულია\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"შეერთება დაუცველია\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"მომხმარებელი:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"პაროლი:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"პაროლის შენახვა თავიდან დასაკავშირებლად\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"გაუთვალისწინებელი შეცდომა სერვერთან დაკავშირებისას:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"&გათიშვა\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&მთელს ეკრანზე\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"&მინიმიზაცია\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"&ფანჯრის ზომის სესიის ზომამდე შეცვლა\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Ctrl-Alt-&Del-ის გაგზავნა\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&ეკრანის განახლება\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&მორგება...\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&შეერთების ინფორმაცია...\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"&TigerVNC-ის შესახებ...\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"VNC-ის შეერთების ინფორმაცია\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"ფანჯარა რეგისტრირებულია შესახებად, ჟესტების მაგიერ\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"ჟესტის კონფიგურაციის მიღება ჩავარდა (შეცდომა 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"ჟესტის ინფორმაციის მიღება ჩავარდა (შეცდომა 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"არასწორი თაგუნას ღილაკი %d. უნდა იყოს რიცხვი შუალედიდან 1-7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"უცნობი ღილაკი 0x%x - კლავიატურის მოვლენის გენერაცია შეუძლებელია.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"X Input 2-ის მოვლენის ნიღბის მიღება შეუძლებელია ფანჯრისთვის 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"ფანჯარას 0x%08lx X Input 2 მოვლენის ნიღაბი არ აქვს\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"ფანჯარას 0x%08lx ერთზე მეტი X Input 2 მოვლენის ნიღაბი აქვს\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"მოწყობილობის ჩაჭერის შეცდომა: %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"დაუკავშირდით VNC სერვერს და აჩვენეთ დაშორებული ეკრანი\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"TigerVNC-ის კავშირი CentOS-ის მანქანასთან\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"TigerVNC-ის კავშირი macOS-ის მანქანასთან\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"TigerVNC-ის კავშირი Windows-ის მანქანასთან\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"TigerVNC-ის გუნდი\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"პარამეტრის სახელი ძალიან დიდია\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"პარამეტრი ძალიან დიდია\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"არასწორი ფორმატი ან ძალიან დიდი მნიშვნელობა\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"რეესრის გასაღების შექმნის შეცდომა\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"რეესტრის გასაღების დახურვის შეცდომა\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"\\\"%s'-ის შენახვის შეცდომა: %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"\\\"%s\\\"-ის წაშლის შეცდომა: %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"რეესტრის გასაღების გახსნის შეცდომა\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"სერვერის ისტორიის ჩანაწერის (%d) წაკითხვა შეუძლებელია: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"\\\"%s\\\"-ის წაკითხვის შეცდომა: %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"VNC-ის კონფიგურაციის საქაღალდის ბილიკის დადგენა შეუძლებელია\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"პარამეტრის კოდირების შეცდომა\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"კონფიგურაციის არასწორი ფორმატი ფაილისთვის : %s\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"არასწორი ფორმატი\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"უცნობი პარამეტრი\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"მიღებულია შეტყობინება (0x%x) დაუმუშავებელი ფანჯრისთვის\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"არასწორი ფანჯარა 0x%08lx მაჩვენებლის ჩასაჭერად\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"ვერ შევქმენი შეხების დამმუშავებელი: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"მოვლენების დამმუშავებლის ფანჯარაზე მიმაგრება შეუძლებელია (შეცდომა 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"ჩავარდა მოვლენის მონაცემების მიღება X-ის შეყვანის მოვლენისთვის\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"X Input-ის მოვლენა უცნობი ფანჯრისთვის\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"X Input-ის გაფართოება მიუწვდომელია.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2 (ან უფრო ახალი) მიუწვდომელია.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2.2 (ან უფრო ახალი) მიუწვდომელია. შეხების ჟესტები მხარდაუჭერელია.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC v%s\\n\"\n\"აგების თარიღი: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC-ის გუნდი და მრავალი სხვა (იხ README.rst)\\n\"\n\"მეტი ინფორმაციისთვის TigerVNC-ის შესახებ იხილეთ https://www.tigervnc.org .\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"TigerVNC-ის შესახებ\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"FLTK-ის შიდა შეცდომა. პროგრამა ასრულებს მუშაობას.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"ვცადო თავიდან დაკავშირება?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"ახალი კავშირის გაშვების შეცდომა: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"მიღებულია შეწყვეტის სიგნალი %d. TigerVNC მუშაობას დაასრულებს.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"დიახ\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"დახურვა\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"შესახებ\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"დამალვა\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"გასვლა\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"სერვისები\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"სხვების დამალვა\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"ყველას ჩვენება\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&ფაილი\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&ახალი შეერთება\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"გამოყენება: %s [პარამეტრები] [ჰოსტი][:ეკრანისნომ]\\n\"\n\"       %s [პარამეტრები] [ჰოსტი][::პორტი]\\n\"\n\"       %s [პარამეტრები] [unix სოკეტი]\\n\"\n\"       %s [პარამეტრები] -listen [პორტი]\\n\"\n\"       %s [პარამეტრები] [.tigervnc ფაილი]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"პარამეტრები:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - მიუთითებს X-ის ეკრანს მნახველის ფანჯრისთვის\\n\"\n\"  -geometry geometry - TigerVNC-ის მთავარი ფანჯრის საწყისი მდებარეობა. დეტალებისთვის\\n\"\n\"                       იხილეთ სახელმძღვანელო.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors მოძველებულია. სამაგიეროდ დააყენეთ FullScreenMode მნიშვნელობაზე 'all'\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor მოძველებულია. სამაგიეროდ დააყენეთ AlwaysCursor მნიშვნელობაზე 1 და CursorType მნიშვნელობაზე 'Dot'\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc მოძველებულია. სანახავად, სად მოხდა მიგრაცია, იხილეთ 'man vncviewer'.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc მოძველებულია. გადაერთეთ მდებარეობაზე %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"ვერ შევქმენი VNC-ის კონფიგურაციის საქაღალდე \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"VNC-ის მონაცემების საქაღალდის ბილიკის დადგენა შეუძლებელია\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"ვერ შევქმენი VNC-ის მონაცემების საქაღალდე \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"VNC-ის მდგომარეობის საქაღალდის \\\"%s\\\" შექმნა შეუძლებელია: %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: უცნობი პარამეტრი '%s'\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"მეტი ინფორმაციისთვის იხილეთ '%s --help'.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: დამატებითი არგუმენტი '%s'\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"პარამეტრები -listen და -via თავსებადი არაა\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"შემომავალი კავშირებისთვის მოსმენა შეუძლებელია\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"ვუსმენ პორტზე %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"VNC-ის შემომავალი შეერთების ლოდინის შეცდომა:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"შეცდომა დაშიფრული გვირაბის მორგებისას:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"დაშორებული სამუშაო მაგიდის კლიენტი\"\n\n#, c-format\n#~ msgid \"(server default %s)\"\n#~ msgstr \"(სერვერის ნაგულისხმები %s)\"\n\n#, c-format\n#~ msgid \"SetDesktopSize failed: %d\"\n#~ msgstr \"SetDesktopSize-ის შეცდომა: %d\"\n\n#~ msgid \"Invalid SetColourMapEntries from server!\"\n#~ msgstr \"არასწორი SetColourMapEntries სერვერიდან!\"\n\n#, c-format\n#~ msgid \"Invalid configuration specified for %s\"\n#~ msgstr \"%s-ის მითითებული კონფიგურაცია არასწორია\"\n\n#, c-format\n#~ msgid \"Invalid monitor index '%s'\"\n#~ msgstr \"ეკრანის არასწორი ინდექსი: '%s'\"\n\n#, c-format\n#~ msgid \"Unexpected character '%c'\"\n#~ msgstr \"მოულოდნელი სიმბოლო '%c'\"\n\n#~ msgid \"Pass system keys directly to server (full screen)\"\n#~ msgstr \"სისტემური ღილაკების პირდაპირ სერვერზე გაგზავნა (სრულ ეკრანზე)\"\n\n#~ msgid \"Menu key\"\n#~ msgstr \"მენიუს ღილაკი\"\n\n#~ msgid \"VNC viewer: Connection details\"\n#~ msgstr \"VNC-ის დათვალიერება: კავშირის დეტალები\"\n\n#, c-format\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Send %s\"\n#~ msgstr \"%s-ის გაგზავნა\"\n\n#~ msgid \"TigerVNC viewer\"\n#~ msgstr \"TigerVNC-ის დამთვალიერებელი\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"მონიტორის სახელის მიღება შეუძლებელია X11 Randr-ის არარსებობის გამო\"\n\n#, c-format\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"CRTC %d-ის შესახებ ინფორმაციის მიღება შეუძლებელია\"\n\n#, c-format\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"CRTC %d-ის %d გამოტანის შესახებ ინფორმაციის მიღება შეუძლებელია\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"ეკრანი\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"შეერთებისას დაშორებული ეკრანის ზომის შეცვლა\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"დაშორებული ეკრანის ადგილობრივ ფანჯრის ზომამდე შეცვლა\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"სრული ეკრანის ჩართვა\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"სხვ.\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"კურსორის არქონის შემთხვევაში წერტილის ჩვენება\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"კლავიატურის LED-ის მდგომარეობის განახლების შეცდომა: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"ღილაკის დაწოლის კოდი მითითებული არაა\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"პარამეტრის უცნობ ტიპი\"\n"
  },
  {
    "path": "po/ko.po",
    "content": "# Korean Translation for TigerVNC.\n# Copyright (C) 2009-2023 TigerVNC Team and many others (see README.rst)\n# This file is distributed under the same license as the tigervnc package.\n# JiYoon Kwon <bbkjo0123@gmail.com>, 2023.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.12.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2022-12-15 16:35+0100\\n\"\n\"PO-Revision-Date: 2023-08-15 23:51+0900\\n\"\n\"Last-Translator: JiYoon Kwon <bbkjo0123@gmail.com>\\n\"\n\"Language-Team: Korean <translation-team-ko@googlegroups.com>\\n\"\n\"Language: ko\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.3.2\\n\"\n\n#: vncviewer/CConn.cxx:103\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"소켓 %s에 연결됨\"\n\n#: vncviewer/CConn.cxx:110\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"호스트 %s의 포트 %d와 연결됨\"\n\n#: vncviewer/CConn.cxx:114\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"\\\"%s\\\"와 연결 실패: \\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:159\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"데스크톱 이름: %.80s\"\n\n#: vncviewer/CConn.cxx:164\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"호스트: %.80s 포트: %d\"\n\n#: vncviewer/CConn.cxx:169\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"크기: %d x %d\"\n\n#: vncviewer/CConn.cxx:177\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"픽셀 형식: %s\"\n\n#: vncviewer/CConn.cxx:184\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(서버 기본값 %s)\"\n\n#: vncviewer/CConn.cxx:189\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"요청된 인코딩: %s\"\n\n#: vncviewer/CConn.cxx:194\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"최근 사용된 인코딩: %s\"\n\n#: vncviewer/CConn.cxx:199\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"회선 속도 측정: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"프로토콜 버전: %d.%d\"\n\n#: vncviewer/CConn.cxx:209\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"보안 방식: %s\"\n\n#: vncviewer/CConn.cxx:270 vncviewer/CConn.cxx:272\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"세션이 생성되기 전 서버에서 연결을 끊었습니다.\"\n\n#: vncviewer/CConn.cxx:332\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"데스크톱 사이즈 설정 실패: %d\"\n\n#: vncviewer/CConn.cxx:404\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"서버에서 잘못된 SetColourMapEntries를 설정했습니다!\"\n\n#: vncviewer/CConn.cxx:512\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"처리량 %d kbit/s - 품질을 %d로 변경 중\"\n\n#: vncviewer/CConn.cxx:534\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"처리량 %d kbit/s - 높은 색상 수준으로 변경 가능\"\n\n#: vncviewer/CConn.cxx:537\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"처리량 %d kbit/s - 높은 색상 수준으로 변경 불가\"\n\n# 사용 중..? 사용?\n#: vncviewer/CConn.cxx:563\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"%s 픽셀 형식을 사용\"\n\n# geometry를 해상도라고 번역\n#: vncviewer/DesktopWindow.cxx:145\nmsgid \"Invalid geometry specified!\"\nmsgstr \"잘못된 해상도가 지정되었습니다!\"\n\n#: vncviewer/DesktopWindow.cxx:166\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"현재 모니터에 맞게 창 크기 축소\"\n\n#: vncviewer/DesktopWindow.cxx:648\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"실수로 최대화 요청을 하지 않도로 창 크기를 조정\"\n\n#: vncviewer/DesktopWindow.cxx:696\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"콘텍스트 메뉴를 열려면 %s를 누르십시오\"\n\n#: vncviewer/DesktopWindow.cxx:1083 vncviewer/DesktopWindow.cxx:1091\n#: vncviewer/DesktopWindow.cxx:1111\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"키보드 점유 실패\"\n\n#: vncviewer/DesktopWindow.cxx:1401\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"크기 재조정 요청에 대해 잘못된 화면 레이아웃이 계산되었습니다!\"\n\n#: vncviewer/EmulateMB.cxx:226 vncviewer/EmulateMB.cxx:289\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"유효하지 않은 3 버튼 에뮬레이션 상태\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:52\n#: vncviewer/MonitorIndicesParameter.cxx:105\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"시스템 모니터 환경 설정을 가져오는 데 실패함\"\n\n# geometry를 해상도라고 번역\n#: vncviewer/MonitorIndicesParameter.cxx:83\n#, c-format\nmsgid \"Invalid configuration specified for %s\"\nmsgstr \"%s에 대해 유효하지 않은 환경 설정\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:91\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"모니터 인덱스 %d가 존재하지 않음\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:169\n#: vncviewer/MonitorIndicesParameter.cxx:189\n#, c-format\nmsgid \"Invalid monitor index '%s'\"\nmsgstr \"유효하지 않은 모니터 인덱스 '%s'\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:177\n#, c-format\nmsgid \"Unexpected character '%c'\"\nmsgstr \"예상치 못한 문자 '%c'\"\n\n#: vncviewer/OptionsDialog.cxx:63\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"VNC 뷰어: 연결 설정\"\n\n#: vncviewer/OptionsDialog.cxx:89 vncviewer/ServerDialog.cxx:108\n#: vncviewer/vncviewer.cxx:417\nmsgid \"Cancel\"\nmsgstr \"취소\"\n\n#: vncviewer/OptionsDialog.cxx:94 vncviewer/vncviewer.cxx:416\nmsgid \"OK\"\nmsgstr \"확인\"\n\n#: vncviewer/OptionsDialog.cxx:484\nmsgid \"Compression\"\nmsgstr \"압축\"\n\n#: vncviewer/OptionsDialog.cxx:501\nmsgid \"Auto select\"\nmsgstr \"자동 선택\"\n\n#: vncviewer/OptionsDialog.cxx:516\nmsgid \"Preferred encoding\"\nmsgstr \"선호되는 인코딩\"\n\n#: vncviewer/OptionsDialog.cxx:574\nmsgid \"Color level\"\nmsgstr \"색상 수준\"\n\n#: vncviewer/OptionsDialog.cxx:585\nmsgid \"Full\"\nmsgstr \"높음\"\n\n#: vncviewer/OptionsDialog.cxx:592\nmsgid \"Medium\"\nmsgstr \"중간\"\n\n#: vncviewer/OptionsDialog.cxx:599\nmsgid \"Low\"\nmsgstr \"낮음\"\n\n#: vncviewer/OptionsDialog.cxx:606\nmsgid \"Very low\"\nmsgstr \"매우 낮음\"\n\n#: vncviewer/OptionsDialog.cxx:624\nmsgid \"Custom compression level:\"\nmsgstr \"사용자 정의 압축 수준:\"\n\n#: vncviewer/OptionsDialog.cxx:630\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"품질(0=나쁨, 9=좋음)\"\n\n#: vncviewer/OptionsDialog.cxx:637\nmsgid \"Allow JPEG compression:\"\nmsgstr \"JPEG 압축 허용:\"\n\n#: vncviewer/OptionsDialog.cxx:643\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"품질(0=나쁨, 9=좋음)\"\n\n#: vncviewer/OptionsDialog.cxx:654\nmsgid \"Security\"\nmsgstr \"보안\"\n\n#: vncviewer/OptionsDialog.cxx:676\nmsgid \"Encryption\"\nmsgstr \"암호화\"\n\n#: vncviewer/OptionsDialog.cxx:687 vncviewer/OptionsDialog.cxx:750\n#: vncviewer/OptionsDialog.cxx:854\nmsgid \"None\"\nmsgstr \"없음\"\n\n#: vncviewer/OptionsDialog.cxx:694\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"익명 인증서가 있는 TLS\"\n\n#: vncviewer/OptionsDialog.cxx:700\nmsgid \"TLS with X509 certificates\"\nmsgstr \"X509 인증서가 있는 TLS\"\n\n#: vncviewer/OptionsDialog.cxx:707\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"X509 CA 인증서의 경로\"\n\n#: vncviewer/OptionsDialog.cxx:714\nmsgid \"Path to X509 CRL file\"\nmsgstr \"X509 CRL 파일의 경로\"\n\n#: vncviewer/OptionsDialog.cxx:739\nmsgid \"Authentication\"\nmsgstr \"인증\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"표준 VNC (암호화하지 않아 취약함)\"\n\n# 사용자라고 표시하기 괜찮은가?\n# 사용자 명?\n# 사용자 이름\n#: vncviewer/OptionsDialog.cxx:762\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"사용자와 암호(암호화하지 않아 취약함)\"\n\n#: vncviewer/OptionsDialog.cxx:781\nmsgid \"Input\"\nmsgstr \"입력\"\n\n#: vncviewer/OptionsDialog.cxx:794\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"보기 전용(마우스와 키보드 무시)\"\n\n#: vncviewer/OptionsDialog.cxx:801\nmsgid \"Mouse\"\nmsgstr \"마우스\"\n\n#: vncviewer/OptionsDialog.cxx:815\nmsgid \"Emulate middle mouse button\"\nmsgstr \"마우스 가운데 버튼 에뮬레이트\"\n\n#: vncviewer/OptionsDialog.cxx:821\nmsgid \"Show dot when no cursor\"\nmsgstr \"커서가 없을 때 점 표시\"\n\n#: vncviewer/OptionsDialog.cxx:835\nmsgid \"Keyboard\"\nmsgstr \"키보드\"\n\n#: vncviewer/OptionsDialog.cxx:849\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"시스템 키를 서버에 직접 전달 (전체 화면)\"\n\n#: vncviewer/OptionsDialog.cxx:852\nmsgid \"Menu key\"\nmsgstr \"메뉴 키\"\n\n#: vncviewer/OptionsDialog.cxx:871\nmsgid \"Clipboard\"\nmsgstr \"클립보드\"\n\n# 승인 vs 허용\n#: vncviewer/OptionsDialog.cxx:885\nmsgid \"Accept clipboard from server\"\nmsgstr \"서버에서 받은 클립보드를 허용\"\n\n# 왜 also가 붙을까?\n#: vncviewer/OptionsDialog.cxx:893\nmsgid \"Also set primary selection\"\nmsgstr \"주 선택으로도 설정\"\n\n#: vncviewer/OptionsDialog.cxx:900\nmsgid \"Send clipboard to server\"\nmsgstr \"클립보드를 서버에 전송\"\n\n#: vncviewer/OptionsDialog.cxx:908\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"기본 선택을 클립보드로 전송\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Display\"\nmsgstr \"화면\"\n\n#: vncviewer/OptionsDialog.cxx:941\nmsgid \"Display mode\"\nmsgstr \"화면 모드\"\n\n#: vncviewer/OptionsDialog.cxx:956\nmsgid \"Windowed\"\nmsgstr \"창 모드\"\n\n#: vncviewer/OptionsDialog.cxx:964\nmsgid \"Full screen on current monitor\"\nmsgstr \"현재 모니터에 전체화면\"\n\n#: vncviewer/OptionsDialog.cxx:972\nmsgid \"Full screen on all monitors\"\nmsgstr \"모든 모니터에 전체 화면\"\n\n#: vncviewer/OptionsDialog.cxx:980\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"선택한 모니터에 전체 화면\"\n\n#: vncviewer/OptionsDialog.cxx:1007\nmsgid \"Misc.\"\nmsgstr \"기타.\"\n\n#: vncviewer/OptionsDialog.cxx:1015\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"공유 (다른 뷰어와의 연결을 끊지 않음)\"\n\n#: vncviewer/OptionsDialog.cxx:1021\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"연결 오류 시 다시 연결을 요청\"\n\n#: vncviewer/ServerDialog.cxx:58\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"VNC 뷰어: 연결 세부 사항\"\n\n#: vncviewer/ServerDialog.cxx:65 vncviewer/ServerDialog.cxx:70\nmsgid \"VNC server:\"\nmsgstr \"VNC 서버:\"\n\n#: vncviewer/ServerDialog.cxx:81\nmsgid \"Options...\"\nmsgstr \"설정...\"\n\n#: vncviewer/ServerDialog.cxx:86\nmsgid \"Load...\"\nmsgstr \"불러오기...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save As...\"\nmsgstr \"다른 이름으로 저장...\"\n\n#: vncviewer/ServerDialog.cxx:103\nmsgid \"About...\"\nmsgstr \"정보...\"\n\n#: vncviewer/ServerDialog.cxx:113\nmsgid \"Connect\"\nmsgstr \"연결\"\n\n#: vncviewer/ServerDialog.cxx:145\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"서버 히스토리를 불러올 수 없음:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:173 vncviewer/ServerDialog.cxx:212\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"TigerVNC 환경 설정(*.tigervnc)\"\n\n# 구성 vs 환경설정\n#: vncviewer/ServerDialog.cxx:174\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"TigerVNC 환경 설정 파일 선택\"\n\n#: vncviewer/ServerDialog.cxx:196 vncviewer/vncviewer.cxx:552\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"지정한 환경 설정 파일을 불러올 수 없음:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:213\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"TigerVNC 환경 설정을 파일로 저장\"\n\n#: vncviewer/ServerDialog.cxx:239\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s이(가) 이미 존재합니다. 덮어쓰시겠습니까?\"\n\n#: vncviewer/ServerDialog.cxx:240 vncviewer/vncviewer.cxx:414\nmsgid \"No\"\nmsgstr \"아니오\"\n\n#: vncviewer/ServerDialog.cxx:240\nmsgid \"Overwrite\"\nmsgstr \"덮어쓰기\"\n\n#: vncviewer/ServerDialog.cxx:256\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"지정한 환경 설정 파일을 저장할 수 없음:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:290\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"기본 환경 설정을 저장할 수 없음:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:303\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"서버 히스토리를 저장할 수 없음:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:320 vncviewer/ServerDialog.cxx:387\n#: vncviewer/parameters.cxx:635 vncviewer/parameters.cxx:740\n#: vncviewer/vncviewer.cxx:459\nmsgid \"Could not obtain the home directory path\"\nmsgstr \"VNC 홈 디렉토리 생성 불가: %s\"\n\n#: vncviewer/ServerDialog.cxx:333 vncviewer/ServerDialog.cxx:396\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:753\n#, c-format\nmsgid \"Could not open \\\"%s\\\": %s\"\nmsgstr \"\\\"%s\\\"를 열 수 없습니다: %s\"\n\n#: vncviewer/ServerDialog.cxx:348 vncviewer/ServerDialog.cxx:356\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:773\n#: vncviewer/parameters.cxx:804 vncviewer/parameters.cxx:833\n#: vncviewer/parameters.cxx:839\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"파일의 %d줄을 읽지 못함 %s: %s\"\n\n#: vncviewer/ServerDialog.cxx:357 vncviewer/parameters.cxx:774\nmsgid \"Line too long\"\nmsgstr \"행 길이 초과\"\n\n#: vncviewer/UserDialog.cxx:98\nmsgid \"Opening password file failed\"\nmsgstr \"암호 파일을 열기 실패\"\n\n#: vncviewer/UserDialog.cxx:118\nmsgid \"VNC authentication\"\nmsgstr \"VNC 인증\"\n\n#: vncviewer/UserDialog.cxx:125\nmsgid \"This connection is secure\"\nmsgstr \"이 연결은 안전합니다\"\n\n#: vncviewer/UserDialog.cxx:129\nmsgid \"This connection is not secure\"\nmsgstr \"이 연결은 취약합니다\"\n\n#: vncviewer/UserDialog.cxx:146\nmsgid \"Username:\"\nmsgstr \"사용자:\"\n\n#: vncviewer/UserDialog.cxx:159\nmsgid \"Password:\"\nmsgstr \"비밀번호:\"\n\n#: vncviewer/UserDialog.cxx:198\nmsgid \"Authentication cancelled\"\nmsgstr \"인증이 취소됨\"\n\n#: vncviewer/Viewport.cxx:391\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"키보드 LED 상태 업데이트 실패: %lu\"\n\n#: vncviewer/Viewport.cxx:397 vncviewer/Viewport.cxx:403\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"키보드 LED 상태 업데이트 실패: %d\"\n\n#: vncviewer/Viewport.cxx:433\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"키보드 LED 상태 업데이트 실패\"\n\n#: vncviewer/Viewport.cxx:460 vncviewer/Viewport.cxx:468\n#: vncviewer/Viewport.cxx:485\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"키보드 LED 상태 불러오기 실패: %d\"\n\n#: vncviewer/Viewport.cxx:849\nmsgid \"No key code specified on key press\"\nmsgstr \"입력된 키 코드가 지정되지 않음\"\n\n#: vncviewer/Viewport.cxx:1008\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"확장된 가상 키 0x%02x의 스캔 코드가 없음\"\n\n#: vncviewer/Viewport.cxx:1010\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"가상 키 0x%02x의 스캔 코드가 없음\"\n\n#: vncviewer/Viewport.cxx:1016\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"잘못된 스캔 코드 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1046\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"확장된 가상 키 0x%02x의 심볼이 없음\"\n\n#: vncviewer/Viewport.cxx:1048\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"가상 키 0x%02x의 심볼이 없음\"\n\n#: vncviewer/Viewport.cxx:1154\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"키 0x%02x의 심볼이 없음 (현재 상태)\"\n\n#: vncviewer/Viewport.cxx:1187\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"키 %d의 심볼이 없음 (현재 상태)\"\n\n#: vncviewer/Viewport.cxx:1247\nmsgctxt \"ContextMenu|\"\nmsgid \"Dis&connect\"\nmsgstr \"연결끊기(&C)\"\n\n#: vncviewer/Viewport.cxx:1250\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"최대화(&F)\"\n\n#: vncviewer/Viewport.cxx:1253\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"최소화(&Z)\"\n\n#: vncviewer/Viewport.cxx:1255\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"세션에 맞춰 화면 크기를 재설정(&W)\"\n\n#: vncviewer/Viewport.cxx:1260\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:1263\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1269\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"%s 전송\"\n\n#: vncviewer/Viewport.cxx:1275\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Ctrl-Alt-Del 전송(&D)\"\n\n#: vncviewer/Viewport.cxx:1278\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"화면을 다시 불러오기(&R)\"\n\n#: vncviewer/Viewport.cxx:1281\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"설정(&O)\"\n\n#: vncviewer/Viewport.cxx:1283\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"연결 정보(&I)\"\n\n#: vncviewer/Viewport.cxx:1285\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"TigerVNC 뷰어 정보(&T)\"\n\n#: vncviewer/Viewport.cxx:1374\nmsgid \"VNC connection info\"\nmsgstr \"VNC 연결 정보\"\n\n#: vncviewer/Win32TouchHandler.cxx:47\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"제스처 대신 터치로 창이 등록됨\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"제스처 구성 설정 실패 (오류: 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"제스처 정보를 불러오기 실패 (오류 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:358\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"잘못된 마우스 버튼 %d, 1에서 7 사이의 값을 가져야 합니다.\"\n\n#: vncviewer/Win32TouchHandler.cxx:423\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"처리되지 않은 키 0x%x - 키보드 이벤트를 생성할 수 없음.\"\n\n#: vncviewer/XInputTouchHandler.cxx:102 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"창 0x%08lx에 대한 X Input 2 이벤트 마스크를 가져올 수 없음\"\n\n#: vncviewer/XInputTouchHandler.cxx:104\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"0x%08lx 창에 X Input 2 이벤트 마스트가 없음\"\n\n#: vncviewer/XInputTouchHandler.cxx:112 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"창 0x%08lx에 X Input 2 이벤트 마스크가 두 개 이상 존재함\"\n\n#: vncviewer/XInputTouchHandler.cxx:143\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"장치 %i을(를) 가져오지 못함\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.cxx:406 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"TigerVNC 뷰어\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"VNC 서버와 연결하고 원격 데스크톱을 보입니다\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"가상 네트워크 컴퓨팅(Virtual Network Computing, VNC)이란 네트워크를 통해 다른 컴퓨터에서 실행 중인 가상 데스크톱 환경을 보고 상호작용할 수 있는 원격 디스플레이 시스템입니다. VNC을 사용하면 원격 컴퓨터에서 실행한 그래픽 애플리케이션의 화면만 로컬 장치로 전송할 수 있습니다. 이 패키지에는 VNC 서버를 실행하는 다른 데스크톱에 연결할 수 있는 클라이언트가 포함되어 있습니다. VNC는 플랫폼 독립적이며 서버와 클라이언트로서 다양한 운영 체제 및 아키텍처를 지원합니다.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC는 RealVNC 4와 X.org 코드를 기반으로 한 고속 버전의 VNC입니다. TigerVNC는 Unix 및 Linux 플랫폼에서의 차세대 TightVNC를 개발하기 위해 시작되었지만 2009년 초에 프로젝트에서 분리었고 TightVNC는 Windows 플랫폼에 집중할 수 있게 되었습니다. TigerVNC는 libjpeg-turbo JPEG 코덱을 사용하여 가속화되는 Tight 인코딩의 변형을 지원합니다.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC Viewer connection to a CentOS machine\"\nmsgstr \"CentOS 기기에 대한 TigerVNC 뷰어 연결\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC Viewer connection to a macOS machine\"\nmsgstr \"macOS 기기에 대한 TigerVNC 뷰어 연결\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC Viewer connection to a Windows machine\"\nmsgstr \"Windows 기기에 대한 TigerVNC 뷰어 연결\"\n\n#: vncviewer/parameters.cxx:308 vncviewer/parameters.cxx:333\n#: vncviewer/parameters.cxx:350 vncviewer/parameters.cxx:390\n#: vncviewer/parameters.cxx:410\nmsgid \"The name of the parameter is too large\"\nmsgstr \"변수명 길이 초과\"\n\n#: vncviewer/parameters.cxx:312 vncviewer/parameters.cxx:317\n#: vncviewer/parameters.cxx:368\nmsgid \"The parameter is too large\"\nmsgstr \"변수 크기 초과\"\n\n#: vncviewer/parameters.cxx:375 vncviewer/parameters.cxx:696\n#: vncviewer/parameters.cxx:818\nmsgid \"Invalid format or too large value\"\nmsgstr \"잘못된 형식 또는 변수 크기 초과\"\n\n#: vncviewer/parameters.cxx:429 vncviewer/parameters.cxx:460\nmsgid \"Failed to create registry key\"\nmsgstr \"레지스트리 키 생성 실패\"\n\n#: vncviewer/parameters.cxx:448 vncviewer/parameters.cxx:503\n#: vncviewer/parameters.cxx:545 vncviewer/parameters.cxx:612\nmsgid \"Failed to close registry key\"\nmsgstr \"레지스트리 키를 닫지 못함\"\n\n#: vncviewer/parameters.cxx:466 vncviewer/parameters.cxx:483\n#: vncviewer/parameters.cxx:654 vncviewer/parameters.cxx:664\n#: vncviewer/parameters.cxx:675\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"\\\"%s\\\" 저장 실패: %s\"\n\n#: vncviewer/parameters.cxx:479 vncviewer/parameters.cxx:567\n#: vncviewer/parameters.cxx:677 vncviewer/parameters.cxx:714\nmsgid \"Unknown parameter type\"\nmsgstr \"알 수 없는 타입의 변수\"\n\n#: vncviewer/parameters.cxx:496\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"\\\"%s\\\" 삭제 실패: %s\"\n\n# 레지스터 vs 등록\n#: vncviewer/parameters.cxx:518 vncviewer/parameters.cxx:590\nmsgid \"Failed to open registry key\"\nmsgstr \"레지스트리 키를 열지 못함\"\n\n#: vncviewer/parameters.cxx:535\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"서버 히스토리 항목 %d를 읽지 못함: %s\"\n\n#: vncviewer/parameters.cxx:571 vncviewer/parameters.cxx:601\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"변수 %s 읽기 실패: %s\"\n\n#: vncviewer/parameters.cxx:655 vncviewer/parameters.cxx:666\nmsgid \"Could not encode parameter\"\nmsgstr \"파라미터를 인코딩할 수 없음\"\n\n#: vncviewer/parameters.cxx:783\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"환경 설정 파일 %s의 형식이 잘못됨\"\n\n#: vncviewer/parameters.cxx:805\nmsgid \"Invalid format\"\nmsgstr \"잘못된 형식\"\n\n#: vncviewer/parameters.cxx:840\nmsgid \"Unknown parameter\"\nmsgstr \"알 수 없는 타입의 파라미터\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"처리되지 않은 창에 대한 메시지(0x%x)를 받았습니다\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"포인터 그랩에 잘못된 창 0x%08lx가 지정됨\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"터치 핸들러 생성 실패: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"이벤트 핸들러를 창에 연결할 수 없음 (오류 0x%x)\"\n\n#: vncviewer/touch.cxx:212\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"X Input 이벤트에 대한 이벤트 데이터를 가져오지 못함\"\n\n#: vncviewer/touch.cxx:225\nmsgid \"X Input event for unknown window\"\nmsgstr \"알 수 없는 창에 대한 X Input 이벤트\"\n\n#: vncviewer/touch.cxx:251\nmsgid \"X Input extension not available.\"\nmsgstr \"X Input 확장자를 사용할 수 없습니다.\"\n\n#: vncviewer/touch.cxx:258\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2(또는 그 이상)을 사용할 수 없습니다.\"\n\n#: vncviewer/touch.cxx:263\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2.2(또는 그 이상)을 사용할 수 없습니다. 터치 제스처는 지원하지 않습니다.\"\n\n#: vncviewer/vncviewer.cxx:107\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC Viewer v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"TigerVNC에 대한 자세한 정보는 https://www.tigervnc.org를 참조하십시오.\"\n\n#: vncviewer/vncviewer.cxx:161\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"서버 통신 중 예상치 못한 오류 발생: %s\"\n\n#: vncviewer/vncviewer.cxx:177\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"TigerVNC 뷰어 정보\"\n\n#: vncviewer/vncviewer.cxx:198\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"내부 FLTK 오류. 종료합니다.\"\n\n#: vncviewer/vncviewer.cxx:217\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"다시 연결을 시도하시겠습니까?\"\n\n#: vncviewer/vncviewer.cxx:248 vncviewer/vncviewer.cxx:260\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"새 TigerVNC 뷰어를 시작하는 중 오류 발생: %s\"\n\n#: vncviewer/vncviewer.cxx:269\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"종료 신호 %d가 수신되었습니다. TigerVNC 뷰어를 종료합니다.\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Yes\"\nmsgstr \"예\"\n\n#: vncviewer/vncviewer.cxx:418\nmsgid \"Close\"\nmsgstr \"닫기\"\n\n#: vncviewer/vncviewer.cxx:423\nmsgid \"About\"\nmsgstr \"정보\"\n\n#: vncviewer/vncviewer.cxx:426\nmsgid \"Hide\"\nmsgstr \"숨기기\"\n\n#: vncviewer/vncviewer.cxx:429\nmsgid \"Quit\"\nmsgstr \"나가기\"\n\n#: vncviewer/vncviewer.cxx:433\nmsgid \"Services\"\nmsgstr \"서비스\"\n\n#: vncviewer/vncviewer.cxx:434\nmsgid \"Hide Others\"\nmsgstr \"다른 것 숨기기\"\n\n#: vncviewer/vncviewer.cxx:435\nmsgid \"Show All\"\nmsgstr \"모두 보이기\"\n\n#: vncviewer/vncviewer.cxx:444\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"파일(&F)\"\n\n#: vncviewer/vncviewer.cxx:447\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"새 연결(&N)\"\n\n#: vncviewer/vncviewer.cxx:463\n#, c-format\nmsgid \"Could not create VNC home directory: %s\"\nmsgstr \"VNC 홈 디렉토리 생성 불가: %s\"\n\n#: vncviewer/vncviewer.cxx:562\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors는 더 이상 사용되지 않으며 대신 FullScreenMode를 'all'로 설정합니다\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:768 vncviewer/vncviewer.cxx:769\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"-listen과 -via를 통한 인자들은 호환되지 않음\"\n\n#: vncviewer/vncviewer.cxx:783\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"포트 %d에 접속 대기중\"\n\n#: vncviewer/vncviewer.cxx:816\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"들어오는 VNC 연결을 기다리는 중 오류가 발생함:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"원격 데스크톱 뷰어\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"X11 RandR을 찾을 수 없어 모니터 이름을 가져오지 못함\"\n\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"CRTC %d에 대한 정보를 가져오는 데 실패함\"\n\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"CRTC %d의 출력 %d에 대한 정보를 가져오는 데 실패함\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"화면\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"연결 시 원격 세션의 크기를 조정\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"원격 세션의 크기를 로컬 창으로 조정\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"전체 화면 모드 사용\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"높음 (이용 가능한 모든 색상)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"중간 (256 색상)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"낮음 (64 색상)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"매우 낮음 (8 색상)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"레벨(1=빠름, 6=품질[4-6은 잘 사용되지 않습니다])\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"전체 화면 모드\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"뷰어 나가기(&X)\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"메뉴 해제(&D)\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"%s 타입의 변수 %s를 레지스트리에 쓸 수 없습니다: %ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"변수명 %s이(가) 너무 길어 레지스트리에서 읽을 수 없습니다\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"변수 %s가 너무 커 레지스트리에서 읽을 수 없습니다\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"환경설정 파일 저장 실패, 홈 디렉토리 경로를 얻지 못하였습니다.\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"환경설정 파일 저장 실패, %s를 열 수 없습니다: %s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"환경설정 파일 불러오기 실패, 홈 디렉토리 경로를 얻지 못하였습니다.\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"알 수 없는 매개변수 %1$s가 파일 %3$s의 %2$d줄에 존재\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"VNC 홈 디렉토리 생성 불가: 홈 디렉토리 경로를 찾을 수 없습니다.\"\n\n#~ msgid \"tigervnc\"\n#~ msgstr \"tigervnc\"\n"
  },
  {
    "path": "po/nl.po",
    "content": "# Dutch translations for TigerVNC.\n# Copyright (C) the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n#\n# \"That said, you owe me a new keyboard.\"\n#\n# Benno Schulenberg <benno@vertaalt.nl>, 2014, 2015, 2016, 2017.\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.7.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2017-04-19 13:05+0000\\n\"\n\"PO-Revision-Date: 2017-05-03 20:34+0200\\n\"\n\"Last-Translator: Benno Schulenberg <benno@vertaalt.nl>\\n\"\n\"Language-Team: Dutch <vertaling@vrijschrift.org>\\n\"\n\"Language: nl\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Lokalize 1.0\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\n#: vncviewer/CConn.cxx:110\n#, c-format\nmsgid \"connected to host %s port %d\"\nmsgstr \"verbonden met host %s poort %d\"\n\n#: vncviewer/CConn.cxx:169\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Bureaubladnaam: %.80s\"\n\n#: vncviewer/CConn.cxx:174\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Host: %.80s poort: %d\"\n\n#: vncviewer/CConn.cxx:179\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Grootte: %d x %d\"\n\n#: vncviewer/CConn.cxx:187\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Pixel-indeling: %s\"\n\n#: vncviewer/CConn.cxx:194\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(serverstandaard is %s)\"\n\n#: vncviewer/CConn.cxx:199\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Gevraagde codering: %s\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Laatst gebruikte codering: %s\"\n\n#: vncviewer/CConn.cxx:209\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Geschatte lijnsnelheid: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:214\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Protocolversie: %d.%d\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Beveiligingsmethode: %s\"\n\n#: vncviewer/CConn.cxx:343\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"### SetDesktopSize is mislukt: %d\"\n\n#: vncviewer/CConn.cxx:413\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"Ongeldige 'SetColourMapEntries' van de server!\"\n\n#: vncviewer/CConn.cxx:489\nmsgid \"Enabling continuous updates\"\nmsgstr \"Continue updates inschakelen\"\n\n#: vncviewer/CConn.cxx:559\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Throughput is %d kbit/s -- overgaand naar kwaliteit %d\"\n\n#: vncviewer/CConn.cxx:581\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now %s\"\nmsgstr \"Throughput is %d kbit/s -- volledige kleuren is nu %s\"\n\n#: vncviewer/CConn.cxx:583\nmsgid \"disabled\"\nmsgstr \"uitgeschakeld\"\n\n#: vncviewer/CConn.cxx:583\nmsgid \"enabled\"\nmsgstr \"ingeschakeld\"\n\n#: vncviewer/CConn.cxx:593\n#, c-format\nmsgid \"Using %s encoding\"\nmsgstr \"Codering %s wordt gebruikt\"\n\n#: vncviewer/CConn.cxx:640\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Pixel-indeling %s wordt gebruikt\"\n\n#: vncviewer/DesktopWindow.cxx:121\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Ongeldige afmetingen opgegeven!\"\n\n#: vncviewer/DesktopWindow.cxx:434\nmsgid \"Adjusting window size to avoid accidental full screen request\"\nmsgstr \"Venstergrootte wordt aangepast om onbedoeld volledigschermverzoek te vermijden\"\n\n#: vncviewer/DesktopWindow.cxx:478\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Druk op %s om het contextmenu te openen\"\n\n#: vncviewer/DesktopWindow.cxx:741 vncviewer/DesktopWindow.cxx:747\n#: vncviewer/DesktopWindow.cxx:760\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Het \\\"grijpen\\\" van het toetsenbord is mislukt\"\n\n#: vncviewer/DesktopWindow.cxx:772\nmsgid \"Failure grabbing mouse\"\nmsgstr \"Het \\\"grijpen\\\" van de muis is mislukt\"\n\n#: vncviewer/DesktopWindow.cxx:1002\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Ongeldige schermopmaak berekend voor wijzigingsverzoek.\"\n\n#: vncviewer/FLTKPixelBuffer.cxx:33\nmsgid \"Not enough memory for framebuffer\"\nmsgstr \"Onvoldoende geheugen beschikbaar voor framebuffer\"\n\n#: vncviewer/OptionsDialog.cxx:57\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"VNC-viewer: Verbindingsopties\"\n\n#: vncviewer/OptionsDialog.cxx:83 vncviewer/ServerDialog.cxx:91\n#: vncviewer/vncviewer.cxx:282\nmsgid \"Cancel\"\nmsgstr \"Annuleren\"\n\n#: vncviewer/OptionsDialog.cxx:88 vncviewer/vncviewer.cxx:281\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: vncviewer/OptionsDialog.cxx:423\nmsgid \"Compression\"\nmsgstr \"Compressie\"\n\n#: vncviewer/OptionsDialog.cxx:439\nmsgid \"Auto select\"\nmsgstr \"Automatisch selecteren\"\n\n#: vncviewer/OptionsDialog.cxx:451\nmsgid \"Preferred encoding\"\nmsgstr \"Voorkeurscodering\"\n\n#: vncviewer/OptionsDialog.cxx:499\nmsgid \"Color level\"\nmsgstr \"Kleurdiepte\"\n\n#: vncviewer/OptionsDialog.cxx:510\nmsgid \"Full (all available colors)\"\nmsgstr \"volledig (alle beschikbare kleuren)\"\n\n#: vncviewer/OptionsDialog.cxx:517\nmsgid \"Medium (256 colors)\"\nmsgstr \"medium (256 kleuren)\"\n\n#: vncviewer/OptionsDialog.cxx:524\nmsgid \"Low (64 colors)\"\nmsgstr \"laag (64 kleuren)\"\n\n#: vncviewer/OptionsDialog.cxx:531\nmsgid \"Very low (8 colors)\"\nmsgstr \"zeer laag (8 kleuren)\"\n\n#: vncviewer/OptionsDialog.cxx:548\nmsgid \"Custom compression level:\"\nmsgstr \"Aangepast compressieniveau:\"\n\n#: vncviewer/OptionsDialog.cxx:554\nmsgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\nmsgstr \"niveau (1=snel, 6=best [4-6 zijn zelden nuttig])\"\n\n#: vncviewer/OptionsDialog.cxx:561\nmsgid \"Allow JPEG compression:\"\nmsgstr \"JPEG-compressie toestaan:\"\n\n#: vncviewer/OptionsDialog.cxx:567\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"kwaliteit (0=slecht, 9=best)\"\n\n#: vncviewer/OptionsDialog.cxx:578\nmsgid \"Security\"\nmsgstr \"Beveiliging\"\n\n#: vncviewer/OptionsDialog.cxx:593\nmsgid \"Encryption\"\nmsgstr \"Versleuteling\"\n\n#: vncviewer/OptionsDialog.cxx:604 vncviewer/OptionsDialog.cxx:657\n#: vncviewer/OptionsDialog.cxx:737\nmsgid \"None\"\nmsgstr \"Geen\"\n\n#: vncviewer/OptionsDialog.cxx:610\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS met anonieme certificaten\"\n\n#: vncviewer/OptionsDialog.cxx:616\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS met X509-certificaten\"\n\n#: vncviewer/OptionsDialog.cxx:623\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Pad naar X509 CA-certificaat\"\n\n#: vncviewer/OptionsDialog.cxx:630\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Pad naar X509 CRL-bestand\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Authentication\"\nmsgstr \"Authenticatie\"\n\n#: vncviewer/OptionsDialog.cxx:663\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Standaard VNC (onveilig zonder versleuteling)\"\n\n#: vncviewer/OptionsDialog.cxx:669\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Gebruikersnaam en wachtwoord (onveilig zonder versleuteling)\"\n\n#: vncviewer/OptionsDialog.cxx:688\nmsgid \"Input\"\nmsgstr \"Invoer\"\n\n#: vncviewer/OptionsDialog.cxx:696\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Alleen kijken (muis en toetsenbord negeren)\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"Accept clipboard from server\"\nmsgstr \"Klembord van server accepteren\"\n\n#: vncviewer/OptionsDialog.cxx:710\nmsgid \"Also set primary selection\"\nmsgstr \"Ook de hoofdselectie instellen\"\n\n#: vncviewer/OptionsDialog.cxx:717\nmsgid \"Send clipboard to server\"\nmsgstr \"Klembord naar server zenden\"\n\n#: vncviewer/OptionsDialog.cxx:725\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Hoofdselectie als klembord verzenden\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Systeemsleutels direct aan server doorgeven (volledigscherm)\"\n\n#: vncviewer/OptionsDialog.cxx:735\nmsgid \"Menu key\"\nmsgstr \"Menutoets\"\n\n#: vncviewer/OptionsDialog.cxx:751\nmsgid \"Screen\"\nmsgstr \"Scherm\"\n\n#: vncviewer/OptionsDialog.cxx:759\nmsgid \"Resize remote session on connect\"\nmsgstr \"Grootte van gindse sessie aanpassen bij verbinden\"\n\n#: vncviewer/OptionsDialog.cxx:772\nmsgid \"Resize remote session to the local window\"\nmsgstr \"Gindse sessie aan het lokale venster aanpassen\"\n\n#: vncviewer/OptionsDialog.cxx:778\nmsgid \"Full-screen mode\"\nmsgstr \"Volledigscherm-modus\"\n\n#: vncviewer/OptionsDialog.cxx:784\nmsgid \"Enable full-screen mode over all monitors\"\nmsgstr \"Volledigscherm-modus over alle beeldschermen inschakelen\"\n\n#: vncviewer/OptionsDialog.cxx:793\nmsgid \"Misc.\"\nmsgstr \"Overige\"\n\n#: vncviewer/OptionsDialog.cxx:801\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Gedeeld (verbinding van andere viewers niet verbreken)\"\n\n#: vncviewer/OptionsDialog.cxx:807\nmsgid \"Show dot when no cursor\"\nmsgstr \"Punt tonen als er geen cursor is\"\n\n#: vncviewer/ServerDialog.cxx:42\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"VNC-viewer: Verbindingsdetails\"\n\n#: vncviewer/ServerDialog.cxx:49 vncviewer/ServerDialog.cxx:54\nmsgid \"VNC server:\"\nmsgstr \"VNC-server:\"\n\n#: vncviewer/ServerDialog.cxx:64\nmsgid \"Options...\"\nmsgstr \"Opties...\"\n\n#: vncviewer/ServerDialog.cxx:69\nmsgid \"Load...\"\nmsgstr \"Laden...\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"Save As...\"\nmsgstr \"Opslaan als...\"\n\n#: vncviewer/ServerDialog.cxx:86\nmsgid \"About...\"\nmsgstr \"Info...\"\n\n#: vncviewer/ServerDialog.cxx:96\nmsgid \"Connect\"\nmsgstr \"Verbinden\"\n\n#: vncviewer/UserDialog.cxx:74\nmsgid \"Opening password file failed\"\nmsgstr \"Openen van wachtwoordbestand is mislukt\"\n\n#: vncviewer/UserDialog.cxx:86 vncviewer/UserDialog.cxx:96\nmsgid \"VNC authentication\"\nmsgstr \"VNC-authenticatie\"\n\n#: vncviewer/UserDialog.cxx:87 vncviewer/UserDialog.cxx:102\nmsgid \"Password:\"\nmsgstr \"Wachtwoord:\"\n\n#: vncviewer/UserDialog.cxx:89\nmsgid \"Authentication cancelled\"\nmsgstr \"Authenticatie is geannuleerd\"\n\n#: vncviewer/UserDialog.cxx:99\nmsgid \"Username:\"\nmsgstr \"Gebruikersnaam:\"\n\n#: vncviewer/Viewport.cxx:586\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Geen scancode voor uitgebreide virtuele toets 0x%02x\"\n\n#: vncviewer/Viewport.cxx:588\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Geen scancode voor virtuele toets 0x%02x\"\n\n#: vncviewer/Viewport.cxx:605\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Geen symbool voor uitgebreide virtuele toets 0x%02x\"\n\n#: vncviewer/Viewport.cxx:607\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Geen symbool voor virtuele toets 0x%02x\"\n\n#: vncviewer/Viewport.cxx:645\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"Geen symbool voor toetscode 0x%02x (in de huidige toestand)\"\n\n#: vncviewer/Viewport.cxx:671\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Geen symbool voor toetscode %d (in de huidige toestand)\"\n\n#: vncviewer/Viewport.cxx:708\nmsgctxt \"ContextMenu|\"\nmsgid \"E&xit viewer\"\nmsgstr \"Viewer af&sluiten\"\n\n#: vncviewer/Viewport.cxx:711\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Volledig scherm\"\n\n#: vncviewer/Viewport.cxx:714\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"&Minimaliseren\"\n\n#: vncviewer/Viewport.cxx:716\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Ve&nster aan sessie aanpassen\"\n\n#: vncviewer/Viewport.cxx:721\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:724\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:730\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"%s zenden\"\n\n#: vncviewer/Viewport.cxx:736\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Ctrl-Alt-&Del zenden\"\n\n#: vncviewer/Viewport.cxx:739\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Sch&erm verversen\"\n\n#: vncviewer/Viewport.cxx:742\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Opties...\"\n\n#: vncviewer/Viewport.cxx:744\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Verbindings&info...\"\n\n#: vncviewer/Viewport.cxx:746\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"Info over &TigerVNC-viewer...\"\n\n#: vncviewer/Viewport.cxx:749\nmsgctxt \"ContextMenu|\"\nmsgid \"Dismiss &menu\"\nmsgstr \"Menu ver&laten\"\n\n#: vncviewer/Viewport.cxx:833\nmsgid \"VNC connection info\"\nmsgstr \"VNC-verbindingsinfo\"\n\n#: vncviewer/parameters.cxx:286 vncviewer/parameters.cxx:320\n#, c-format\nmsgid \"The name of the parameter %s was too large to write to the registry\"\nmsgstr \"De naam van parameter %s is te lang om naar het register te schrijven\"\n\n#: vncviewer/parameters.cxx:292 vncviewer/parameters.cxx:299\n#, c-format\nmsgid \"The parameter %s was too large to write to the registry\"\nmsgstr \"Parameter %s is te lang om naar het register te schrijven\"\n\n#: vncviewer/parameters.cxx:305 vncviewer/parameters.cxx:326\n#, c-format\nmsgid \"Failed to write parameter %s of type %s to the registry: %ld\"\nmsgstr \"Schrijven van parameter %s van type %s naar het register is mislukt: %ld\"\n\n#: vncviewer/parameters.cxx:341 vncviewer/parameters.cxx:380\n#, c-format\nmsgid \"The name of the parameter %s was too large to read from the registry\"\nmsgstr \"De naam van parameter %s is te lang om uit het register te lezen\"\n\n#: vncviewer/parameters.cxx:350 vncviewer/parameters.cxx:389\n#, c-format\nmsgid \"Failed to read parameter %s from the registry: %ld\"\nmsgstr \"Lezen van parameter %s uit het register is mislukt: %ld\"\n\n#: vncviewer/parameters.cxx:359\n#, c-format\nmsgid \"The parameter %s was too large to read from the registry\"\nmsgstr \"Parameter %s is te lang om uit het register te lezen\"\n\n#: vncviewer/parameters.cxx:409\n#, c-format\nmsgid \"Failed to create registry key: %ld\"\nmsgstr \"Aanmaken van registersleutel %ld is mislukt\"\n\n#: vncviewer/parameters.cxx:423 vncviewer/parameters.cxx:472\n#: vncviewer/parameters.cxx:534 vncviewer/parameters.cxx:665\n#, c-format\nmsgid \"Unknown parameter type for parameter %s\"\nmsgstr \"Onbekend parametertype voor parameter %s\"\n\n#: vncviewer/parameters.cxx:430 vncviewer/parameters.cxx:479\n#, c-format\nmsgid \"Failed to close registry key: %ld\"\nmsgstr \"Sluiten van registersleutel %ld is mislukt\"\n\n#: vncviewer/parameters.cxx:446\n#, c-format\nmsgid \"Failed to open registry key: %ld\"\nmsgstr \"Openen van registersleutel %ld is mislukt\"\n\n#: vncviewer/parameters.cxx:503\nmsgid \"Failed to write configuration file, can't obtain home directory path.\"\nmsgstr \"Schrijven van configuratiebestand is mislukt; kan pad van thuismap niet verkrijgen.\"\n\n#: vncviewer/parameters.cxx:516\n#, c-format\nmsgid \"Failed to write configuration file, can't open %s: %s\"\nmsgstr \"Schrijven van configuratiebestand is mislukt; kan %s niet openen: %s\"\n\n#: vncviewer/parameters.cxx:559\nmsgid \"Failed to read configuration file, can't obtain home directory path.\"\nmsgstr \"Lezen van configuratiebestand is mislukt; kan pad van thuismap niet verkrijgen.\"\n\n#: vncviewer/parameters.cxx:572\n#, c-format\nmsgid \"Failed to read configuration file, can't open %s: %s\"\nmsgstr \"Lezen van configuratiebestand is mislukt; kan %s niet openen: %s\"\n\n#: vncviewer/parameters.cxx:585 vncviewer/parameters.cxx:590\n#: vncviewer/parameters.cxx:615 vncviewer/parameters.cxx:628\n#: vncviewer/parameters.cxx:644\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"Lezen van regel %d in bestand %s is mislukt: %s\"\n\n#: vncviewer/parameters.cxx:591\nmsgid \"Line too long\"\nmsgstr \"Regel is te lang\"\n\n#: vncviewer/parameters.cxx:598\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Configuratiebestand %s het een ongeldige opmaak\"\n\n#: vncviewer/parameters.cxx:616\nmsgid \"Invalid format\"\nmsgstr \"Ongeldige opmaak\"\n\n#: vncviewer/parameters.cxx:629 vncviewer/parameters.cxx:645\nmsgid \"Invalid format or too large value\"\nmsgstr \"Ongeldige opmaak of te grote waarde\"\n\n#: vncviewer/parameters.cxx:672\n#, c-format\nmsgid \"Unknown parameter %s on line %d in file %s\"\nmsgstr \"Onbekende parameter %s op regel %d in bestand %s\"\n\n#: vncviewer/vncviewer.cxx:100\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer %d-bit v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.txt)\\n\"\n\"See http://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC Viewer (%d-bit) v%s\\n\"\n\"Gecompileerd op: %s\\n\"\n\"Copyright (C) 1999-%d het TigerVNC-team en vele anderen (zie README.txt)\\n\"\n\"Zie http://www.tigervnc.org voor informatie over TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:127\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"Info over TigerVNC-viewer\"\n\n#: vncviewer/vncviewer.cxx:140\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Interne FLTK-fout.  Bezig met afsluiten.\"\n\n#: vncviewer/vncviewer.cxx:158 vncviewer/vncviewer.cxx:170\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Fout tijdens starten van nieuwe TigerVNC-viewer: %s\"\n\n#: vncviewer/vncviewer.cxx:179\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"Beëindigingssignaal %d werd ontvangen.  TigerVNC-viewer sluit nu af.\"\n\n#: vncviewer/vncviewer.cxx:271\nmsgid \"TigerVNC Viewer\"\nmsgstr \"TigerVNC-viewer\"\n\n#: vncviewer/vncviewer.cxx:279\nmsgid \"No\"\nmsgstr \"Nee\"\n\n#: vncviewer/vncviewer.cxx:280\nmsgid \"Yes\"\nmsgstr \"Ja\"\n\n#: vncviewer/vncviewer.cxx:283\nmsgid \"Close\"\nmsgstr \"Sluiten\"\n\n#: vncviewer/vncviewer.cxx:288\nmsgid \"About\"\nmsgstr \"Info\"\n\n#: vncviewer/vncviewer.cxx:291\nmsgid \"Hide\"\nmsgstr \"Verbergen\"\n\n#: vncviewer/vncviewer.cxx:294\nmsgid \"Quit\"\nmsgstr \"Afsluiten\"\n\n#: vncviewer/vncviewer.cxx:298\nmsgid \"Services\"\nmsgstr \"Diensten\"\n\n#: vncviewer/vncviewer.cxx:299\nmsgid \"Hide Others\"\nmsgstr \"Andere verbergen\"\n\n#: vncviewer/vncviewer.cxx:300\nmsgid \"Show All\"\nmsgstr \"Alles tonen\"\n\n#: vncviewer/vncviewer.cxx:309\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Bestand\"\n\n#: vncviewer/vncviewer.cxx:312\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Nieuwe verbinding\"\n\n#: vncviewer/vncviewer.cxx:324\nmsgid \"Could not create VNC home directory: can't obtain home directory path.\"\nmsgstr \"Kan de VNC-thuismap niet aanmaken: kan pad van thuismap niet verkrijgen.\"\n\n#: vncviewer/vncviewer.cxx:329\n#, c-format\nmsgid \"Could not create VNC home directory: %s.\"\nmsgstr \"Kan de VNC-thuismap niet aanmaken: %s.\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:534 vncviewer/vncviewer.cxx:535\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"de opties '-listen' en '-via' gaan niet samen\"\n\n#: vncviewer/vncviewer.cxx:550\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Luisterend op poort %d\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"Kan framebuffer-apparaat niet aanmaken\"\n\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"Kan framebuffer-bitkaart niet aanmaken\"\n\n#~ msgid \"Unable to create platform specific framebuffer: %s\"\n#~ msgstr \"Kan geen platform-specifiek framebuffer aanmaken: %s\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"Platform-onafhankelijk framebuffer wordt gebruikt\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"kan geen DIB-sectie aanmaken\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"### CreateCompatibleDC is mislukt\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"### SelectObject is mislukt\"\n\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"### BitBlt is mislukt\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"Scherm heeft geen pixmap-indeling voor standaard kleurdiepte\"\n\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"Kan geen geschikte pixmap-indeling vinden\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"Alleen true-color beeldschermen worden ondersteund\"\n\n#~ msgid \"Using default colormap and visual, TrueColor, depth %d.\"\n#~ msgstr \"Standaard kleurenkaart en visual worden gebruikt, TrueColor, diepte %d.\"\n\n#~ msgid \"Could not create framebuffer image\"\n#~ msgstr \"Kan framebuffer-afbeelding niet aanmaken\"\n\n#~ msgid \"Unknown encoding %d\"\n#~ msgstr \"Onbekende codering %d\"\n\n#~ msgid \"Unknown encoding\"\n#~ msgstr \"Onbekende codering\"\n\n#~ msgid \"Bad Name/Value pair on line: %d in file: %s\"\n#~ msgstr \"Ongeldig naam-waardepaar op regel %d in bestand %s\"\n\n#~ msgid \"Multiple characters given for key code %d (0x%04x): '%s'\"\n#~ msgstr \"Meerdere tekens opgegeven voor toetscode %d (0x%04x): '%s'\"\n\n#~ msgid \"Unknown FLTK key code %d (0x%04x)\"\n#~ msgstr \"Onbekende FLTK-toetscode %d (0x%04x)\"\n\n#~ msgid \"Unknown decimal separator: '%s'\"\n#~ msgstr \"Onbekend decimaal scheidingsteken: '%s'\"\n\n#~ msgid \"Unknown escape sequence at character %d\"\n#~ msgstr \"Onbekende stuurcodereeks bij teken %d\"\n"
  },
  {
    "path": "po/pl.po",
    "content": "# Copyright (C) 2011 TigerVNC Team\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: pl\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2014-09-22 11:15+0000\\n\"\n\"PO-Revision-Date: 2009-03-25 21:26+0100\\n\"\n\"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\\n\"\n\"Language-Team: Polish <pl@li.org>\\n\"\n\"Language: pl\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:194\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:227\n#, fuzzy\nmsgid \"About\"\nmsgstr \"O programie...\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:103\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"O Przeglądarce VNC\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1086\n#, fuzzy\nmsgid \"About TigerVNC viewer...\"\nmsgstr \"O Przeglądarce VNC\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:86\nmsgid \"About...\"\nmsgstr \"O programie...\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:704\nmsgid \"Accept clipboard from server\"\nmsgstr \"Akceptuj schowek z serwera\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:327\nmsgid \"Adjusting window size to avoid accidental full screen request\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:563\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Zezwolenie na kompresję JPEG:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1070\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:648\n#, fuzzy\nmsgid \"Authentication\"\nmsgstr \"Uwierzytelnianie VNC\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:89\n#, fuzzy\nmsgid \"Authentication cancelled\"\nmsgstr \"Uwierzytelnianie VNC\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:437\nmsgid \"Auto select\"\nmsgstr \"Automatyczne wykrywanie\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:651\n#, c-format\nmsgid \"Bad Name/Value pair on line: %d in file: %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Win32PixelBuffer.cxx:92\nmsgid \"BitBlt failed\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:91\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:221\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:83\nmsgid \"Cancel\"\nmsgstr \"Anuluj\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:116\nmsgid \"CleanupSignalHandler called\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:222\nmsgid \"Close\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:499\nmsgid \"Color level\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:421\n#, fuzzy\nmsgid \"Compression\"\nmsgstr \"Własny poziom kompresji:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:96\nmsgid \"Connect\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1085\nmsgid \"Connection info...\"\nmsgstr \"Informacje o połączeniu...\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:362\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:404\n#, c-format\nmsgid \"\"\n\"Could not convert the parameter-name %s to wchar_t* when reading from the \"\n\"Registry, the buffersize is to small.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:302\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:340\n#, c-format\nmsgid \"\"\n\"Could not convert the parameter-name %s to wchar_t* when writing to the \"\n\"Registry, the buffersize is to small.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:318\n#, c-format\nmsgid \"\"\n\"Could not convert the parameter-value %s to wchar_t* when writing to the \"\n\"Registry, the buffersize is to small.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:381\n#, c-format\nmsgid \"\"\n\"Could not convert the parameter-value for %s to utf8 char* when reading from \"\n\"the Registry, the buffer dest is to small.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:256\n#, c-format\nmsgid \"Could not create VNC home directory: %s.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:251\nmsgid \"Could not create VNC home directory: can't obtain home directory path.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:310\n#, c-format\nmsgid \"Could not encode the parameter-value %s when writing to the Registry.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:613\n#, c-format\nmsgid \"\"\n\"Could not read the line(%d) in the configuration file,the buffersize is to \"\n\"small.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Win32PixelBuffer.cxx:80\nmsgid \"CreateCompatibleDC failed\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1068\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:550\nmsgid \"Custom compression level:\"\nmsgstr \"Własny poziom kompresji:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:283\nmsgid \"\"\n\"Decoding: The size of the buffer dest is to small, it needs to be 1 byte \"\n\"bigger.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:172\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1088\nmsgid \"Dismiss menu\"\nmsgstr \"Zwolnij menu\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:778\nmsgid \"Enable full-screen mode over all monitors\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:469\nmsgid \"Enabling continuous updates\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:200\n#, c-format\nmsgid \"\"\n\"Encoding backslash: The size of the buffer dest is to small, it needs to be \"\n\"more than %d bytes bigger.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:214\n#, c-format\nmsgid \"\"\n\"Encoding escape sequence: The size of the buffer dest is to small, it needs \"\n\"to be more than %d bytes bigger.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:234\n#, c-format\nmsgid \"\"\n\"Encoding normal character: The size of the buffer dest is to small, it needs \"\n\"to be more than %d bytes bigger.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:595\nmsgid \"Encryption\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:503\n#, c-format\nmsgid \"Error(%d) closing key:  Software\\\\TigerVNC\\\\vncviewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:455\n#, c-format\nmsgid \"Error(%d) closing key: Software\\\\TigerVNC\\\\vncviewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:434\n#, c-format\nmsgid \"Error(%d) creating key: Software\\\\TigerVNC\\\\vncviewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:471\n#, c-format\nmsgid \"Error(%d) opening key: Software\\\\TigerVNC\\\\vncviewer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:373\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:415\n#, c-format\nmsgid \"Error(%d) reading %s from Registry.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:348\n#, c-format\nmsgid \"Error(%d) writing %d(REG_DWORD) to Registry.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:326\n#, c-format\nmsgid \"Error(%d) writing %s(REG_SZ) to Registry.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OSXPixelBuffer.cxx:50\n#: /home/ossman/devel/tigervnc/vncviewer/FLTKPixelBuffer.cxx:33\nmsgid \"Error: Not enough memory for framebuffer\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/X11PixelBuffer.cxx:69\nmsgid \"Error: couldn't find suitable pixmap format\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/X11PixelBuffer.cxx:60\nmsgid \"Error: display lacks pixmap format for default depth\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/X11PixelBuffer.cxx:78\nmsgid \"Error: only true colour displays supported\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1056\nmsgid \"Exit viewer\"\nmsgstr \"Zakończ przeglądarkę\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:588\nmsgid \"Failed to read configuration file, can't obtain home directory path.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:602\n#, c-format\nmsgid \"Failed to read configuration file, can't open %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:621\n#, c-format\nmsgid \"Failed to read line %d in file %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:528\nmsgid \"Failed to write configuration file, can't obtain home directory path.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:542\n#, c-format\nmsgid \"Failed to write configuration file, can't open %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:526\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:538\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:551\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:563\nmsgid \"Failure grabbing mouse\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:512\nmsgid \"Full (all available colors)\"\nmsgstr \"Pełny (wszystkie dostępne kolory)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1059\nmsgid \"Full screen\"\nmsgstr \"Pełny ekran\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:770\nmsgid \"Full-screen mode\"\nmsgstr \"Tryb pełnoekranowy\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:230\nmsgid \"Hide\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:238\nmsgid \"Hide Others\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:177\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:690\n#, fuzzy\nmsgid \"Input\"\nmsgstr \"Wejścia:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:510\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:384\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:106\nmsgid \"Invalid geometry specified!\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Invalid parameter name on line: %d in file: %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/DesktopWindow.cxx:797\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:631\n#, c-format\nmsgid \"\"\n\"Line 1 in file %s\\n\"\n\"must contain the TigerVNC configuration file identifier string:\\n\"\n\"\\\"%s\\\"\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:209\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:478\n#, c-format\nmsgid \"Listening on port %d\\n\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:69\nmsgid \"Load...\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:526\nmsgid \"Low (64 colors)\"\nmsgstr \"Niski (64 kolory)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:519\nmsgid \"Medium (256 colors)\"\nmsgstr \"Średni (256 kolorów)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:725\nmsgid \"Menu key\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:791\n#, fuzzy\nmsgid \"Misc.\"\nmsgstr \"Różne:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1026\n#, c-format\nmsgid \"Multiple characters given for key code %d (0x%04x): '%s'\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:218\nmsgid \"No\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:688\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:690\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:701\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:765\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:739\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:703\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:606\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:659\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:727\nmsgid \"None\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:220\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:88\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:74\nmsgid \"Opening password file failed\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1084\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:64\nmsgid \"Options...\"\nmsgstr \"Opcje...\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:463\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:464\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:722\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:87\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:102\nmsgid \"Password:\"\nmsgstr \"Hasło:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:625\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:632\nmsgid \"Path to X509 CRL file\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:188\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:449\nmsgid \"Preferred encoding\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:214\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:233\nmsgid \"Quit\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1082\nmsgid \"Refresh screen\"\nmsgstr \"Odśwież ekran\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:199\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:749\nmsgid \"Resize remote session on connect\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:762\nmsgid \"Resize remote session to the local window\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1062\nmsgid \"Resize window to session\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:74\nmsgid \"Save As...\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:741\nmsgid \"Screen\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:580\nmsgid \"Security\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Win32PixelBuffer.cxx:83\nmsgid \"SelectObject failed\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1075\n#, c-format\nmsgid \"Send %s\"\nmsgstr \"Wyślij %s\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1080\nmsgid \"Send Ctrl-Alt-Del\"\nmsgstr \"Wyślij Ctrl-Alt-Del\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:710\nmsgid \"Send clipboard to server\"\nmsgstr \"Wyślij schowek do serwera\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:716\n#, fuzzy\nmsgid \"Send primary selection and cut buffer as clipboard\"\nmsgstr \"Wyślij główny wybór i bufor wycinania jako schowek\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:237\nmsgid \"Services\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:319\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:799\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Współdzielone (nie rozłączaj inne przeglądarki)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:239\nmsgid \"Show All\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:805\nmsgid \"Show dot when no cursor\"\nmsgstr \"Wyświetl kropkę, kiedy nie ma kursora\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:182\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:665\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:618\nmsgid \"TLS with X509 certificates\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:612\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:448\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:497\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:561\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:701\n#, c-format\nmsgid \"The parameterArray contains a object of a invalid type at line %d.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:664\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:680\n#, c-format\nmsgid \"The value of the parameter %s on line %d in file %s is invalid.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:539\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:561\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:210\n#, fuzzy\nmsgid \"TigerVNC Viewer\"\nmsgstr \"O Przeglądarce VNC\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:80\n#, fuzzy, c-format\nmsgid \"\"\n\"TigerVNC Viewer %d-bit v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.txt)\\n\"\n\"See http://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"Przeglądarka TigerVNC %d-bit wersja %s (%s)\\n\"\n\"%s\\n\"\n\"Copyright (C) 1999-2011 TigerVNC Team and many others (see README.txt)\\n\"\n\"Zobacz http://www.tigervnc.org, aby dowiedzieć się więcej o TigerVNC.\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1004\n#, c-format\nmsgid \"Unknown FLTK key code %d (0x%04x)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:878\n#, c-format\nmsgid \"Unknown decimal separator: '%s'\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/parameters.cxx:271\n#, c-format\nmsgid \"Unknown escape sequence at character %d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:430\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:437\nmsgid \"Unknown rect encoding\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:429\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:436\n#, c-format\nmsgid \"Unknown rect encoding %d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:671\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:99\nmsgid \"Username:\"\nmsgstr \"Nazwa użytkownika:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:573\n#, c-format\nmsgid \"Using %s encoding\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/X11PixelBuffer.cxx:80\n#, c-format\nmsgid \"Using default colormap and visual, %sdepth %d.\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:620\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:42\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"Przeglądarka VNC: szczegóły połączenia\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:57\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"Przeglądarka VNC: opcje połączenia\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:86\n#: /home/ossman/devel/tigervnc/vncviewer/UserDialog.cxx:96\nmsgid \"VNC authentication\"\nmsgstr \"Uwierzytelnianie VNC\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Viewport.cxx:1176\nmsgid \"VNC connection info\"\nmsgstr \"Informacje o połączeniu VNC\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:49\n#: /home/ossman/devel/tigervnc/vncviewer/ServerDialog.cxx:54\nmsgid \"VNC server:\"\nmsgstr \"Serwer VNC:\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:533\nmsgid \"Very low (8 colors)\"\nmsgstr \"Bardzo niski (8 kolorów)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:698\n#, fuzzy\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Tylko wyświetlaj (ignoruj mysz i klawiaturę)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/vncviewer.cxx:219\nmsgid \"Yes\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:111\n#, c-format\nmsgid \"connected to host %s port %d\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:563\nmsgid \"disabled\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/CConn.cxx:563\nmsgid \"enabled\"\nmsgstr \"\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:556\n#, fuzzy\nmsgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\nmsgstr \"poziom (1=szybki, 9=najlepszy)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/OptionsDialog.cxx:569\n#, fuzzy\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"jakość (1=słaba, 9=najlepsza)\"\n\n#: /home/ossman/devel/tigervnc/vncviewer/Win32PixelBuffer.cxx:63\nmsgid \"unable to create DIB section\"\nmsgstr \"\"\n\n#~ msgid \"About VNCviewer...\"\n#~ msgstr \"O VNCviewer...\"\n\n#~ msgid \"\"\n#~ \"Desktop name: %.80s\\n\"\n#~ \"Host: %.80s port: %d\\n\"\n#~ \"Size: %d x %d\\n\"\n#~ \"Pixel format: %s\\n\"\n#~ \"(server default %s)\\n\"\n#~ \"Requested encoding: %s\\n\"\n#~ \"Last used encoding: %s\\n\"\n#~ \"Line speed estimate: %d kbit/s\\n\"\n#~ \"Protocol version: %d.%d\\n\"\n#~ \"Security method: %s\\n\"\n#~ msgstr \"\"\n#~ \"Nazwa pulpitu: %.80s\\n\"\n#~ \"Komputer: %.80s port: %d\\n\"\n#~ \"Rozmiar: %d x %d\\n\"\n#~ \"Format pikseli: %s\\n\"\n#~ \"(domyślne serwera %s)\\n\"\n#~ \"Żądane kodowanie: %s\\n\"\n#~ \"Ostatnio używane kodowanie: %s\\n\"\n#~ \"Szacowana prędkość łącza: %d kbit/s\\n\"\n#~ \"Wersja protokołu: %d.%d\\n\"\n#~ \"Metoda bezpieczeństwa: %s\\n\"\n\n#~ msgid \"Encoding and Color Level:\"\n#~ msgstr \"Kodowanie i poziom kolorów:\"\n\n#~ msgid \"New connection...\"\n#~ msgstr \"Nowe połączenie...\"\n\n#~ msgid \"Render cursor locally\"\n#~ msgstr \"Renderuj kursor lokalnie\"\n\n#~ msgid \"TigerVNC: %.240s\"\n#~ msgstr \"TigerVNC: %.240s\"\n\n#~ msgid \"VNC Menu\"\n#~ msgstr \"Menu VNC\"\n"
  },
  {
    "path": "po/pt_BR.po",
    "content": "# Brazilian Portuguese translation of tigervnc.\n# Copyright (C) 2019 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Rafael Fontenelle <rafaelff@gnome.org>, 2015-2019.\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.9.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2019-10-18 10:14+0200\\n\"\n\"PO-Revision-Date: 2019-10-29 05:03-0200\\n\"\n\"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\\n\"\n\"Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge.net>\\n\"\n\"Language: pt_BR\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\"X-Generator: Virtaal 1.0.0-beta1\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\n#: vncviewer/CConn.cxx:99\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Conectado ao soquete %s\"\n\n#: vncviewer/CConn.cxx:106\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Conectado ao host %s porta %d\"\n\n#: vncviewer/CConn.cxx:157\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Nome do desktop: %.80s\"\n\n#: vncviewer/CConn.cxx:162\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Host: %.80s porta: %d\"\n\n#: vncviewer/CConn.cxx:167\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Tamanho: %d x %d\"\n\n#: vncviewer/CConn.cxx:175\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Formato de pixel: %s\"\n\n#: vncviewer/CConn.cxx:182\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(padrão do servidor %s)\"\n\n#: vncviewer/CConn.cxx:187\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Codificação solicitada: %s\"\n\n#: vncviewer/CConn.cxx:192\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Última codificação usada: %s\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Velocidade estimada da linha: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:202\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Versão do protocolo: %d.%d\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Método de segurança: %s\"\n\n#: vncviewer/CConn.cxx:324\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"SetDesktopSize falhou: %d\"\n\n#: vncviewer/CConn.cxx:372\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"SetColourMapEntries inválido do servidor!\"\n\n#: vncviewer/CConn.cxx:480\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Taxa de transferência %d kbit/s - alteração para qualidade %d\"\n\n#: vncviewer/CConn.cxx:502\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Taxa de transferência %d kbit/s - cor total agora habilitado\"\n\n#: vncviewer/CConn.cxx:505\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Taxa de transferência %d kbit/s - cor total agora está desabilitado\"\n\n#: vncviewer/CConn.cxx:531\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Usando formato de pixel %s\"\n\n#: vncviewer/DesktopWindow.cxx:122\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Geometria inválida especificada!\"\n\n#: vncviewer/DesktopWindow.cxx:495\nmsgid \"Adjusting window size to avoid accidental full screen request\"\nmsgstr \"Ajustando tamanho de janela para evitar solicitação de tela cheia acidental\"\n\n#: vncviewer/DesktopWindow.cxx:539\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Pressione %s para abrir o menu de contexto\"\n\n#: vncviewer/DesktopWindow.cxx:836 vncviewer/DesktopWindow.cxx:844\n#: vncviewer/DesktopWindow.cxx:864\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Falha ao se conectar com o teclado\"\n\n#: vncviewer/DesktopWindow.cxx:938\nmsgid \"Failure grabbing mouse\"\nmsgstr \"Falha ao se conectar com o mouse\"\n\n#: vncviewer/DesktopWindow.cxx:1162\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Layout de tela inválida computada para solicitação de redimensionamento!\"\n\n#: vncviewer/OptionsDialog.cxx:57\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"Visualizador VNC: Opções da conexão\"\n\n#: vncviewer/OptionsDialog.cxx:83 vncviewer/ServerDialog.cxx:91\n#: vncviewer/vncviewer.cxx:282\nmsgid \"Cancel\"\nmsgstr \"Cancelar\"\n\n#: vncviewer/OptionsDialog.cxx:88 vncviewer/vncviewer.cxx:281\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: vncviewer/OptionsDialog.cxx:423\nmsgid \"Compression\"\nmsgstr \"Compressão\"\n\n#: vncviewer/OptionsDialog.cxx:439\nmsgid \"Auto select\"\nmsgstr \"Seleção automática\"\n\n#: vncviewer/OptionsDialog.cxx:451\nmsgid \"Preferred encoding\"\nmsgstr \"Codificação preferida\"\n\n#: vncviewer/OptionsDialog.cxx:499\nmsgid \"Color level\"\nmsgstr \"Profundidade de cores\"\n\n#: vncviewer/OptionsDialog.cxx:510\nmsgid \"Full (all available colors)\"\nmsgstr \"Completo (todas as cores)\"\n\n#: vncviewer/OptionsDialog.cxx:517\nmsgid \"Medium (256 colors)\"\nmsgstr \"Médio (256 cores)\"\n\n#: vncviewer/OptionsDialog.cxx:524\nmsgid \"Low (64 colors)\"\nmsgstr \"Baixo (64 cores)\"\n\n#: vncviewer/OptionsDialog.cxx:531\nmsgid \"Very low (8 colors)\"\nmsgstr \"Muito baixo (8 cores)\"\n\n#: vncviewer/OptionsDialog.cxx:548\nmsgid \"Custom compression level:\"\nmsgstr \"Compressão personalizada:\"\n\n#: vncviewer/OptionsDialog.cxx:554\nmsgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\nmsgstr \"nível (1=rápido, 6=o melhor [4-6 raramente úteis])\"\n\n#: vncviewer/OptionsDialog.cxx:561\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Permite compressão JPEG:\"\n\n#: vncviewer/OptionsDialog.cxx:567\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"qualidade (0=ruim, 9=o melhor)\"\n\n#: vncviewer/OptionsDialog.cxx:578\nmsgid \"Security\"\nmsgstr \"Segurança\"\n\n#: vncviewer/OptionsDialog.cxx:593\nmsgid \"Encryption\"\nmsgstr \"Criptografia\"\n\n#: vncviewer/OptionsDialog.cxx:604 vncviewer/OptionsDialog.cxx:657\n#: vncviewer/OptionsDialog.cxx:737\nmsgid \"None\"\nmsgstr \"Nenhum\"\n\n#: vncviewer/OptionsDialog.cxx:610\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS com certificados anônimos\"\n\n#: vncviewer/OptionsDialog.cxx:616\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS com certificados X509\"\n\n# AC = Autoridade Certificadora\n#: vncviewer/OptionsDialog.cxx:623\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Caminho para o certificado X509 de AC\"\n\n#: vncviewer/OptionsDialog.cxx:630\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Caminho para o arquivo X509 de CRL\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Authentication\"\nmsgstr \"Autenticação\"\n\n#: vncviewer/OptionsDialog.cxx:663\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"VNC padrão (inseguro sem criptografia)\"\n\n#: vncviewer/OptionsDialog.cxx:669\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Usuário e senha (inseguro sem criptografia)\"\n\n#: vncviewer/OptionsDialog.cxx:688\nmsgid \"Input\"\nmsgstr \"Entrada\"\n\n#: vncviewer/OptionsDialog.cxx:696\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Visualizar apenas (ignora mouse e teclado)\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"Accept clipboard from server\"\nmsgstr \"Aceitar área de transferência do servidor\"\n\n#: vncviewer/OptionsDialog.cxx:710\nmsgid \"Also set primary selection\"\nmsgstr \"Também enviar seleção primária\"\n\n#: vncviewer/OptionsDialog.cxx:717\nmsgid \"Send clipboard to server\"\nmsgstr \"Enviar área de transferência para o servidor\"\n\n#: vncviewer/OptionsDialog.cxx:725\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Enviar seleção primária como área de transferência\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Passar teclas de sistema diretamente para o servidor (tela cheia)\"\n\n#: vncviewer/OptionsDialog.cxx:735\nmsgid \"Menu key\"\nmsgstr \"Tecla de menu\"\n\n#: vncviewer/OptionsDialog.cxx:751\nmsgid \"Screen\"\nmsgstr \"Tela\"\n\n#: vncviewer/OptionsDialog.cxx:759\nmsgid \"Resize remote session on connect\"\nmsgstr \"Redimensionar a sessão remota ao conectar\"\n\n#: vncviewer/OptionsDialog.cxx:772\nmsgid \"Resize remote session to the local window\"\nmsgstr \"Redimensionar a sessão remota para a janela local\"\n\n#: vncviewer/OptionsDialog.cxx:778\nmsgid \"Full-screen mode\"\nmsgstr \"Modo tela cheia\"\n\n#: vncviewer/OptionsDialog.cxx:784\nmsgid \"Enable full-screen mode over all monitors\"\nmsgstr \"Ativar o modo de tela cheia em todos os monitores\"\n\n#: vncviewer/OptionsDialog.cxx:793\nmsgid \"Misc.\"\nmsgstr \"Diversos\"\n\n#: vncviewer/OptionsDialog.cxx:801\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Compartilhado (não desconecta outros visualizadores)\"\n\n#: vncviewer/OptionsDialog.cxx:807\nmsgid \"Show dot when no cursor\"\nmsgstr \"Mostrar ponto quando estiver sem mouse\"\n\n#: vncviewer/ServerDialog.cxx:42\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"Visualizador VNC: Detalhes da conexão\"\n\n#: vncviewer/ServerDialog.cxx:49 vncviewer/ServerDialog.cxx:54\nmsgid \"VNC server:\"\nmsgstr \"Servidor VNC:\"\n\n#: vncviewer/ServerDialog.cxx:64\nmsgid \"Options...\"\nmsgstr \"Opções...\"\n\n#: vncviewer/ServerDialog.cxx:69\nmsgid \"Load...\"\nmsgstr \"Carregar...\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"Save As...\"\nmsgstr \"Salvar como...\"\n\n#: vncviewer/ServerDialog.cxx:86\nmsgid \"About...\"\nmsgstr \"Sobre...\"\n\n#: vncviewer/ServerDialog.cxx:96\nmsgid \"Connect\"\nmsgstr \"Conectar\"\n\n#: vncviewer/ServerDialog.cxx:137 vncviewer/ServerDialog.cxx:171\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Configuração do TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:138\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Selecionar um arquivo de configuração do TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:172\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Salvar a configuração do TigerVNC para arquivo\"\n\n#: vncviewer/ServerDialog.cxx:197\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s já existe. Você deseja sobrescrevê-lo?\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:279\nmsgid \"No\"\nmsgstr \"Não\"\n\n#: vncviewer/ServerDialog.cxx:198\nmsgid \"Overwrite\"\nmsgstr \"Sobrescrever\"\n\n#: vncviewer/UserDialog.cxx:85\nmsgid \"Opening password file failed\"\nmsgstr \"A abertura do arquivo de senha falhou\"\n\n#: vncviewer/UserDialog.cxx:105\nmsgid \"VNC authentication\"\nmsgstr \"Autenticação VNC\"\n\n#: vncviewer/UserDialog.cxx:112\nmsgid \"This connection is secure\"\nmsgstr \"Essa conexão é segura\"\n\n#: vncviewer/UserDialog.cxx:116\nmsgid \"This connection is not secure\"\nmsgstr \"Essa conexão não é segura\"\n\n#: vncviewer/UserDialog.cxx:133\nmsgid \"Username:\"\nmsgstr \"Nome de usuário:\"\n\n#: vncviewer/UserDialog.cxx:146\nmsgid \"Password:\"\nmsgstr \"Senha:\"\n\n#: vncviewer/UserDialog.cxx:185\nmsgid \"Authentication cancelled\"\nmsgstr \"Autenticação cancelada\"\n\n#: vncviewer/Viewport.cxx:389\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Falha ao atualizar estado do LED do teclado: %lu\"\n\n#: vncviewer/Viewport.cxx:395 vncviewer/Viewport.cxx:401\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"Falha ao atualizar estado do LED do teclado: %d\"\n\n#: vncviewer/Viewport.cxx:431\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Falha ao atualizar estado do LED do teclado\"\n\n#: vncviewer/Viewport.cxx:458 vncviewer/Viewport.cxx:466\n#: vncviewer/Viewport.cxx:483\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Falha ao obter estado do LED do teclado: %d\"\n\n#: vncviewer/Viewport.cxx:833\nmsgid \"No key code specified on key press\"\nmsgstr \"Nenhum código de tecla especificado no pressionamento de tecla\"\n\n#: vncviewer/Viewport.cxx:982\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Nenhum código de scan para a tecla virtual estendida 0x%02x\"\n\n#: vncviewer/Viewport.cxx:984\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Nenhum código de scan para a tecla virtual 0x%02x\"\n\n#: vncviewer/Viewport.cxx:990\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"código de scan inválido 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1020\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Nenhum símbolo para a tecla virtual estendida 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1022\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Nenhum símbolo para a tecla virtual 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1115\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"Nenhum símbolo para a tecla virtual 0x%02x (no estado atual)\"\n\n#: vncviewer/Viewport.cxx:1148\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Nenhum símbolo para a tecla virtual %d (no estado atual)\"\n\n#: vncviewer/Viewport.cxx:1199\nmsgctxt \"ContextMenu|\"\nmsgid \"E&xit viewer\"\nmsgstr \"&Sair do visualizador\"\n\n#: vncviewer/Viewport.cxx:1202\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Tela cheia\"\n\n#: vncviewer/Viewport.cxx:1205\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Minimi&zar\"\n\n#: vncviewer/Viewport.cxx:1207\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Redimensionar a &janela para a sessão\"\n\n#: vncviewer/Viewport.cxx:1212\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:1215\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1221\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"Enviar %s\"\n\n#: vncviewer/Viewport.cxx:1227\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Enviar Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:1230\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&Atualizar tela\"\n\n#: vncviewer/Viewport.cxx:1233\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Opções...\"\n\n#: vncviewer/Viewport.cxx:1235\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&Informação de conexão...\"\n\n#: vncviewer/Viewport.cxx:1237\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"Sobre o visualizador &TigerVNC...\"\n\n#: vncviewer/Viewport.cxx:1240\nmsgctxt \"ContextMenu|\"\nmsgid \"Dismiss &menu\"\nmsgstr \"Recusar &menu\"\n\n#: vncviewer/Viewport.cxx:1329\nmsgid \"VNC connection info\"\nmsgstr \"Informação de conexão VNC...\"\n\n#: vncviewer/parameters.cxx:278 vncviewer/parameters.cxx:312\n#, c-format\nmsgid \"The name of the parameter %s was too large to write to the registry\"\nmsgstr \"O nome do parâmetro %s era grande demais ser escrito no registro\"\n\n#: vncviewer/parameters.cxx:284 vncviewer/parameters.cxx:291\n#, c-format\nmsgid \"The parameter %s was too large to write to the registry\"\nmsgstr \"O parâmetro %s era grande demais para ser escrito no registro\"\n\n#: vncviewer/parameters.cxx:297 vncviewer/parameters.cxx:318\n#, c-format\nmsgid \"Failed to write parameter %s of type %s to the registry: %ld\"\nmsgstr \"Falha ao escrever parâmetro %s do tipo %s no registro: %ld\"\n\n#: vncviewer/parameters.cxx:334 vncviewer/parameters.cxx:377\n#, c-format\nmsgid \"The name of the parameter %s was too large to read from the registry\"\nmsgstr \"O nome do parâmetro %s era grande demais ser lido do registro\"\n\n#: vncviewer/parameters.cxx:346 vncviewer/parameters.cxx:386\n#, c-format\nmsgid \"Failed to read parameter %s from the registry: %ld\"\nmsgstr \"Falha ao ler parâmetro %s do registro: %ld\"\n\n#: vncviewer/parameters.cxx:357\n#, c-format\nmsgid \"The parameter %s was too large to read from the registry\"\nmsgstr \"O parâmetro %s era grande demais para ser lido do registro\"\n\n#: vncviewer/parameters.cxx:406\n#, c-format\nmsgid \"Failed to create registry key: %ld\"\nmsgstr \"Falha ao criar chave de registro: %ld\"\n\n#: vncviewer/parameters.cxx:420 vncviewer/parameters.cxx:469\n#: vncviewer/parameters.cxx:532 vncviewer/parameters.cxx:666\n#, c-format\nmsgid \"Unknown parameter type for parameter %s\"\nmsgstr \"Tipo de parâmetro desconhecido para o parâmetro %s\"\n\n#: vncviewer/parameters.cxx:427 vncviewer/parameters.cxx:476\n#, c-format\nmsgid \"Failed to close registry key: %ld\"\nmsgstr \"Falha ao fechar chave de registro: %ld\"\n\n#: vncviewer/parameters.cxx:443\n#, c-format\nmsgid \"Failed to open registry key: %ld\"\nmsgstr \"Falha ao abrir chave de registro: %ld\"\n\n#: vncviewer/parameters.cxx:500\nmsgid \"Failed to write configuration file, can't obtain home directory path.\"\nmsgstr \"Não foi possível escrever o arquivo de configuração, não foi possível obter o caminho do diretório HOME.\"\n\n#: vncviewer/parameters.cxx:514\n#, c-format\nmsgid \"Failed to write configuration file, can't open %s: %s\"\nmsgstr \"Não foi possível escrever o arquivo de configuração, não foi possível abrir %s: %s\"\n\n#: vncviewer/parameters.cxx:559\nmsgid \"Failed to read configuration file, can't obtain home directory path.\"\nmsgstr \"Não foi possível ler o arquivo de configuração, não foi possível obter o caminho do diretório HOME.\"\n\n#: vncviewer/parameters.cxx:573\n#, c-format\nmsgid \"Failed to read configuration file, can't open %s: %s\"\nmsgstr \"Não foi possível ler o arquivo de configuração, não foi possível abrir %s: %s\"\n\n#: vncviewer/parameters.cxx:586 vncviewer/parameters.cxx:591\n#: vncviewer/parameters.cxx:616 vncviewer/parameters.cxx:629\n#: vncviewer/parameters.cxx:645\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"Falha ao ler a linha %d no arquivo %s: %s\"\n\n#: vncviewer/parameters.cxx:592\nmsgid \"Line too long\"\nmsgstr \"Linha longa demais\"\n\n#: vncviewer/parameters.cxx:599\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"O arquivo de configuração %s está em um formato inválido\"\n\n#: vncviewer/parameters.cxx:617\nmsgid \"Invalid format\"\nmsgstr \"Formato inválido\"\n\n#: vncviewer/parameters.cxx:630 vncviewer/parameters.cxx:646\nmsgid \"Invalid format or too large value\"\nmsgstr \"Formato inválido ou valor grande demais\"\n\n#: vncviewer/parameters.cxx:673\n#, c-format\nmsgid \"Unknown parameter %s on line %d in file %s\"\nmsgstr \"Parâmetro %s desconhecido na linha %d no arquivo %s\"\n\n#: vncviewer/vncviewer.cxx:100\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer %d-bit v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"Visualizador TigerVNC %d bits v%s\\n\"\n\"Compilado em: %s\\n\"\n\"Copyright (C) 1999-%d Equipe TigerVNC e muitos outros (veja README.rst)\\n\"\n\"Veja https://www.tigervnc.org para informação sobre o TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:127\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"Sobre o Visualizador TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:140\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Erro interno no FLTK. Saindo.\"\n\n#: vncviewer/vncviewer.cxx:158 vncviewer/vncviewer.cxx:170\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Erro ao iniciar novo Visualizador TigerVNC: %s\"\n\n#: vncviewer/vncviewer.cxx:179\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"Sinal de terminação %d foi recebido. Visualizador TigerVNC vai fechar agora.\"\n\n#: vncviewer/vncviewer.cxx:271 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"Visualizador TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:280\nmsgid \"Yes\"\nmsgstr \"Sim\"\n\n#: vncviewer/vncviewer.cxx:283\nmsgid \"Close\"\nmsgstr \"Fechar\"\n\n#: vncviewer/vncviewer.cxx:288\nmsgid \"About\"\nmsgstr \"Sobre\"\n\n#: vncviewer/vncviewer.cxx:291\nmsgid \"Hide\"\nmsgstr \"Ocultar\"\n\n#: vncviewer/vncviewer.cxx:294\nmsgid \"Quit\"\nmsgstr \"Sair\"\n\n#: vncviewer/vncviewer.cxx:298\nmsgid \"Services\"\nmsgstr \"Serviços\"\n\n#: vncviewer/vncviewer.cxx:299\nmsgid \"Hide Others\"\nmsgstr \"Ocultar Outros\"\n\n#: vncviewer/vncviewer.cxx:300\nmsgid \"Show All\"\nmsgstr \"Exibir Todos\"\n\n#: vncviewer/vncviewer.cxx:309\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Arquivo\"\n\n#: vncviewer/vncviewer.cxx:312\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Nova Conexão\"\n\n#: vncviewer/vncviewer.cxx:324\nmsgid \"Could not create VNC home directory: can't obtain home directory path.\"\nmsgstr \"Não foi possível criar o diretório HOME do VNC: não foi possível obter o caminho do diretório HOME.\"\n\n#: vncviewer/vncviewer.cxx:329\n#, c-format\nmsgid \"Could not create VNC home directory: %s.\"\nmsgstr \"Não foi possível criar um diretório HOME do VNC: %s.\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:602 vncviewer/vncviewer.cxx:604\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Os parâmetros -listen e -via são incompatíveis\"\n\n#: vncviewer/vncviewer.cxx:619\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Ouvindo na porta %d\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"Visualização de área de trabalho remota\"\n\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Conecte a um servidor VNC e exiba a área de trabalho remota\"\n\n#: vncviewer/vncviewer.desktop.in.in:7\nmsgid \"tigervnc\"\nmsgstr \"tigervnc\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Ativando atualizações contínuas\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"desativado\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"ativado\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Usando codificação %s\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"Memória insuficiente para o framebuffer\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"Não foi possível criar dispositivo de framebuffer\"\n\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"Não foi possível criar bitmap de framebuffer\"\n\n#~ msgid \"Unable to create platform specific framebuffer: %s\"\n#~ msgstr \"Não foi possível criar framebuffer específico da plataforma: %s\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"Usando framebuffer independente de plataforma\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"não foi possível criar seção DIB\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"CreateCompatibleDC falhou\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"SelectObject falhou\"\n\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"BitBlt falhou\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"Tela carece de formato de pixmap para profundidade padrão\"\n\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"Não foi possível localizar um formato de pixmap adequado\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"Apenas suporte a telas True Color\"\n\n#~ msgid \"Using default colormap and visual, TrueColor, depth %d.\"\n#~ msgstr \"Usando mapa de cores padrão e visual, TrueColor, profundidade %d.\"\n\n#~ msgid \"Could not create framebuffer image\"\n#~ msgstr \"Não foi possível criar imagem framebuffer\"\n\n#~ msgid \"Unknown encoding %d\"\n#~ msgstr \"Codificação %d desconhecida\"\n\n#~ msgid \"Unknown encoding\"\n#~ msgstr \"Codificação desconhecida\"\n\n#~ msgid \"Multiple characters given for key code %d (0x%04x): '%s'\"\n#~ msgstr \"Diversos caracteres fornecidos como código de chave %d (0x%04x): '%s'\"\n\n#~ msgid \"Unknown FLTK key code %d (0x%04x)\"\n#~ msgstr \"Código de chave FLTK desconhecido %d (0x%04x)\"\n\n#~ msgid \"Unknown decimal separator: '%s'\"\n#~ msgstr \"Separador decimal desconhecido:  '%s'\"\n\n#, fuzzy\n#~ msgid \"Unknown escape sequence at character %d\"\n#~ msgstr \"Separador decimal desconhecido:  '%s'\"\n\n#, fuzzy\n#~ msgid \"\"\n#~ \"Desktop name: %.80s\\n\"\n#~ \"Host: %.80s port: %d\\n\"\n#~ \"Size: %d x %d\\n\"\n#~ \"Pixel format: %s\\n\"\n#~ \"(server default %s)\\n\"\n#~ \"Requested encoding: %s\\n\"\n#~ \"Last used encoding: %s\\n\"\n#~ \"Line speed estimate: %d kbit/s\\n\"\n#~ \"Protocol version: %d.%d\\n\"\n#~ \"Security method: %s\\n\"\n#~ msgstr \"\"\n#~ \"Nome do desktop: %.80s\\n\"\n#~ \"Tamanho: %d x %d\\n\"\n#~ \"Formato do pixel: %s\\n\"\n#~ \"(padrão do servidor %s)\\n\"\n#~ \"Codificação solicitada: %s\\n\"\n#~ \"Última codificação usada: %s\\n\"\n#~ \"Velocidade estimada da linha: %d kbit/s\\n\"\n"
  },
  {
    "path": "po/ro.po",
    "content": "# Romanian translation for tigervnc.\n# Mesajele în limba română pentru pachetul tigervnc.\n# Copyright © 2022, 2024, 2025 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Copyright © 2022, 2024, 2025 TigerVNC Team and many others (see README.rst).\n#\n# Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>, 2022 - 2025.\n#\n# Cronologia traducerii fișierului „tigervnc”:\n# Traducerea inițială, făcută de R-GC, pentru versiunea tigervnc 1.11.90, mai-2022.\n# Actualizare a traducerii pentru versiunea 1.12.90, făcută de R-GC, dec-2022.\n# Actualizare a traducerii pentru versiunea 1.13.90, făcută de R-GC, iun-2024.\n# Actualizare a traducerii pentru versiunea 1.14.90, făcută de R-GC, ian-2025.\n# Actualizare a traducerii pentru versiunea 1.15.90, făcută de R-GC, noi-2025.\n# Actualizare a traducerii pentru versiunea Y, făcută de X, Z(anul).\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2025-11-13 13:46+0100\\n\"\n\"Last-Translator: Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>\\n\"\n\"Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\\n\"\n\"Language: ro\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n==0 || (n!=1 && n%100>=1 && n%100<=19) ? 1 : 2);\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Conectat la soclul %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Conectat la gazda %s portul %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nu s-a putut conecta la „%s”:\\n\"\n\"\\n\"\n\"%s\"\n\n# R-GC, scrie:\n# după revizarea fișierului, DȘ, spune:\n# „→ aici ar trebui lăsat „desktop”, din păcate nu avem termen mai bun,\n# iar traducerea curentă sună puțin hidos.\n# → caută și după celelalte apariții din cadrul fișierului”\n# ===\n# desktop = birou, masă de lucru, banc de lucru, pupitru\n# apare în dicționar eng. → rom.; și de mai\n# bine de 70 - 80 ani în traducerile făcute\n#  unor cărți, reviste și filme de renume; mai\n# nou, în traducerile de software, unde\n# traducătorii au înțeles că «desktop»,\n# poate să-li se pară „cool”, unora, dar, pînă\n# la urmă, rămîne să fie biroul nostru de\n# toate zilele.\n# Reamintesc faptul, binecunoscut,\n# dealtfel, că toate lucrurile din informatică,\n# au avut(au) ca inspirație, lucruri, activități\n# cotidiene din „lumea reală”; de exemplu:\n# fișier, arhivă, dosar, criptare/descriptare\n# comprimare/descomprimare, și multe\n# altele...\n# Deci, nu văd pentru ce trebuie ca\n# într-un software cu mesajele traduse, să\n# apară aberații de tipul: Desktop Virtual\n# din englezescul, Virtual Desktop;\n# Desktop (de) Gnome/KDE/LXDE/LXQt, etc\n# și nici bineînțeles „corespondentul”\n# românesc de, Remote Desktop =\n# Desktop la distanță\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Numele biroului: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Gazdă: %.80s port: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Dimensiune: %d x %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Format pixel: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Codificarea solicitată: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Ultima codificare utilizată: %s\"\n\n# R-GC, scrie:\n# după revizarea fișierului, DȘ, spune:\n# „→ aici parcă aș ajusta la „Estimarea vitezei\n# liniei”(legăturii/circuitului/firului)”\n# ===\n# Ok, sugestie aplicată\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Viteza estimată a conexiunii: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Versiunea protocolului: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Metoda de securitate: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Conexiunea a fost întreruptă de server înainte ca sesiunea să poată fi stabilită.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Autentificarea a eșuat: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Autentificarea cu serverul a eșuat. Motivul dat de server:\\n\"\n\"\\n\"\n\"%s\"\n\n# R-GC, scrie:\n# am tradus acest mesaj, și următoarele două mesaje, în baza comentariului făcut\n# de autori în codul sursă:\n# „autoSelectFormatAndEncoding() chooses the format and encoding appropriate to the connection speed:\n# //\n# -   First we wait for at least one second of bandwidth measurement.\n# //\n# -   Above 16Mbps (i.e. LAN), we choose the second highest JPEG quality, which should be perceptually lossless.\n# //\n# -   If the bandwidth is below that, we choose a more lossy JPEG quality.\n# //\n# //   If the bandwidth drops below 256 Kbps, we switch to palette mode.\n# //\n# Note: The system here is fairly arbitrary and should be replaced  with something more intelligent at the server end.”\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Lățimea de bandă este de %d kbit/s - se trece la calitatea %d de JPEG\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Lățimea de bandă este de %d kbit/s - nivelul de profunditate al culorii → «deplin», este acum activat acum\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Lățimea de bandă este de %d kbit/s - nivelul de profunditate al culorii → «deplin», este dezactivat acum\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Se utilizează formatul de pixel %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Geometria specificată nu este validă!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Se reduce dimensiunea ferestrei pentru a se potrivi pe monitorul actual\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"Apăsați %sM pentru a deschide meniul contextual\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s - TigerVNC (tastatură preluată)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s - TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Se ajustează dimensiunea ferestrei pentru a evita solicitarea accidentală a ecranului complet\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"Apăsați %sEnter pentru a ieși din modul de ecran complet\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"Eșec la preluarea controlului tastaturii\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"Apăsați %s pentru a elibera controlul tastaturii din sesiune\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Aspect nevalid al ecranului calculat pentru cererea de redimensionare!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Stare nevalidă pentru emularea cu trei butoane\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Niciun cod de scanare pentru tasta virtuală extinsă 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Niciun cod de scanare pentru tasta virtuală 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Cod de scanare nevalid 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Niciun simbol pentru tasta virtuală extinsă 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Niciun simbol pentru tasta virtuală 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Nu s-a putut actualiza starea LED-ului tastaturii: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Niciun simbol pentru codul tastei %d (în starea curentă)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Nu s-a putut obține starea LED-ului tastaturii: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Nu s-a putut actualiza starea LED-ului tastaturii\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Nu s-a putut obține configurația monitorului sistemului\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Indexul de monitor %d nu există\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"Opțiuni TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Anulare\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"Ok\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"Comprimare\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"Selectare automată\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"Permite comprimarea JPEG\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"Codificarea preferată\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"Nivelul de profunditate al culorii\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"Deplin\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"Mediu\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"Scăzut\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"Foarte scăzut\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"Nivel de comprimare personalizat\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"nivel (0 = rapid, 9 = cel mai bun)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"Nivel de calitate\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"calitate (0 = redusă, 9 = cea mai bună)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"Securitate\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"Criptare\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"Niciuna\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS cu certificate anonime\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS cu certificate X509\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Ruta către certificatul CA X509\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Ruta către fișierul CRL X509\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"Autentificare\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"VNC standard (nesigur fără criptare)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Nume de utilizator și parolă (nesigure fără criptare)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"Intrare\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Numai vizualizare (se ignoră mouse-ul și tastatura)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"Mouse\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Emulează butonul din mijloc al mouse-ului\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Afișează cursorul local atunci când nu este furnizat de server\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"Tipul cursorului\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"Punct „Dot”\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"Sistem\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"Tastatură\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"Trimite întotdeauna toate intrările de la tastatură în modul de ecran complet\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"Clipboard\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"Acceptă clipboard-ul de pe server\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"Stabilește, de asemenea, selecția principală\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"Trimite clipboard-ul la server\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Trimite selecția principală ca clipboard\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"Taste de comenzi rapide\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"Taste modificatoare pentru comenzi rapide de la tastatură:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Shift\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Shift\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Opțiune\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"Afișare\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"Modul de afișare\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"În fereastră\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"Ecran complet pe monitorul actual\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"Ecran complet pe toate monitoare\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Ecran complet pe monitorul(ele) selectat(e)\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"Diverse\"\n\n# R-GC, scrie:\n# după revizarea fișierului, DȘ, spune:\n# „→ lipsește închiderea parantezei”\n# ===\n# corectare făcută\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Partajat (nu deconectează alte vizoare)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Solicită reconectarea în cazul erorilor de conectare\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"Toate comenzile rapide de la tastatură sunt dezactivate.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"Pentru a elibera controlul tastaturii din sesiune, apăsați %s.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"Pentru a pasa toate intrările de la tastatură către sesiune, apăsați %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"Pentru a trece în modul de ecran complet, apăsați %sEnter.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"Pentru a deschide meniul contextual al sesiunii, apăsați %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"Pentru a trimite o combinație de taste care include %s direct către sesiune, apăsați %sSpațiu, eliberați bara de spațiu fără a elibera %s și apăsați tasta dorită.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"Serverul VNC:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"Opțiuni...\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"Încărcare...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"Salvează ca...\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"Despre...\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"Conectare\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nu se poate încărca istoricul serverului:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Configurația TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Selectați un fișier de configurare TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nu se poate încărca fișierul de configurare specificat:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Salvați configurația TigerVNC în fișier\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s există deja. Doriți să-l suprascrieți?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Nu\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"Suprascrie\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nu se poate salva fișierul de configurare specificat:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nu se poate salva configurația implicită:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nu se poate salva istoricul serverului:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"Nu s-a putut determina ruta directorului de stare al VNC\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"Nu s-a putut deschide „%s”\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Nu s-a putut citi linia %d din fișierul „%s”\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"Linia este prea lungă\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"Deschiderea fișierului cu parole a eșuat\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"Autentificare VNC\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"Această conexiune este sigură\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"Această conexiune nu este sigură\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"Numele utilizatorului:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"Parola:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"Păstrează parola pentru reconectare\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"A apărut o eroare neașteptată la comunicarea cu serverul:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"Deco&nectare\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Ecran complet\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Minimi&zare\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Redimensionează &fereastra conform sesiunii\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Trimite Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&Reîmprospătează ecranul\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Opțiuni...\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&Informații despre conexiune...\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"Despre &TigerVNC...\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"Informații despre conexiunea VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Fereastra este înregistrată pentru atingere în loc de gesturi\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Nu s-a putut definii configurația gesturilor (eroare 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Nu s-au putut obține informații despre gesturi (eroare 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Butonul mouse-ului %d nu este valid, trebuie să fie un număr între 1 și 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Tasta 0x%x necunoscută - nu se poate genera un eveniment de la tastatură.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Nu se poate obține masca de eveniment X Input 2 pentru fereastra 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Fereastra 0x%08lx nu are mască de eveniment X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Fereastra 0x%08lx are mai mult de o mască de eveniment X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Eroare la preluarea dispozitivului %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Se conectează la serverul VNC și afișează biroul de la distanță\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Calculatoare în rețea virtuală ⟶ (Virtual Network Computing) «VNC» este un sistem de afișare la distanță care vă permite să vizualizați și să interacționați cu un mediu de birou virtual care rulează pe un alt computer din rețea. Folosind VNC, puteți rula aplicații grafice pe o mașină de la distanță și puteți trimite numai afișarea din aceste aplicații pe dispozitivul local. Acest pachet conține un client care vă va permite să vă conectați la alte calculatoare care rulează un server VNC. VNC este independent de platformă și acceptă diverse sisteme de operare și arhitecturi atât ca servere, cât și ca clienți.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC este o versiune de mare viteză a VNC bazată pe bazele codurilor RealVNC 4 și X.org. TigerVNC a început ca un efort de dezvoltare de ultimă generație pentru TightVNC pe platformele Unix și Linux, dar s-a despărțit de proiectul său părinte la începutul anului 2009, astfel încât TightVNC să se poată concentra pe platformele Windows. TigerVNC acceptă o variantă de codificare Tight care este mult accelerată prin utilizarea codec-ului JPEG libjpeg-turbo.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"Conexiune a TigerVNC la o mașină «GNU/Linux»\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"Conexiune a TigerVNC la o mașină «macOS»\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"Conexiune a TigerVNC la o mașină «Windows»\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"Echipa TigerVNC\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Numele parametrului este prea lung\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"Parametrul este prea lung\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"Format nevalid sau valoare prea mare\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"Nu s-a putut crea cheia de registru\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"Nu s-a putut închide cheia de registru\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Nu s-a putut salva „%s”: %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Nu s-a putut elimina „%s”: %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"Nu s-a putut deschide cheia de registru\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Nu s-a putut citi intrarea din istoricul serverului %d: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Nu s-a putut citi parametrul „%s”: %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"Nu s-a putut determina ruta directorului de configurare al VNC\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"Nu s-a putut codifica parametrul\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Fișierul de configurare %s este într-un format nevalid\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"Format nevalid\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"Parametru necunoscut\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"S-a primit mesajul (0x%x) pentru o fereastră negestionată\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Fereastra 0x%08lx nevalidă a fost specificată pentru preluarea indicatorului mouse-ului\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Nu s-a putut crea gestionarul de atingere: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Nu s-a putut atașa gestionarul de evenimente la fereastră (eroare 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Nu s-au putut obține datele despre eveniment pentru evenimentul X Input\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"Eveniment X Input pentru o fereastră necunoscută\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"Extensia X Input nu este disponibilă.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2 (sau mai nouă) nu este disponibilă.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2 (sau mai nouă) nu este disponibilă. Gesturile tactile nu vor fi acceptate.\"\n\n# R-GC, scrie:\n# după revizarea fișierului, DȘ, spune:\n# «→ aici poți ajusta puțin stilul înlocuind „vedeți” cu „consultați”»\n# ===\n# de acord cu faptul că în general,\n# see → consultați, dar să nu uităm că:\n# see == vedea, a se vedea\n# una este să consulți documentația, deobicei\n# echivalentul unui almanah sau al unei cărți,\n# și alta este să-ți arunci privirea pe-o listă,\n# deobicei mai mică decît o pagină\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC versiunea %s\\n\"\n\"Construit pe: %s\\n\"\n\"Drepturi de autor © 1999-%d Echipa TigerVNC și mulți alții (vedeți fișierul README.rst)\\n\"\n\"Consultați https://www.tigervnc.org pentru informații despre TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"Despre TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Eroare FLTK internă. Se finalizează.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Încercați să vă reconectați?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"Eroare la inițierea noii conexiuni: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"Semnalul de terminare %d a fost primit. TigerVNC se va închide acum.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Da\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Închide\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"Despre\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Ascunde\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Ieșire\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Servicii\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Ascunde pe celelalte\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Afișează pe toate\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Fişier\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"Conexiune &nouă\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Utilizare: %s [parametri] [gazda][:Număr-ecran]\\n\"\n\"           %s [parametri] [gazda][::port]\\n\"\n\"           %s [parametri] [soclu unix]\\n\"\n\"           %s [parametri] -listen [port]\\n\"\n\"           %s [parametri] [fișier .tigervnc]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Opțiuni:\\n\"\n\"\\n\"\n\"  -display afișajulX  - Specifică afișajul X pentru fereastra vizorului\\n\"\n\"  -geometry geometria - Poziția inițială a ferestrei principale a TigerVNC.\\n\"\n\"                        Consultați pagina de manual pentru detalii.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Parametrii pot fi activați cu -<param> sau dezactivați cu -<param>=0\\n\"\n\"Parametrii care iau o valoare pot fi specificați ca -<param> <valoare>\\n\"\n\"Alte forme valide sunt <param>=<valoare> -<param>=<valoare> --<param>=<valoare>\\n\"\n\"Numele parametrilor nu sunt sensibile la majuscule.  Parametrii sunt:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors este învechit, stabiliți în schimb FullScreenMode la „all”\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor este depreciat, stabiliți AlwaysCursor la 1 și CursorType la „Dot” în schimb\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc este depreciat, vă rugăm să consultați «man vncviewer» pentru căile de migrare.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc este depreciat, vă rugăm să treceți la locația %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"Nu s-a putut crea directorul de configurare al VNC „%s”: %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"Nu s-a putut determina ruta directorului de date al VNC\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"Nu s-a putut crea directorul de date al VNC „%s”: %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"Nu s-a putut crea directorul de stare al VNC „%s”: %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: opțiune nerecunoscută „%s”\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"Consultați «%s --help» pentru mai multe informații.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Argument extra „%s”\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Parametrii „-listen” și „-via” sunt incompatibili\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Nu se poate asculta pentru conexiunile primite\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Se ascultă pe portul %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Eroare la așteptarea conexiunii VNC de intrare:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Eșec la configurarea tunelului criptat\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"Vizor pentru birou la distanță\"\n\n#, c-format\n#~ msgid \"(server default %s)\"\n#~ msgstr \"(server implicit %s)\"\n\n#, c-format\n#~ msgid \"SetDesktopSize failed: %d\"\n#~ msgstr \"Funcția SetDesktopSize() a eșuat: %d\"\n\n#~ msgid \"Invalid SetColourMapEntries from server!\"\n#~ msgstr \"Valoare SetColourMapEntries nevalidă de la server!\"\n\n#, c-format\n#~ msgid \"Invalid configuration specified for %s\"\n#~ msgstr \"Configurație nevalidă specificată pentru %s\"\n\n#, c-format\n#~ msgid \"Invalid monitor index '%s'\"\n#~ msgstr \"Index de monitor nevalid „%s”\"\n\n#, c-format\n#~ msgid \"Unexpected character '%c'\"\n#~ msgstr \"Caracter neașteptat „%c”\"\n\n#~ msgid \"Pass system keys directly to server (full screen)\"\n#~ msgstr \"Pasează tastele sistemului direct către server (ecran complet)\"\n\n#~ msgid \"Menu key\"\n#~ msgstr \"Tasta de meniu\"\n\n#~ msgid \"VNC viewer: Connection details\"\n#~ msgstr \"Vizor VNC: Detalii de conectare\"\n\n#, c-format\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Send %s\"\n#~ msgstr \"Trimite %s\"\n\n#~ msgid \"TigerVNC viewer\"\n#~ msgstr \"Vizor TigerVNC\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"Afișează un punct când nu există cursor al mouse-ului\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"Nu s-a putut actualiza starea LED-ului tastaturii: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"Nu a fost specificat niciun cod de tastă la apăsarea tastei\"\n\n#, c-format\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"Niciun simbol pentru codul tastei 0x%02x (în starea curentă)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"Tip de parametru necunoscut\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"Vizualizator VNC: Opțiuni de conectare\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"Diverse\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"Nu s-a putut obține numele monitorului deoarece X11 RandR nu a putut fi găsit\"\n\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"Nu s-au putut obține informații despre CRTC %d\"\n\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"Nu s-au putut obține informații despre ieșirea %d pentru CRTC %d\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"Ecran\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"Redimensionează sesiunea de la distanță la conectare\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"Redimensionează sesiunea de la distanță la fereastra locală\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"Activează ecranul complet\"\n"
  },
  {
    "path": "po/ru.po",
    "content": "# Russian translation for tigervnc.\n# Copyright © 2016 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# PuppyRus linux team <www.puppyrus.org>.\n# Constantin Kaplinsky <const@tightvnc.com>, 2011.\n# Pavel Maryanov <acid@jack.kiev.ua>, 2016.\n# Yuri Kozlov <yuray@komyakino.ru>, 2016, 2017, 2018, 2019, 2021, 2023, 2025.\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.14.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-01-14 16:15+0100\\n\"\n\"PO-Revision-Date: 2025-03-26 21:38+0300\\n\"\n\"Last-Translator: Yuri Kozlov <yuray@komyakino.ru>\\n\"\n\"Language-Team: Russian <gnu@d07.ru>\\n\"\n\"Language: ru_UA\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\\n\"\n\"X-Generator: Lokalize 24.12.0\\n\"\n\n#: vncviewer/CConn.cxx:102\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Подключён к сокету %s\"\n\n#: vncviewer/CConn.cxx:109\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Подключён к компьютеру %s, порт %d\"\n\n#: vncviewer/CConn.cxx:114\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не удалось подключиться к «%s»:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:151\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Имя компьютера: %.80s\"\n\n#: vncviewer/CConn.cxx:154\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Компьютер: %.80s порт: %d\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Размер: %d x %d\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Формат пикселей: %s\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(сервер по умолчанию %s)\"\n\n#: vncviewer/CConn.cxx:173\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Запрошено кодирование: %s\"\n\n#: vncviewer/CConn.cxx:177\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Используется кодирование: %s\"\n\n#: vncviewer/CConn.cxx:181\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Скорость соединения: %d кбит/с\"\n\n#: vncviewer/CConn.cxx:185\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Версия протокола: %d.%d\"\n\n#: vncviewer/CConn.cxx:189\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Метод защиты: %s\"\n\n#: vncviewer/CConn.cxx:250 vncviewer/CConn.cxx:252\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Соединение прервано сервером до установления сеанса.\"\n\n#: vncviewer/CConn.cxx:262\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Ошибка аутентификации: %s\"\n\n#: vncviewer/CConn.cxx:263\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Ошибка аутентификации на сервере. Причина, полученная от сервера:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:335\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"Ошибка SetDesktopSize: %d\"\n\n#: vncviewer/CConn.cxx:408\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"С сервера получен недопустимый SetColourMapEntries\"\n\n#: vncviewer/CConn.cxx:516\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Пропускная способность %d кбит/с. Установлено качество %d\"\n\n#: vncviewer/CConn.cxx:538\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Пропускная способность %d кбит/с — включено полноцветное отображение\"\n\n#: vncviewer/CConn.cxx:541\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Пропускная способность %d кбит/с — полноцветное отображение выключено\"\n\n#: vncviewer/CConn.cxx:567\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Используется формат пикселей %s\"\n\n#: vncviewer/DesktopWindow.cxx:146\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Указан недопустимый размер экрана.\"\n\n#: vncviewer/DesktopWindow.cxx:167\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Уменьшается размер окна, чтобы поместиться в текущем мониторе\"\n\n#: vncviewer/DesktopWindow.cxx:646\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Подгоняется размер окна, чтобы избегать случайных запросов переключения в полный экран\"\n\n#: vncviewer/DesktopWindow.cxx:694\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Нажмите %s, чтобы открыть контекстное меню\"\n\n#: vncviewer/DesktopWindow.cxx:1094 vncviewer/DesktopWindow.cxx:1102\n#: vncviewer/DesktopWindow.cxx:1122\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Не удалось перехватить клавиатуру\"\n\n#: vncviewer/DesktopWindow.cxx:1411\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Для запроса на изменение размера рассчитан недопустимый макет экрана.\"\n\n#: vncviewer/EmulateMB.cxx:226 vncviewer/EmulateMB.cxx:289\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Некорректное состояние для эмуляция средней кнопки\"\n\n#: vncviewer/KeyboardWin32.cxx:242\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Нет скан-кода для дополнительной виртуальной клавиши 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:244\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Нет скан-кода для виртуальной клавиши 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Некорректный скан-код 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:262\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Нет символа для расширенной виртуальной клавиши 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:264\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Нет символа для виртуальной клавиши 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:423\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Не удалось обновить состояние LED клавиатуры: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:104\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Нет символа для кода клавиши %d (в текущем состоянии)\"\n\n#: vncviewer/KeyboardX11.cxx:129\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Не удалось получить состояние LED клавиатуры: %d\"\n\n#: vncviewer/KeyboardX11.cxx:174\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Не удалось обновить состояние LED клавиатуры\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:52\n#: vncviewer/MonitorIndicesParameter.cxx:100\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Не удалось получить настройки системного монитора\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:79\n#, c-format\nmsgid \"Invalid configuration specified for %s\"\nmsgstr \"Задано недопустимое значение для %s\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:86\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Монитор с индексом %d не существует\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:162\n#: vncviewer/MonitorIndicesParameter.cxx:182\n#, c-format\nmsgid \"Invalid monitor index '%s'\"\nmsgstr \"Некорректный индекс монитора «%s»\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:170\n#, c-format\nmsgid \"Unexpected character '%c'\"\nmsgstr \"Неожиданный символ «%c»\"\n\n#: vncviewer/OptionsDialog.cxx:64\nmsgid \"TigerVNC options\"\nmsgstr \"Параметры TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:97 vncviewer/ServerDialog.cxx:107\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Отмена\"\n\n#: vncviewer/OptionsDialog.cxx:102 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"ОК\"\n\n#: vncviewer/OptionsDialog.cxx:514\nmsgid \"Compression\"\nmsgstr \"Сжатие\"\n\n#: vncviewer/OptionsDialog.cxx:530\nmsgid \"Auto select\"\nmsgstr \"Автоматический выбор\"\n\n#: vncviewer/OptionsDialog.cxx:541\nmsgid \"Preferred encoding\"\nmsgstr \"Вид кодирования\"\n\n#: vncviewer/OptionsDialog.cxx:602\nmsgid \"Color level\"\nmsgstr \"Глубина цвета\"\n\n#: vncviewer/OptionsDialog.cxx:614\nmsgid \"Full\"\nmsgstr \"Полная\"\n\n#: vncviewer/OptionsDialog.cxx:621\nmsgid \"Medium\"\nmsgstr \"Средняя\"\n\n#: vncviewer/OptionsDialog.cxx:628\nmsgid \"Low\"\nmsgstr \"Низкая\"\n\n#: vncviewer/OptionsDialog.cxx:635\nmsgid \"Very low\"\nmsgstr \"Очень низкая\"\n\n#: vncviewer/OptionsDialog.cxx:657\nmsgid \"Custom compression level:\"\nmsgstr \"Уровень сжатия:\"\n\n#: vncviewer/OptionsDialog.cxx:664\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"уровень (0=быстрое, 9=лучшее)\"\n\n#: vncviewer/OptionsDialog.cxx:671\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Разрешить сжатие JPEG:\"\n\n#: vncviewer/OptionsDialog.cxx:678\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"качество (0=наихудшее, 9=наилучшее)\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Security\"\nmsgstr \"Безопасность\"\n\n#: vncviewer/OptionsDialog.cxx:703\nmsgid \"Encryption\"\nmsgstr \"Шифрование\"\n\n#: vncviewer/OptionsDialog.cxx:715 vncviewer/OptionsDialog.cxx:782\n#: vncviewer/OptionsDialog.cxx:905\nmsgid \"None\"\nmsgstr \"Нет\"\n\n#: vncviewer/OptionsDialog.cxx:722\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS с анонимными сертификатами\"\n\n#: vncviewer/OptionsDialog.cxx:728\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS с сертификатами X509\"\n\n#: vncviewer/OptionsDialog.cxx:735\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Путь к сертификату X509 CA\"\n\n#: vncviewer/OptionsDialog.cxx:742\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Путь к файлу X509 CRL\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Authentication\"\nmsgstr \"Авторизация\"\n\n#: vncviewer/OptionsDialog.cxx:788\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Стандартный VNC (без защиты и шифрования)\"\n\n#: vncviewer/OptionsDialog.cxx:794\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Имя пользователя и пароль (без защиты и шифрования)\"\n\n#: vncviewer/OptionsDialog.cxx:822\nmsgid \"Input\"\nmsgstr \"Ввод\"\n\n#: vncviewer/OptionsDialog.cxx:835\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Только просмотр (не перехватывать мышь и клавиатуру)\"\n\n#: vncviewer/OptionsDialog.cxx:842\nmsgid \"Mouse\"\nmsgstr \"Мышь\"\n\n#: vncviewer/OptionsDialog.cxx:854\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Эмулировать среднюю кнопку мыши\"\n\n#: vncviewer/OptionsDialog.cxx:860\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Показывать локальный курсор, когда он не предоставляется сервером\"\n\n#: vncviewer/OptionsDialog.cxx:865\nmsgid \"Cursor type\"\nmsgstr \"Тип курсора\"\n\n#: vncviewer/OptionsDialog.cxx:867\nmsgid \"Dot\"\nmsgstr \"Dot\"\n\n#: vncviewer/OptionsDialog.cxx:868\nmsgid \"System\"\nmsgstr \"System\"\n\n#: vncviewer/OptionsDialog.cxx:888\nmsgid \"Keyboard\"\nmsgstr \"Клавиатура\"\n\n#: vncviewer/OptionsDialog.cxx:900\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Отправлять сочетания клавиш (для полного экрана)\"\n\n#: vncviewer/OptionsDialog.cxx:903\nmsgid \"Menu key\"\nmsgstr \"Вызов меню:\"\n\n#: vncviewer/OptionsDialog.cxx:926\nmsgid \"Clipboard\"\nmsgstr \"Буфер обмена\"\n\n#: vncviewer/OptionsDialog.cxx:938\nmsgid \"Accept clipboard from server\"\nmsgstr \"Принимать буфер обмена с сервера\"\n\n#: vncviewer/OptionsDialog.cxx:946\nmsgid \"Also set primary selection\"\nmsgstr \"Также принимать мышиный буфер\"\n\n#: vncviewer/OptionsDialog.cxx:953\nmsgid \"Send clipboard to server\"\nmsgstr \"Отправлять буфер обмена на сервер\"\n\n#: vncviewer/OptionsDialog.cxx:961\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Отправлять мышиный буфер туда же, куда и буфер обмена\"\n\n#: vncviewer/OptionsDialog.cxx:982\nmsgid \"Display\"\nmsgstr \"Экран\"\n\n#: vncviewer/OptionsDialog.cxx:996\nmsgid \"Display mode\"\nmsgstr \"Режим экрана\"\n\n#: vncviewer/OptionsDialog.cxx:1009\nmsgid \"Windowed\"\nmsgstr \"Оконный режим\"\n\n#: vncviewer/OptionsDialog.cxx:1017\nmsgid \"Full screen on current monitor\"\nmsgstr \"Полноэкранный режим на текущем мониторе\"\n\n#: vncviewer/OptionsDialog.cxx:1025\nmsgid \"Full screen on all monitors\"\nmsgstr \"Полноэкранный режим на всех мониторах\"\n\n#: vncviewer/OptionsDialog.cxx:1033\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Полноэкранный режим на выбранных мониторах\"\n\n#: vncviewer/OptionsDialog.cxx:1062\nmsgid \"Miscellaneous\"\nmsgstr \"Разное\"\n\n#: vncviewer/OptionsDialog.cxx:1070\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Совместная работа (не отключать других клиентов)\"\n\n#: vncviewer/OptionsDialog.cxx:1076\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Запрашивать о переподключении при ошибках соединения\"\n\n#: vncviewer/ServerDialog.cxx:63\nmsgid \"VNC viewer: Connection details\"\nmsgstr \"VNC viewer: информация о соединении\"\n\n#: vncviewer/ServerDialog.cxx:73\nmsgid \"VNC server:\"\nmsgstr \"Сервер VNC:\"\n\n#: vncviewer/ServerDialog.cxx:80\nmsgid \"Options...\"\nmsgstr \"Параметры\"\n\n#: vncviewer/ServerDialog.cxx:84\nmsgid \"Load...\"\nmsgstr \"Загрузить\"\n\n#: vncviewer/ServerDialog.cxx:88\nmsgid \"Save as...\"\nmsgstr \"Сохранить как…\"\n\n#: vncviewer/ServerDialog.cxx:102\nmsgid \"About...\"\nmsgstr \"О программе\"\n\n#: vncviewer/ServerDialog.cxx:111\nmsgid \"Connect\"\nmsgstr \"Войти\"\n\n#: vncviewer/ServerDialog.cxx:147\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Невозможно загрузить историю сервера:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:176 vncviewer/ServerDialog.cxx:216\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Настройки TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:177\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Выбрать файл настроек TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:199 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Невозможно загрузить указанный файл настроек:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:217\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Сохранить настройки TigerVNC в файл\"\n\n#: vncviewer/ServerDialog.cxx:243\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"Файл «%s» уже существует, перезаписать?\"\n\n#: vncviewer/ServerDialog.cxx:244 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Нет\"\n\n#: vncviewer/ServerDialog.cxx:244\nmsgid \"Overwrite\"\nmsgstr \"Перезаписать\"\n\n#: vncviewer/ServerDialog.cxx:260\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Невозможно сохранить указанный файл настроек:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:294\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Невозможно сохранить файл настроек по умолчанию:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:306\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Невозможно сохранить историю сервера:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:429\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"Невозможно определить путь к каталогу состояния VNC\"\n\n#: vncviewer/ServerDialog.cxx:363 vncviewer/ServerDialog.cxx:437\n#: vncviewer/parameters.cxx:671 vncviewer/parameters.cxx:752\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"Невозможно открыть «%s»\"\n\n#: vncviewer/ServerDialog.cxx:378 vncviewer/ServerDialog.cxx:387\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:773\n#: vncviewer/parameters.cxx:807 vncviewer/parameters.cxx:837\n#: vncviewer/parameters.cxx:844\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Не удалось прочитать строку %d из файла «%s»\"\n\n#: vncviewer/ServerDialog.cxx:390 vncviewer/parameters.cxx:776\nmsgid \"Line too long\"\nmsgstr \"Строка слишком длинная\"\n\n#: vncviewer/UserDialog.cxx:123\nmsgid \"Opening password file failed\"\nmsgstr \"Не удалось открыть файл с паролем\"\n\n#: vncviewer/UserDialog.cxx:143\nmsgid \"VNC authentication\"\nmsgstr \"Аутентификация VNC\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"This connection is secure\"\nmsgstr \"Это соединение защищено\"\n\n#: vncviewer/UserDialog.cxx:154\nmsgid \"This connection is not secure\"\nmsgstr \"Это соединение не защищено\"\n\n#: vncviewer/UserDialog.cxx:176\nmsgid \"Username:\"\nmsgstr \"Имя пользователя:\"\n\n#: vncviewer/UserDialog.cxx:189\nmsgid \"Password:\"\nmsgstr \"Пароль:\"\n\n#: vncviewer/UserDialog.cxx:197\nmsgid \"Keep password for reconnect\"\nmsgstr \"Сохранить пароль для переподключения\"\n\n#: vncviewer/Viewport.cxx:695\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"От&ключиться\"\n\n#: vncviewer/Viewport.cxx:698\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"Полный &экран\"\n\n#: vncviewer/Viewport.cxx:701\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"&Свернуть\"\n\n#: vncviewer/Viewport.cxx:703\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Изменить &размер окна\"\n\n#: vncviewer/Viewport.cxx:708\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:711\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:717\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"Отправить %s\"\n\n#: vncviewer/Viewport.cxx:724\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Отправить Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:727\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&Обновить экран\"\n\n#: vncviewer/Viewport.cxx:730\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Параметры…\"\n\n#: vncviewer/Viewport.cxx:732\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Сведен&ия о соединении…\"\n\n#: vncviewer/Viewport.cxx:734\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"О &TigerVNC…\"\n\n#: vncviewer/Viewport.cxx:830\nmsgid \"VNC connection info\"\nmsgstr \"Сведения о соединении VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:48\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Для окна зарегистрировано управление прикосновениями, а не жестами\"\n\n#: vncviewer/Win32TouchHandler.cxx:83\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Не удалось задать параметры жестов (ошибка 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:95\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Не удалось получить информацию о жестах (ошибка 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:360\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Некорректная кнопка мыши %d: должно быть число от 1 до 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:425\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Необработанная кнопка 0x%x: невозможно сгенерировать событие клавиатуры.\"\n\n#: vncviewer/XInputTouchHandler.cxx:102 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Невозможно получить маску событий X Input 2 для окна 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:104\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"У окна 0x%08lx нет маски событий X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:112 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"У окна 0x%08lx больше одной маски событий X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:143\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Не удалось перехватить устройство %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\nmsgid \"TigerVNC Viewer\"\nmsgstr \"TigerVNC Viewer\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Подключиться к серверу VNC и показать удалённый рабочий стол\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC) — система удалённого рабочего стола, которая позволяет просматривать и взаимодействовать по сети с виртуальным окружением, запущенном на другом компьютере.С помощью VNC вы можете запускать графические приложения на удалённой машине и получать отображение этих приложений на локальной машине. Этот пакет содержит клиентскую часть, которая позволяет подключиться к другим рабочим столам, запущенным сервером VNC. VNC не зависит от платформы и поддерживает различные операционные системы и архитектуры как для серверов так и для клиентов.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC — высокоскоростная версия VNC, в основе лежит код RealVNC 4 и X.org. TigerVNC начиналась как разработка следующего поколения TightVNC для платформ Unix и Linux, но отделилась от родительского проекта в начале 2009 года для того, чтобы TightVNC смогла сфокусироваться на платформе Windows. TigerVNC поддерживает вариант кодирования Tight, который был значительно ускорен с помощью кодека libjpeg-turbo JPEG.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC viewer connection to a CentOS machine\"\nmsgstr \"Подключение TigerVNC viewer к машине CentOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC viewer connection to a macOS machine\"\nmsgstr \"Подключение TigerVNC viewer к машине macOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC viewer connection to a Windows machine\"\nmsgstr \"Подключение TigerVNC viewer к машине Windows\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"Команда TigerVNC\"\n\n#: vncviewer/parameters.cxx:319 vncviewer/parameters.cxx:344\n#: vncviewer/parameters.cxx:361 vncviewer/parameters.cxx:401\n#: vncviewer/parameters.cxx:421\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Название параметра слишком длинное\"\n\n#: vncviewer/parameters.cxx:323 vncviewer/parameters.cxx:328\n#: vncviewer/parameters.cxx:379\nmsgid \"The parameter is too large\"\nmsgstr \"Параметр слишком длинный\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:712\n#: vncviewer/parameters.cxx:822\nmsgid \"Invalid format or too large value\"\nmsgstr \"Недопустимый формат или слишком большое значение\"\n\n#: vncviewer/parameters.cxx:440 vncviewer/parameters.cxx:473\nmsgid \"Failed to create registry key\"\nmsgstr \"Не удалось создать ключ реестра\"\n\n#: vncviewer/parameters.cxx:461 vncviewer/parameters.cxx:528\n#: vncviewer/parameters.cxx:571 vncviewer/parameters.cxx:638\nmsgid \"Failed to close registry key\"\nmsgstr \"Не удалось закрыть ключ реестра\"\n\n#: vncviewer/parameters.cxx:479 vncviewer/parameters.cxx:506\n#: vncviewer/parameters.cxx:680 vncviewer/parameters.cxx:692\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Не удалось сохранить «%s»: %s\"\n\n#: vncviewer/parameters.cxx:489 vncviewer/parameters.cxx:520\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Не удалось удалить «%s»: %s\"\n\n#: vncviewer/parameters.cxx:544 vncviewer/parameters.cxx:616\nmsgid \"Failed to open registry key\"\nmsgstr \"Не удалось открыть ключ реестра\"\n\n#: vncviewer/parameters.cxx:561\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Не удалось прочитать элемент истории сервера %d: %s\"\n\n#: vncviewer/parameters.cxx:597 vncviewer/parameters.cxx:627\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Не удалось прочитать параметр «%s»: %s\"\n\n#: vncviewer/parameters.cxx:661 vncviewer/parameters.cxx:740\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"Невозможно определить путь к каталогу настроек VNC\"\n\n#: vncviewer/parameters.cxx:682 vncviewer/parameters.cxx:694\nmsgid \"Could not encode parameter\"\nmsgstr \"Не удалось закодировать параметр\"\n\n#: vncviewer/parameters.cxx:785\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Недопустимый формат файла конфигурации %s\"\n\n#: vncviewer/parameters.cxx:809\nmsgid \"Invalid format\"\nmsgstr \"Недопустимый формат\"\n\n#: vncviewer/parameters.cxx:846\nmsgid \"Unknown parameter\"\nmsgstr \"Неизвестный параметр\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Получено сообщение (0x%x) для необрабатываемого окна\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Для захвата указателя указано неверное окно 0x%08lx\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Не удалось создать обработчик прикосновений: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Невозможно прикрепить обработчик событий к окну (ошибка 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Не удалось получить данные о событии для события X Input\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"Событие X Input для неизвестного окна\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"Расширение X Input недоступно.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"Расширение X Input 2 (или новее) недоступно.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"Расширение X Input 2.2 (или новее) недоступно. Прикосновения жестов не будут поддерживаться.\"\n\n#: vncviewer/vncviewer.cxx:104\n#, c-format\nmsgid \"\"\n\"TigerVNC viewer v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC viewer v%s\\n\"\n\"Сборка от: %s\\n\"\n\"Copyright (C) 1999-%d, команда TigerVNC и многие другие (см. README.rst)\\n\"\n\"Информация о TigerVNC на сайте https://www.tigervnc.org\"\n\n#: vncviewer/vncviewer.cxx:158\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Произошла непредвиденная ошибка во время соединения с сервером:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:174\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"О TigerVNC viewer\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Внутренняя ошибка FLTK. Выход.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Попытаться переподключиться?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Не удалось запустить новый TigerVNC Viewer: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC viewer will now exit.\"\nmsgstr \"Получен сигнал завершения работы %d. TigerVNC viewer будет закрыт.\"\n\n#: vncviewer/vncviewer.cxx:391 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC viewer\"\nmsgstr \"TigerVNC viewer\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Да\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Закрыть\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"О программе\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Скрыть\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Выход\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Службы\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Скрыть прочее\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Показать всё\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Файл\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Новое соединение\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Использование: %s [параметры] [узел][:номерДисплеия]\\n\"\n\"       %s [параметры] [узел][::порт]\\n\"\n\"       %s [параметры] [сокет unix]\\n\"\n\"       %s [параметры] -listen [порт]\\n\"\n\"       %s [параметры] [файл .tigervnc]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main VNC viewer window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Параметры:\\n\"\n\"\\n\"\n\"  -display Xdisplay   - Задать X-дисплей для окна программы\\n\"\n\"  -geometry геометрия - Начальное положение основного окна VNC.\\n\"\n\"                      Подробности в справочной странице.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Параметры включаются указанием в виде -<параметр> или \\n\"\n\"отключаются в виде -<параметр>=0\\n\"\n\"Параметры со значениями можно задавать в виде -<параметр> <значение>\\n\"\n\"Также допускается формат <параметр>=<значение> -<параметр>=<значение>\\n\"\n\"--<параметр>=<значение>\\n\"\n\"Имена параметров не чувствительны к регистру. Возможные параметры:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors устарел, задайте FullScreenMode со значением «all»\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor устарел, вместо него используйте AlwaysCursor равным 1 и CursorType равным «Dot»\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"Каталог ~/.vnc устарел, по «man vncviewer» можно найти информацию об изменениях в путях.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc устарел, используйте %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"Невозможно создать каталог настроек VNC «%s»: %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"Невозможно определить путь к каталогу данных VNC\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"Невозможно создать каталог данных VNC «%s»: %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"Невозможно создать каталог состояния VNC «%s»: %s\"\n\n#: vncviewer/vncviewer.cxx:703\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: Нераспознанный параметр «%s»\\n\"\n\n#: vncviewer/vncviewer.cxx:705 vncviewer/vncviewer.cxx:713\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"По команде «%s --help» можно получить дополнительную информацию.\\n\"\n\n#: vncviewer/vncviewer.cxx:712\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Лишний аргумент «%s»\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:748 vncviewer/vncviewer.cxx:749\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Параметры -listen и -via несовместимы\"\n\n#: vncviewer/vncviewer.cxx:763\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Невозможно прослушивать входящие соединения\"\n\n#: vncviewer/vncviewer.cxx:765\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Прослушивается порт %d\"\n\n#: vncviewer/vncviewer.cxx:794\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Ошибка при ожидании входящего соединения VNC:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:815\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Ошибка при создании шифрованного туннеля:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote desktop viewer\"\nmsgstr \"Просмотр удалённых рабочих столов\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"VNC Viewer: параметры соединения\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"Показывать точку при отсутствии курсора\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"Разное\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"Не удалось обновить состояние LED клавиатуры: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"Не задан код клавиши при нажатии\"\n\n#, c-format\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"Нет символа для кода клавиши 0x%02x (в текущем состоянии)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"Неизвестный тип для параметра\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"Не удалось получить имя монитора, так как не найден X11 RandR\"\n\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"Не удалось получить информацию о CRTC %d\"\n\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"Не удалось получить информацию о выводе %d у CRTC %d\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"Экран\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"Изменить размер удалённого экрана\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"Изменить размер удалённого сеанса до локального окна\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"Включить режим полного экрана\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"Полная (все цвета)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"Средняя (256 цветов)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"Низкая (64 цвета)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"Минимум цвета (8 цветов)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"уровень (1=мин, 6=макс. [4-6 используются редко])\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"Полноэкранный режим\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"В&ыход\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"Закрыть &меню\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"Не удалось записать параметр %s типа %s в реестр: %ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"Название параметра %s слишком длинное для чтения из реестра\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"Параметр %s слишком длинный для чтения из реестра\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"Не удалось создать домашний каталог VNC: не удаётся получить путь к домашнему каталогу.\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"Не удалось записать файл конфигурации: не удаётся открыть %s: %s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"Не удалось прочитать файл конфигурации: не удаётся получить путь к домашнему каталогу.\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"Неизвестный параметр %s в строке %d файла %s\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"Не удалось создать домашний каталог VNC: не удаётся получить путь к домашнему каталогу.\"\n\n#~ msgid \"tigervnc\"\n#~ msgstr \"tigervnc\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Включение непрерывного обновления\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"отключено\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"включено\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Используется кодирование %s\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"Недостаточно памяти для framebuffer\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"Не удалось создать устройство framebuffer\"\n\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"Не удалось создать framebuffer bitmap\"\n\n#~ msgid \"Unable to create platform specific framebuffer: %s\"\n#~ msgstr \"Не удаётся создать framebuffer: %s\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"Используется универсальный framebuffer\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"не удаётся создать выбор DIB\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"Ошибка CreateCompatibleDC\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"Ошибка SelectObject\"\n\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"Ошибка BitBlt\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"Неправильный формат pixmap для выбранной глубины цвета\"\n\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"Не удалось найти допустимый формат pixmap\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"Поддерживаются только полноцветные экраны\"\n\n#~ msgid \"Using default colormap and visual, TrueColor, depth %d.\"\n#~ msgstr \"Используется стандартная цветовая карта и визуальное оформление, TrueColor, глубина %d.\"\n\n#~ msgid \"Unknown encoding %d\"\n#~ msgstr \"Неизвестное кодирование %d\"\n\n#~ msgid \"Unknown encoding\"\n#~ msgstr \"Неизвестное кодирование\"\n"
  },
  {
    "path": "po/sk.po",
    "content": "# Slovak translation of TigerVNC\n# Copyright (C) 2025 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Jozef Riha <jose1711@gmail.com>, 2008.\n# Marián Haburaj <hajkomajko5@gmail.com>, 2024, 2025.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2025-11-13 16:25+0100\\n\"\n\"Last-Translator: Marián Haburaj <hajkomajko5@gmail.com>\\n\"\n\"Language-Team: Slovak <sk-i18n@lists.linux.sk>\\n\"\n\"Language: sk\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.8\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Pripojené na socket %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Pripojené na stroj %s port %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nepodarilo sa pripojiť k \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Názov plochy: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Stroj: %.80s port: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Veľkosť: %d x %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Formát pixelu: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Požadované kódovanie: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Naposledy použité kódovanie: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Predpokladaná rýchlosť linky: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Verzia protokolu: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Metóda zabezpečenia: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Spojenie bolo prerušené serverom skôr, než mohla byť nadviazaná relácia.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Autentifikácia zlyhala: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Autentifikácia so serverom zlyhala. Dôvod poskytnutý serverom:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Dátový tok %d kbit/s - mením na kvalitu %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Dátový tok %d kbit/s - plné farby sú teraz zapnuté\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Dátový tok %d kbit/s - plné farby sú teraz vypnuté\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Používaný formát pixelu %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Zadaná neplatná geometria!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Zmenšovanie veľkosti okna, aby sa zmestilo na súčasný monitor\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"Stlačte %sM na otvorenie kontextovej ponuky\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s - TigerVNC (klávesnica prebratá)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s - TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Upravovanie veľkosti okna na vyhnutie sa náhodným požiadavkám na celú obrazovku\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"Stlačte %sEnter na opustenie režimu celej obrazovky\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"Chyba pri preberaní kontroly nad klávesnicou\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"Stlačte %s na odpojenie kontroly klávesnice od relácie\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Vypočítané neplatné rozloženie obrazovky pre požiadavku na zmenu veľkosti!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Neplatný stav pre 3-tlačidlovú emuláciu\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Žiaden scan kód pre rozšírený virtuálny kláves 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Žiaden scan kód pre virtuálny kláves 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Neplatný scan kód 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Žiaden symbol pre rozšírený virtuálny kláves 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Žiaden symbol pre virtuálny kláves 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Zlyhalo aktualizovanie stavu diód na klávesnici: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Žiaden symbol pre kód klávesy %d (v súčasnom stave)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Zlyhalo získanie stavu diód na klávesnici: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Zlyhalo aktualizovanie stavu diód na klávesnici\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Nepodarilo sa získať nastavenie monitora systému\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Monitor s číslom %d neexistuje\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"Nastavenia TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Zrušiť\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"OK\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"Kompresia\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"Automatický výber\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"Povoliť kompresiu JPEG\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"Uprednostňované kódovanie\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"Farebnosť\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"Plná\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"Stredná\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"Malá\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"Veľmi malá\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"Vlastný stupeň kompresie\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"úroveň (0=rýchla, 9=najlepšia)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"Stupeň kvality\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"kvalita (0=nízka, 9=najlepšia)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"Bezpečnosť\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"Šifrovanie\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"Žiadne\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS s anonymnými certifikátmi\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS s X509 certifikátmi\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Cesta k X509 certifikátu autority\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Cesta k X509 súboru so zoznamom zneplatnených certifikátov\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"Autentifikácia\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Štandardné VNC (nezabezpečené bez šifrovania)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Používateľské meno a heslo (nezabezpečené bez šifrovania)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"Vstup\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Iba prezerať (ignorovať myš a klávesnicu)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"Myš\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Emulovať stredné tlačidlo myši\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Zobraziť lokálny kurzor, keď nie je poskytovaný serverom\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"Typ kurzoru\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"Bodka\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"Systémový\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"Klávesnica\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"Vždy posielať každý vstup z klávesnice v režime celej obrazovky\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"Schránka\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"Akceptovať schránku zo servera\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"Tiež nastaviť hlavný výber\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"Posielať schránku serveru\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Poslať hlavný výber ako schránku\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"Skratky klávesnice\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"Modifikačné klávesy pre skratky klávesnice:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Shift\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"^ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Shift\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Option\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"Zobrazenie\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"Režim zobrazenia\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"V okne\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"Celá obrazovka na tomto monitore\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"Celá obrazovka na všetkých monitoroch\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Celá obrazovka na zvolených monitoroch\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"Rôzne\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Zdieľané (neodpojiť iných klientov)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Spýtať sa na opätovné pripojenie pri chybe v spojení\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"Všetky skratky klávesnice sú vypnuté.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"Pre odpojenie kontroly klávesnice od relácie stlačte %s.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"Pre posielanie všetkého vstupu z klávesnice relácií stlačte %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"Na prepnutie režimu celej obrazovky stlačte %sEnter.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"Pre otvorenie kontextového menu relácie stlačte %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"Pre poslanie kombinácie klávesov, ktorá zahŕňa %s, priamo relácií stlačte %sMedzerník, pustite medzerník bez pustenia klávesy %s a stlačte požadovaný kláves.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"VNC server:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"Voľby...\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"Načítať...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"Uložiť ako...\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"O programe...\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"Pripojiť\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nemožno načítať históriu servera:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Nastavenie TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Zvoliť súbor s nastaveniami TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Zvolený súbor s nastaveniami nemožno načítať:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Uložiť nastavenie TigerVNC do súboru\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s už existuje. Chcete ho prepísať?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Nie\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"Prepísať\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nemožno uložiť zvolený súbor s nastaveniami:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nemožno uložiť predvolené nastavenia:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Nemožno uložiť históriu servera:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"Nemožno určiť cestu k adresáru stavu VNC\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"Nedá sa otvoriť \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Nedá sa prečítať riadok %d v súbore \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"Príliš dlhý riadok\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"Zlyhalo otváranie súboru s heslami\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"VNC autorizácia\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"Toto spojenie je zabezpečené\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"Toto spojenie nie je zabezpečené\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"Meno používateľa:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"Heslo:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"Ponechať heslo pre opätovné pripojenie\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Stala sa neočakávaná chyba pri komunikácií so serverom:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"O&dpojiť\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Režim celej obrazovky\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Minimali&zovať\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Prispôsobiť &veľkosť okna relácii\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Poslať Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Obnoviť ob&razovku\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"V&oľby...\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&Informácie o pripojení...\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"O aplikácií &TigerVNC...\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"Informácie o VNC pripojení\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Okno je registrované na dotyk namiesto ku gestám\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Zlyhalo nastavenie pre gestá (chyba 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Zlyhalo získanie informácií o gestách (chyba 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Neplatné číslo tlačidla myši %d, musí to byť číslo medzi 1 a 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Neriadený kláves 0x%x - nedá sa vytvoriť udalosť klávesnice.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Maska udalosti X Input 2 pre okno 0x%08lx sa nedá načítať\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Okno 0x%08lx nemá masku udalosti X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Okno 0x%08lx má viac než jednu masku udalosti X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Chyba pri preberaní zariadenia %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Pripojiť sa na VNC server a zobraziť vzdialenú plochu\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC) je technológia vzdialenej plochy, ktorá vám umožní zobraziť a interagovať s prostredím vzdialenej plochy, ktorá je spustená na inom počítači v sieti. Pomocou VNC môžete mať spustené grafické aplikácie na vzdialenom stroji a posielať len obraz z týchto aplikácií do vášho lokálneho zariadenia. Tento balík obsahuje klienta, ktorý vám umožní pripojiť sa k iným plochám, na ktorých je spustený VNC server. VNC je nezávislé na platforme a podporuje rôzne operačné systémy a architektúry tak ako na serveri, tak aj u klienta.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC je vysokorýchlostná verzia VNC založená na kóde RealVNC 4 a X.org. TigerVNC sa začala ako snaha o vývoj novej generácie TightVNC pre Unix a Linux, ale oddelilo sa od rodičovského projektu na začiatku roka 2009, a tak sa TigerVNC mohlo sústrediť na platformu Windows. TigerVNC podporuje variant Tight kódovania, ktorý je značne zrýchlený použitím JPEG kodeku libjpeg-turbo.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"Pripojenie TigerVNC k stroju s CentOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"Pripojenie TigerVNC k stroju s macOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"Pripojenie TigerVNC k stroju s Windows\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"TigerVNC tím\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Názov parametru je príliš dlhý\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"Parameter je príliš veľký\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"Neplatný formát alebo príliš veľká hodnota\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"Zlyhalo vytvorenie kľúča v registry\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"Zlyhalo zatvorenie kľúča v registry\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Zlyhalo uloženie \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Zlyhalo vymazanie \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"Zlyhalo otvorenie kľúča v registry\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Zlyhalo prečítanie záznamu histórie servera %d: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Zlyhalo prečítanie parametra \\\"%s\\\": %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"Nedá sa určiť cesta k adresáru s nastaveniami VNC\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"Nedá sa zakódovať parameter\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Súbor s nastaveniami %s je v neplatnom formáte\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"Neplatný formát\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"Neznámy parameter\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Prijatá správa (0x%x) pre neobsluhované okno\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Neplatné okno 0x%08lx nastavené pre zabranie ukazovateľa\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Zlyhalo vytvorenie obsluhy dotyku: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Nedá sa pripojiť obsluha udalostí k oknu (chyba 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Nepodarilo sa získať dáta udalostí pre udalosť X Input\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"Udalosť X Input pre neznáme okno\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"Rozšírenie X Input je nedostupné.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2 (alebo novšie) nie je dostupné.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2 (alebo novšie) nie je dostupné. Dotykové gestá nebudú podporované.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC v%s\\n\"\n\"Postavený na: %s\\n\"\n\"Copyright (C) 1999-%d Tím TigerVNC a mnohí ďalší (pozri README.rst)\\n\"\n\"Pre informácie o TigerVNC navštívte https://www.tigervnc.org.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"O aplikácií TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Interná FLTK chyba. Ukončuje sa.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Pokúsiť sa znova spojiť?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"Chyba pri nadväzovaní nového spojenia: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"Vnútorný signál na ukončenie %d bol prijatý. TigerVNC sa teraz ukončí.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Áno\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Zatvoriť\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"O programe\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Skryť\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Odísť\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Služby\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Skryť ostatné\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Zobraziť všetky\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Súbor\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Nové pripojenie\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Použitie: %s [parametre] [hostiteľ][:čísloDispleja]\\n\"\n\"       %s[parametre] [hostiteľ][::port]\\n\"\n\"       %s[parametre] [unix socket]\\n\"\n\"       %s[parametre] -listen [port]\\n\"\n\"       %s[parametre] [.tigervnc súbor]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Možnosti:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Špecifikuje X displej pre okno prehliadača\\n\"\n\"  -geometry geometry - Počiatočná poloha hlavného okna TigerVNC. Pozri\\n\"\n\"                       stránku man pre detaily.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Parametre môžu byť zapnuté s -<param> alebo vypnuté s -<param>=0\\n\"\n\"Parametre, ktoré vyžadujú hodnotu môžu byť zadané ako -<param> <value>\\n\"\n\"Ostatné správne formáty sú <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Názvy parametrov nie sú citlivé na veľkosť písmen. Parametre sú:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors je zastaralé, nastavte FullScreenMode na \\\"all\\\" radšej\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor je zastaralé, nastav hodnotu AlwaysCursos na 1 a CursorType na 'Dot' namiesto toho\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc je zastaralé, prosím poraďte sa s \\\"man vncviewer\\\" pre možnosti, ktoré možno použiť.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc je zastaralé, prosím prejdite na %%APPDATA%%\\\\TigerVNC priečinok.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"Nedá sa vytvoriť VNC adresár s nastaveniami: \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"Nedá sa určiť cesta k VNC adresáru pre údaje\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"Nedá sa vytvoriť VNC adresár pre údaje: \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"Nedá sa vytvoriť VNC adresár pre stavy: \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: Nerozpoznané nastavenie '%s'\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"Pozri '%s --help' pre viac informácií.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Dodatočný argument '%s'\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Parametre -listen a -via sa navzájom vylučujú\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Nedajú sa zachytávať prichádzajúce spojenia\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Načúva sa na porte %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Chyba pri čakaní na prichádzajúce VNC spojenia:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Zlyhalo nastavovanie šifrovaného tunela:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"Prehliadač vzdialenej plochy\"\n\n#, c-format\n#~ msgid \"(server default %s)\"\n#~ msgstr \"(predvolené serveru %s)\"\n\n#, c-format\n#~ msgid \"SetDesktopSize failed: %d\"\n#~ msgstr \"Požiadavka SetDesktopSize zlyhala: %d\"\n\n#~ msgid \"Invalid SetColourMapEntries from server!\"\n#~ msgstr \"Neplatná správa SetColourMapEntries od serveru!\"\n\n#, c-format\n#~ msgid \"Invalid configuration specified for %s\"\n#~ msgstr \"Zadané neplatné nastavenie pre %s\"\n\n#, c-format\n#~ msgid \"Invalid monitor index '%s'\"\n#~ msgstr \"Neplatné číslo monitoru \\\"%s\\\"\"\n\n#, c-format\n#~ msgid \"Unexpected character '%c'\"\n#~ msgstr \"Neočakávaný znak \\\"%c\\\"\"\n\n#~ msgid \"Pass system keys directly to server (full screen)\"\n#~ msgstr \"Podávať systémové klávesy priamo na server (celá obrazovka)\"\n\n#~ msgid \"Menu key\"\n#~ msgstr \"Kláves pre zobrazenie ponuky\"\n\n#~ msgid \"VNC viewer: Connection details\"\n#~ msgstr \"Priehliadač VNC: Detaily o pripojení\"\n\n#, c-format\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Send %s\"\n#~ msgstr \"Poslať %s\"\n\n#~ msgid \"TigerVNC viewer\"\n#~ msgstr \"Prehliadač TigerVNC\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"Zobraziť bodku, ak kurzor nie je zobrazený\"\n\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"Zlyhalo aktualizovanie stavu diód na klávesnici: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"Pri stlačení klávesa nebol zadaný žiaden kód klávesu\"\n\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"Žiaden symbol pre kód klávesy 0x%02x (v súčasnom stave)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"Neznámy typ parametra\"\n\n#~ msgid \"Dismiss menu\"\n#~ msgstr \"Zrušiť menu\"\n\n#~ msgid \"Exit viewer\"\n#~ msgstr \"Ukončiť prehliadač\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"Plná (všetky dostupné farby)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"Nízka (64 farieb)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"Stredná (256 farieb)\"\n\n#, fuzzy\n#~ msgid \"Misc.\"\n#~ msgstr \"Iné:\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"VNC Viewer: Voľby pripojenia\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"Veľmi nízka (8 farieb)\"\n\n#, fuzzy\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"stupeň (1=rýchla, 9=najlepšia)\"\n\n#~ msgid \"About VNCviewer...\"\n#~ msgstr \"O VNCviewer...\"\n\n#~ msgid \"\"\n#~ \"Desktop name: %.80s\\n\"\n#~ \"Host: %.80s port: %d\\n\"\n#~ \"Size: %d x %d\\n\"\n#~ \"Pixel format: %s\\n\"\n#~ \"(server default %s)\\n\"\n#~ \"Requested encoding: %s\\n\"\n#~ \"Last used encoding: %s\\n\"\n#~ \"Line speed estimate: %d kbit/s\\n\"\n#~ \"Protocol version: %d.%d\\n\"\n#~ \"Security method: %s\\n\"\n#~ msgstr \"\"\n#~ \"Názov desktopu: %.80s\\n\"\n#~ \"Hostiteľ: %.80s port: %d\\n\"\n#~ \"Veľkosť: %d x %d\\n\"\n#~ \"Formát pixelu: %s\\n\"\n#~ \"(východzie nastavenie serveru %s)\\n\"\n#~ \"Vyžiadané kódovanie: %s\\n\"\n#~ \"Posledné použité kódovanie: %s\\n\"\n#~ \"Odhad rýchlosti linky: %d kbit/s\\n\"\n#~ \"Verzia protokolu: %d.%d\\n\"\n#~ \"Metóda bezpečnosti: %s\\n\"\n\n#~ msgid \"Encoding and Color Level:\"\n#~ msgstr \"Kódovanie a úroveň farieb:\"\n\n#~ msgid \"Render cursor locally\"\n#~ msgstr \"Vykresľovať kurzor lokálne\"\n\n#~ msgid \"VNC Menu\"\n#~ msgstr \"VNC Menu\"\n"
  },
  {
    "path": "po/sr.po",
    "content": "# Serbian translation for tigervnc.\n# Copyright © 2020 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Мирослав Николић <miroslavnikolic@rocketmail.com>, 2016-2026.\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc-1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2026-01-18 15:29+0100\\n\"\n\"Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\\n\"\n\"Language-Team: Serbian <(nothing)>\\n\"\n\"Language: sr\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\\n\"\n\"X-Generator: Poedit 3.6\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Повезан на прикључницу „%s“\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Повезан са домаћином „%s“ прикључник %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Нисам успео да се повежем на „%s“:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Назив радне површи: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Домаћин: %.80s прикључник: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Величина: %d x %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Формат пиксела: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Затражено кодирање: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Последње коришћено кодирање: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Процењена брзина линије: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Издања протокола: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Метода безбедности: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Сервер је одбацио везу пре него ли је сесија могла да се успостави.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Потврђивање идентитета није успело: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Нисам успео да потврдим идентитет са сервером. Разлог који је дао сервер:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Пропусност је %d kbit/s — мењам на квалитет %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Пропусност је %d kbit/s — пуна боја је сада омогућена\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Пропусност је %d kbit/s — пуна боја је сада онемогућена\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Користим формат пиксела %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Наведена је неисправна геометрија!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Смањујем величину прозора да стане на текући монитор\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"Притисните „%sM“ да отворите приручни изборник\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s – TigerVNC (тастата је радна\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s – TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Прилагођавам величину прозора да би се избегли случајни захтеви за целим екраном\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"Притисните „%sУнеси“ да напустите режим целог екрана\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"Неуспех добијања управљања тастатуром\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"притисните „%s“ да отпустите управљање тастатуром из сесије\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Прорачунат је неодговарајући распоред екрана за захтев промене величине!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Неисправно стање за опонашање 3 дугмета\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Нема шифре прегледа за проширени виртуелни кључ 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Нема шифре прегледа за виртуелни кључ 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Неисправан код скенирања 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Нема симбола за проширени виртуелни кључ 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Нема симбола за виртуелни кључ 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Нисам успео да освежим стање диоде тастатуре: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Нема симбола за шифру кључа %d (у текућем стању)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Нисам успео да добавим стање диоде тастатуре: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Нисам успео да освежим стање диоде тастатуре\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Нисам успео да добавим подешавање монитора система\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Индекс монитора %d не постоји\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"Опције TigerVNC-а\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Откажи\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"У реду\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"Сажимање\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"Сам изабери\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"Дозволи ЈПЕГ сажимање\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"Жељено кодирање\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"Ниво боје\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"Пуна\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"Средња\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"Слаба\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"Врло слаба\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"Произвољни ниво сажимања\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"ниво (0=брзо, 9=најбоље)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"Ниво квалитета\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"квалитет (0=лош, 9=најбољи)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"Безбедност\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"Шифровање\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"Ништа\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"ТЛС са анонимним уверењима\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"ТЛС са X509 уверењима\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Путања до X509 уверења\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Путања до X509 ЦРЛ датотеке\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"Потврђивање идентитета\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Стандардни ВНЦ (несигурно без шифровања)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Корисник и лозинка (несигурно без шифровања)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"Улаз\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Само преглед (занемари миша и тастатуру)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"Миш\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Опонашај средње дугме миша\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Прикажи локални курзор када га сервер не достави\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"Врста курзора\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"Тачка\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"Систем\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"Тастатура\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"Увек шаље све улазе тастатуре на цео екран\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"Остава\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"Прихвати оставу са сервера\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"Такође постави први избор\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"Пошаљи оставу на сервер\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Пошаљи први избор као оставу\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"Пречице тастатуре\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"Измењивачки тастери за пречице тастатуре:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ктрл\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Шифт\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Алт\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Ктрл\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Шифт\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Опције\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Кмд\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"Приказ\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"Режим приказа\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"Упрозорен\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"Цео екран на текућем монитору\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"Цео екран на свим мониторима\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Цео екран на изабраном монитору\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"Разно\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Дељено (не прекидај везу другим прегледачима)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Питај за поновно повезивање при грешкама везе\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"Свепречице тастатуре су искључене.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"Да отпустите управљање тастатуром из сесије, притисните „%s“.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"Да проследите све улазе тастатуре у сесију, притисните „%sG“.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"Да окинете режим целог екрана, притисните „%sУнеси“.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"Да отворите приручни изборник сесије, притисните „%sМ“.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"Да пошаљете комбинацију тастера која обухвата „%s“ непосредно на сесију, притисните „%sРазмак“, отпустите тастер размака без отпуштања „%s“ и притисните жељени тастер.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"ВНЦ сервер:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"Могућности...\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"Учитавам...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"Сачувај као...\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"О програму...\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"Повежи се\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не могу да учитам историјат сервера:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Подешавање ТиграВНЦ (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Изаберите датотеку подешавања ТиграВНЦ\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не могу да учитам наведену датотеку подешавања:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Сачувајте подешавање ТиграВНЦ у датотеку\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"„%s“ већ постоји. Желите ли да је препишете?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Не\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"Препиши\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не могу да сачувам наведену датотеку подешавања:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не могу да сачувам основно подешавање:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не могу да сачувам историјат сервера:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"Не могу да одредим путању фасцикле ВНЦ стања\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"Не могу да отворим „%s“\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Нисам успео да прочитам %d. ред у датотеци „%s“\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"Ред је предуг\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"Отварање датотеке лозинке није успело\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"Потврђивање идентитета ВНЦ-а\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"Ова веза је безбедна\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"Ова веза није безбедна\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"Корисник:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"Лозинка:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"Задржи лозинку за поновно повезивање\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Дошло је до неочекиване грешке приликом комуницирања са сервером:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"Пре&кини везу\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Пун екран\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"&Умањи\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"&Величина прозора на сесију\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ктрл\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Алт\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Пошаљи Ктрл-Алт-&Дел\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&Освежи екран\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Могућности...\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Подаци о &вези...\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"О &TigerVNC-у...\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"Подаци о ВНЦ вези\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Прозор је регистрован за додир уместо покрета\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Нисам успео да поставим подешавање покрета (грешка 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Нисам успео да добавим информације покрета (грешка 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Неисправно дугме миша %d, мора бити број између 1 и 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Необрадиви тастер 0x%x – не могу да створим догађај тастатуре.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Не могу да добавим маску „X Input 2“ догађаја за прозор 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Прозор 0x%08lx нема маску „X Input 2“ догађаја\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Прозор 0x%08lx има више од једне маске „X Input 2“ догађаја\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Неуспех хватања уређаја %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Повежите се на ВНЦ сервер и прикажите удаљену радну површ\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Виртуелно мрежно рачунарство (VNC) је систем удаљеног приказа који вам омогућава да видте и радите са виртуелним окружењем радне површи које ради на другом рачунару на мрежи. Коришћењем ВМР-а, можете да покрећете графичке програме на удаљеном рачунару и да пошаљете само приказ тих програма вашем локалном уређају. Овај пакет садржи клијента који ће вам омогућити да се повежете са другим радним површима на којима ради ВМР сервер. ВМР је независан од платформе и подржава разне оперативне системе и архитектуре као и сервере и клијенте.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC великобрзинско издање ВНЦ-а засновано на основама „RealVNC“-у 4 и „X.org“ кода. TigerVNC је започео као развојно залагање следеће генерације за „TightVNC“ на Јуникс и Линукс платформама, али се издваја из свог родитељског пројекта у раним 2009 тако да се „TightVNC“ може фокусирати на Виндоуз платформама. TigerVNC подржава варијанту „Tight“ кодирања тако да је поприлично убрзан коришћењем „libjpeg-turbo“ ЈПЕГ кодека.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"Веза TigerVNC-а са CentOS рачунаром\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"Веза TigerVNC-а са macOS рачунаром\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"Веза TigerVNC-а са Виндоуз рачунаром\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"Тим TigerVNC-а\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Назив параметра је превелик\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"Параметар је превелик\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"Неисправан запис или предуга вредност\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"Нисам успео да направим кључ регистра\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"Нисам успео да затворим кључ регистра\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Нисам успео да сачувам „%s“: %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Нисам успео да уклоним „%s“: %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"Нисам успео да отворим кључ регистра\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Нисам успео да прочитам унос историјата сервера %d: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Нисам успео да прочитам параметар „%s“: %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"Не могу да одредим путању фасцикле ВНЦ подешавања\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"Не могу да кодирам параметар\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Датотека подешавања „%s“ је у неисправном запису\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"Неисправан запис\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"Непознат параметар\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Добих поруку (0x%x) за неруковани прозор\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Неисправан прозор 0x%08lx је наведен за хватање показивача\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Нисам успео да створим руковаоца додира: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Не могу да приложим руковаоца догађајем прозору (грешка 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Нисам успео да добавим податке догађаја за „X Input“ догађај\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"„X Input“ догађај за непознати прозор\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"„X Input“ проширење није доступно.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"„X Input 2“ (или новије) није доступно.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"„X Input 2“ (или новије) није доступно. Покрети додира неће бити подржани.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC и%s\\n\"\n\"Изграђен: %s\\n\"\n\"Ауторска права © 1999-%d Тим TigerVNC-а и многи други (видите „README.rst“)\\n\"\n\"Посетите „https://www.tigervnc.org“ да сазнате више о програму.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"О TigerVNC-у\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Унутрашња ФЛТК грешка. Излазим.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Да покушам да се поново повежем?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"Грешка покретања нове везе: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"Примљен је сигнал за окончавање %d. Програм ће сада изаћи.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Да\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Затвори\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"О програму\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Сакриј\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Изађи\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Услуге\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Сакриј остале\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Прикажи све\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Датотека\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Нова веза\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Коришћење: %s [parametri] [domaćin][:displayNum]\\n\"\n\"       %s [parametri] [domaćin][::port]\\n\"\n\"       %s [parametri] [priključnica linuksa]\\n\"\n\"       %s [parametri] -listen [prikqučnik]\\n\"\n\"       %s [parametri] [.tigervnc datteka]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Опције:\\n\"\n\"\\n\"\n\"  -display Xdisplay  – Наводи X приказ за прозор прегледача\\n\"\n\"  -geometry geometry – почетни положај главног прозора TigerVNC-а. Видите\\n\"\n\"                       страницу упутства за више о томе.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Параметри се могу укључити са „-<param>“ или искључити са „-<param>=0“\\n\"\n\"Параметри који имају вредност се могу навести као „-<param> <vrednost>“\\n\"\n\"Други исправни облици су „<param>=<vrednost> -<param>=<vrednost> --<param>=<vrednost>“\\n\"\n\"Називи параметара нису осетљиви на величину слова.  Параметри су:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"„FullScreenAllMonitors“ је застарело, поставите „FullScreenMode“ на „all“\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"„DotWhenNoCursor“ је застарело, поставите „AlwaysCursor“ на 1 и „CursorType“ на „Dot“ (тачка)\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"„~/.vnc“ је застарело, погледајте „man vncviewer“ за путање за пресељење.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"„%%APPDATA%%\\\\vnc“ је застарело, пређите на „%%APPDATA%%\\\\TigerVNC“.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"Не могу да направим фасциклу подешавања ВНЦ-а „%s“: %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"Не могу да одредим путању фасцикле ВНЦ података\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"Не могу да направим фасциклу података ВНЦ-а „%s“: %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"Не могу да направим фасциклу стања ВНЦ-а „%s“: %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: Непозната опција „%s“\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"Видите „%s --help“ за више информација.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Додатни аргумент „%s“\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Параметри „-listen“ и „-via“ нису сагласни\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Не могу да ослушкујем долазне везе\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Ослушкујем на прикључнику %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Грешка чекања на долазну ВНЦ везу:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Неуспех постављања шифрованог тунела:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"Прегледач удаљених радних површи\"\n\n#, c-format\n#~ msgid \"(server default %s)\"\n#~ msgstr \"(основно на серверу %s)\"\n\n#, c-format\n#~ msgid \"SetDesktopSize failed: %d\"\n#~ msgstr \"Неуспело подешавање величине радне површи: %d\"\n\n#~ msgid \"Invalid SetColourMapEntries from server!\"\n#~ msgstr \"Неисправни уноси подешавања мапе боје са сервера!\"\n\n#, c-format\n#~ msgid \"Invalid configuration specified for %s\"\n#~ msgstr \"Неисправно подешавање је наведено за „%s“\"\n\n#, c-format\n#~ msgid \"Invalid monitor index '%s'\"\n#~ msgstr \"Неисправан индекс монитора „%s“\"\n\n#, c-format\n#~ msgid \"Unexpected character '%c'\"\n#~ msgstr \"Неочекивани знак „%c“\"\n\n#~ msgid \"Pass system keys directly to server (full screen)\"\n#~ msgstr \"Проследи системске кључеве директно на сервер (пун екран)\"\n\n#~ msgid \"Menu key\"\n#~ msgstr \"Тастер изборника\"\n\n#~ msgid \"VNC viewer: Connection details\"\n#~ msgstr \"ВНЦ прегледач: Појединости повезивања\"\n\n#, c-format\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Send %s\"\n#~ msgstr \"Пошаљи „%s“\"\n\n#~ msgid \"TigerVNC viewer\"\n#~ msgstr \"Прегледач ТигарВНЦ\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"Прикажи тачку када нема курзора\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"Нисам успео да освежим стање диоде тастатуре: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"Није наведен код тастера на притисак истог\"\n\n#, c-format\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"Нема симбола за шифру кључа 0x%02x (у текућем стању)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"Непозната врста параметра\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"ВНЦ прегледач: Могућности повезивања\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"Разно\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"Нисам успео да добавим назив монитора јер не могу наћи „X11 RandR“\"\n\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"Нисам успео да добавим информације о „CRTC %d“\"\n\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"Нисам успео да добавим информације о излазу %d за „CRTC %d“\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"Екран\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"Промени величину удаљене сесије приликом повезивања\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"Промени величину удаљене сесије на месни прозор\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"Укључи преко целог екрана\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"Пун (све доступне боје)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"Средњи (256 боја)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"Низак (64 боје)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"Врло низак (8 боје)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"ниво (1=брзо, 6=најбоље [4-6 се ретко користи])\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"Режим пуног екрана\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"&Напусти прегледача\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"Одбаци &изборник\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"Нисам успео да упишем параметар „%s“ врсте „%s“ у регистар: %ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"Назив параметра „%s“ беше превелик за читање из регистра\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"Параметар „%s“ беше превелик за читање из регистра\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"Нисам успео да упишем датотеку подешавања, не могу да добијем путању личне фасцикле.\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"Нисам успео да упишем датотеку подешавања, не могу да отворим „%s“: %s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"Нисам успео да прочитам датотеку подешавања, не могу да добијем путању личне фасцикле.\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"Непознат параметар „%s“ у %d. реду у датотеци „%s“\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"Не могу да направим личну фасциклу ВНЦ-а: не могу да добијем путању личне фасцикле.\"\n\n#~ msgid \"tigervnc\"\n#~ msgstr \"tigervnc\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Укључујем непрекидно освежавање\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"искључена\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"укључена\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Користим „%s“ кодирање\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"Нема довољно меморије за међумеморију кадра\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"Не могу да направим уређај међумеморије кадра\"\n\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"Не могу да направим битмапу међумеморије кадра\"\n\n#~ msgid \"Unable to create platform specific framebuffer: %s\"\n#~ msgstr \"Не могу да направим међумеморију кадра особену за платформу: %s\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"Користим међумеморију кадра независну од платформе\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"Не могу да направим одељак ДИБ\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"Није успело прављење сагласног ДЦ-а\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"Није успело бирање објекта\"\n\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"Није успело Бит блт\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"Приказу недостаје формат пиксмапе за основну дубину\"\n\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"Не могу да нађем погодан формат пиксмапе\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"Само прикази праве боје су подржани\"\n\n#~ msgid \"Using default colormap and visual, TrueColor, depth %d.\"\n#~ msgstr \"Користим основну мапу боје и видности, Права боја, дубине %d.\"\n\n#~ msgid \"Unknown encoding %d\"\n#~ msgstr \"Непознато кодирање „%d“\"\n\n#~ msgid \"Unknown encoding\"\n#~ msgstr \"Непознато кодирање\"\n"
  },
  {
    "path": "po/sv.po",
    "content": "# Swedish messages for TigerVNC.\n# Copyright © 2026 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the TigerVNC package.\n#\n# Peter Åstrand <astrand@cendio.se>, 2011.\n# Göran Uddeborg <goeran@uddeborg.se>, 2015, 2016, 2017, 2018, 2019, 2021, 2022.\n# Luna Jernberg <droidbittin@gmail.com>, 2022, 2024, 2025.\n# Daniel Nylander <po@danielnylander.se>, 2026.\n#\n# $Revision: 1.25 $\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2026-03-11 14:06+0100\\n\"\n\"Last-Translator: Daniel Nylander <po@danielnylander.se>\\n\"\n\"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\\n\"\n\"Language: sv\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.8\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Ansluten till uttaget %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"Ansluten till värden %s port %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Misslyckades med att ansluta till ”%s”:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Skrivbordsnamn: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Värd: %.80s port: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Storlek: %d x %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Bildpunktsformat: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Begärd kodning: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Senast använd kodning: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Uppskattad hastighet på förbindelsen: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Protokollversion: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Säkerhetsmetod: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Anslutningen släpptes av servern innan sessionen kunde etableras.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Autentisering misslyckades: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Misslyckades med autentisering med servern. Anledning från servern:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Bandbredd %d kbit/s - byter till kvalitet %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Bandbredd %d kbit/s – fullfärg är nu aktiverat\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Bandbredd %d kbit/s – fullfärg är nu inaktiverat\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Använder bildpunktsformatet %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Ogiltig geometri angiven!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Reducerar fönsterstorleken till att passa på den aktuella bildskärmen\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"Tryck på %sM för att öppna snabbmenyn\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s - TigerVNC (tangentbordet fångat)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s - TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Justerar fönsterstorleken för att undvika fullskärm av misstag\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"Tryck på %sEnter för att lämna helskärmsläget\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"Misslyckades med att ta kontroll över tangentbordet\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"Tryck på %s för att frigöra tangentbordskontrollen från sessionen\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Ogiltig skärmlayout beräknad för storleksförändrings-begäran!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Felaktigt tillstånd för 3-knappsemulering\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Ingen skanningskod för utökad virtuell tangent 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Ingen skanningskod för virtuell tangent 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Felaktig skanningskod 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Ingen symbol för utökad virtuell tangent 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Ingen symbol för virtuell tangent 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Misslyckades att uppdatera tillståndet för tangentbords-LED: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Ingen symbol för tangentkod %d (i nuvarande tillstånd)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Misslyckades att hämta tillståndet för tangentbords-LED: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Misslyckades att uppdatera tillståndet för tangentbords-LED\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Misslyckades att hämta systemets bildskärmskonfiguration\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Bildskärmsindex %d finns inte\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"TigerVNC-alternativ\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Avbryt\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"Ok\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"Komprimering\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"Automatiskt val\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"Tillåt JPEG-komprimering\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"Föredragen kodning\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"Färgnivå\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"Fullständig\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"Medel\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"Låg\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"Mycket låg\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"Anpassad komprimeringsnivå\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"nivå (0=snabb, 9=bäst)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"Kvalitetsnivå\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"kvalitet (0=dålig, 9=bäst)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"Säkerhet\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"Kryptering\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"Ingen\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS med anonyma certifikat\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS med X509-certifikat\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Sökväg till CA-certifikat för X509\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Sökväg till CRL-fil för X509\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"Autentisering\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Standard-VNC (osäkert utan kryptering)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Användarnamn och lösenord (osäkert utan kryptering)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"Inmatning\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Endast visning (ignorera mus och tangentbord)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"Mus\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Emulera mittenknapp på musen\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Visa den lokala markören när den inte tillhandahålls av servern\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"Markörtyp\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"Punkt\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"System\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"Tangentbord\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"Skicka alltid alla tangentbordsinmatningar i helskärmsläge\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"Urklipp\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"Acceptera urklipp från server\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"Ställ även in primär markering\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"Skicka urklipp till server\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Skicka primär markering som urklipp\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"Tangentbordsgenvägar\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"Modifieringstangenter för tangentbordsgenvägar:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Skift\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Skift\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Option\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"Display\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"Visningsläge\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"Fönster\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"Helskärm på nuvarande bildskärm\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"Helskärm på alla bildskärmar\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Helskärm på valda bildskärmar\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"Diverse\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Delad (koppla ej från andra visare)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Be att få återansluta vid anslutningsfel\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"Alla tangentbordsgenvägar är inaktiverade.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"Tryck på %s för att frigöra tangentbordskontrollen från sessionen.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"Tryck på %sG för att vidarebefordra all tangentbordsinmatning till sessionen.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"Tryck på %sEnter för att växla till helskärmsläge.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"Tryck på %sM för att öppna sessionens snabbmeny.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"För att skicka en tangentkombination som innehåller %s direkt till sessionen, tryck på %sMellanslag, släpp mellanslagstangenten utan att släppa %s och tryck på önskad tangent.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"VNC-server:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"Alternativ...\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"Läs in...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"Spara som...\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"Om...\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"Anslut\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Kan inte läsa in serverhistoriken:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"TigerVNC-konfiguration (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Välj en TigerVNC-konfigurationsfil\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Kunde inte läsa in den angivna konfigurationsfilen:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Spara TigerVNC-konfigurationen i en fil\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s finns redan.  Vill du skriva över den?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Nej\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"Skriv över\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Kunde inte spara den angivna konfigurationsfilen:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Kan inte spara standardkonfigurationen:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Kan inte spara serverhistoriken:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"Kunde inte bestämma VNC-tillståndskatalogsökväg\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"Kunde inte öppna \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Misslyckades med att läsa rad %d i fil \\\"%s\\\"\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"Raden är för lång\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"Öppning av lösenordsfilen misslyckades\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"VNC-autentisering\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"Denna anslutning är säker\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"Denna anslutning är inte säker\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"Användarnamn:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"Lösenord:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"Behåll lösenordet för att återansluta\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Ett oväntat fel uppstod vid kommunikation med servern:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"Koppla f&rån\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Helskärm\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"M&inimera\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Storleksanpassa &fönster till session\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"A&lt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Skicka Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&Uppdatera skärm\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Alternativ...\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"&Information om anslutning...\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"Om &TigerVNC...\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"VNC-anslutningsinformation\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Fönstret har registrerats för beröring istället för gester\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Misslyckades med att ställa in gestkonfigurationen (fel 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Misslyckades att få gestinformation (fel 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Felaktig musknapp %d, måste vara ett nummer mellan 1 och 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Icke-hanterad tangent 0x%x — kan inte generera en tangentbordshändelse.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Kan inte få X-inmatning 2 händelsemask för fönster 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Fönster 0x%08lx har ingen X inmatning 2 händelsemask\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Fönster 0x%08lx har mer än en X inmatning 2 händelsemask\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Misslyckades med att fånga enhet %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Anslut till en VNC-server och visa ett fjärrskrivbord\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC) är ett system för fjärrskrivbord som gör att man kan se och interagera med en virtuell skrivbordsmiljö som kör på en annan dator i nätverket. Genom att använda VNC kan man köra grafiska program på en fjärrmaskin och skicka bara det som visas från dessa program till den lokala enheten. Detta paket innehåller en klient vilken kommer göra det möjligt att ansluta till andra skrivbord som kör en VNC-server. VNC är plattformsoberoende och har stöd för olika operativsystem och arkitekturer både som servrar och klienter.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC är en höghastighetsversion av VNC baserat på kodbaserna RealVNC 4 och X.org. TigerVNC startades som ett arbete att utveckla nästa generation av TightVNC på Unix- och Linuxplattformar, men delades av från sitt överliggande projekt i början av 2009 så att TightVNC kunde fokusera på plattformen Windows. TigerVNC stödjer en variant av Tight-kodning som är kraftigt accelererad genom användning av JPEG-omkodaren från libjpeg-turbo.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"TigerVNC-anslutning till en CentOS-dator\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"TigerVNC-anslutning till en macOS-dator\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"TigerVNC-anslutning till en Windows-dator\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"TigerVNC-teamet\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Namnet på parametern är för stort\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"Parametern är för stor\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"Ogiltigt format eller för stort värde\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"Misslyckades med att skapa registernyckel\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"Misslyckades med att stänga registernyckel\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Misslyckades att spara ”%s”: %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Misslyckades att ta bort ”%s”: %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"Misslyckades med att öppna registernyckel\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Misslyckades med att läsa serverhistorikpost %d: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Misslyckades med att läsa parametern ”%s”: %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"Kunde inte bestämma VNC-konfigurationskatalogsökvägen\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"Kunde inte koda parametern\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Konfigurationsfilen %s har ogiltigt format\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"Ogiltigt format\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"Okänd parameter\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Fick ett meddelande (0x%x) för ett ej hanterat fönster\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Felaktigt fönster 0x%08lx angivet för pekargrepp\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Misslyckades med att skapa en beröringshanterare: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Kunde inte koppla en händelsehanterare till fönstret (fel 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Misslyckades att få händelsedata för en X inmatningshändelse\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"X Input-händelse för ett okänt fönster\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"X Input-utökning är inte tillgänglig.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2 (eller nyare) är inte tillgänglig.\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2.2 (eller nyare) är inte tillgänglig. Beröringsgester kommer inte stödjas.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC v%s\\n\"\n\"Byggt på: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC-teamet och många andra (se README.rst)\\n\"\n\"Se https://www.tigervnc.org för information om TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"Om TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Internt FLTK-fel. Avslutar.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Försök att återansluta?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"Fel vid start av ny anslutning: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"Avslutningssignal %d har mottagits. TigerVNC kommer nu att avslutas.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Ja\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Stäng\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"Om\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Dölj\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Avsluta\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Tjänster\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Dölj andra\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Visa alla\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Arkiv\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Ny anslutning\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Användning: %s [parametrar] [värd][:displayNum]\\n\"\n\"       %s [parametrar] [värd][::port]\\n\"\n\"       %s [parametrar] [unix-uttag]\\n\"\n\"       %s [parametrar] -listen [port]\\n\"\n\"       %s [parametrar] [.tigervnc-fil]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Flaggor:\\n\"\n\"  -display Xdisplay  - Anger X-skärmen för visningsfönstret\\n\"\n\"  -geometry geometri - Startposition för TigerVNC:s huvudfönster. Se\\n\"\n\"                       manualsidan för mer information.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Parametrar kan aktiveras med -<param> eller av med -<param>=0\\n\"\n\"Parametrar som tar ett värde kan specificeras som -<param> <value>\\n\"\n\"Andra giltiga former är <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameternamn är inte skiftlägeskänsliga. Parametrarna är:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors är föråldrat, ställ in FullScreenMode till ”all” istället\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor är utfasad, ställ in AlwaysCursor till 1 och CursorType till \\\"Dot\\\" istället\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc är utfasad, konsultera 'man vncviewer' för sökvägar att migrera till.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc är utfasad, byt till %%APPDATA%%\\\\TigerVNC-platsen.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"Kunde inte skapa en VNC-konfigurationskatalog: \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"Kunde inte fastställa sökvägen till VNC-datakatalogen\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"Kunde inte skapa en VNC-datakatalog: \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"Kunde inte skapa VNC-tillståndskatalog: \\\"%s\\\": %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: Okänd flagga '%s'\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"Se '%s --help' för mer information.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: Extra argument '%s'\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Parametrarna -listen och -via är inkompatibla\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Misslyckades att lyssna efter inkommande anslutningar\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Lyssnar på port %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Misslyckades att vänta på inkommande VNC-förbindelse:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Misslyckades med att konfigurera krypterad tunnel:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"Fjärrskrivbordsvisare\"\n\n#, c-format\n#~ msgid \"(server default %s)\"\n#~ msgstr \"(serverstandard %s)\"\n\n#, c-format\n#~ msgid \"SetDesktopSize failed: %d\"\n#~ msgstr \"SetDesktopSize misslyckades: %d\"\n\n#~ msgid \"Invalid SetColourMapEntries from server!\"\n#~ msgstr \"Ogiltig SetColourMapEntries från server!\"\n\n#, c-format\n#~ msgid \"Invalid configuration specified for %s\"\n#~ msgstr \"Ogiltig konfiguration angiven för %s\"\n\n#, c-format\n#~ msgid \"Invalid monitor index '%s'\"\n#~ msgstr \"Felaktigt skärmindex ”%s”\"\n\n#, c-format\n#~ msgid \"Unexpected character '%c'\"\n#~ msgstr \"Oväntat tecken ”%c”\"\n\n#~ msgid \"Pass system keys directly to server (full screen)\"\n#~ msgstr \"Skicka systemtangenter direkt till servern (fullskärm)\"\n\n#~ msgid \"Menu key\"\n#~ msgstr \"Menytangent\"\n\n#~ msgid \"VNC viewer: Connection details\"\n#~ msgstr \"VNC visare: Anslutningsdetaljer\"\n\n#, c-format\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Send %s\"\n#~ msgstr \"Skicka %s\"\n\n#~ msgid \"TigerVNC viewer\"\n#~ msgstr \"TigerVNC-visare\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"Visa punkt när muspekare saknas\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"Misslyckades att uppdatera tillståndet för tangentbords-LED: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"Ingen tangentkod angiven vid tangenttryckning\"\n\n#, c-format\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"Ingen symbol för tangentkod 0x%02x (i nuvarande tillstånd)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"Okänd parametertyp\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"VNC-visare: Anslutningsalternativ\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"Diverse.\"\n"
  },
  {
    "path": "po/tigervnc.pot",
    "content": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR TigerVNC team and many others (see README.rst)\n# This file is distributed under the same license as the PACKAGE package.\n# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: PACKAGE VERSION\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n\"\n\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n\"Language: \\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"\"\n\"The connection was dropped by the server before the session could be \"\n\"established.\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"\"\n\"To send a key combination that includes %s directly to the session, press \"\n\"%sSpace, release the space bar without releasing %s, and press the desired \"\n\"key.\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"\"\n\"Virtual Network Computing (VNC) is a remote display system that allows you \"\n\"to view and interact with a virtual desktop environment running on another \"\n\"computer on the network. Using VNC, you can run graphical applications on a \"\n\"remote machine and send only the display from these applications to your \"\n\"local device. This package contains a client which will enable you to \"\n\"connect to other desktops running a VNC server. VNC is platform-independent \"\n\"and supports various operating systems and architectures as both servers and \"\n\"clients.\"\nmsgstr \"\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"\"\n\"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org \"\n\"code bases. TigerVNC started as a next-generation development effort for \"\n\"TightVNC on Unix and Linux platforms, but it split from its parent project \"\n\"in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC \"\n\"supports a variant of Tight encoding that is greatly accelerated by the use \"\n\"of the libjpeg-turbo JPEG codec.\"\nmsgstr \"\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"\"\n\"X Input 2.2 (or newer) is not available. Touch gestures will not be \"\n\"supported.\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See \"\n\"the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"\"\n\"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"\"\n\"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' \"\n\"instead\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"\"\n\"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"\"\n\"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC \"\n\"location.\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"\"\n"
  },
  {
    "path": "po/tr.po",
    "content": "# Turkish translation for tigervnc.\n# Copyright (C) TigerVNC Team\n# This file is distributed under the same license as the tigervnc package.\n# Volkan Gezer <volkangezer@gmail.com>, 2017.\n# Volkan Gezer <volkangezer@gmail.com>, 2023.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.12.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2022-12-15 16:35+0100\\n\"\n\"PO-Revision-Date: 2023-09-08 22:51+0200\\n\"\n\"Last-Translator: Volkan Gezer <volkangezer@gmail.com>\\n\"\n\"Language-Team: Turkish <gnome-turk@gnome.org>\\n\"\n\"Language: tr\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=2; plural=(n > 1);\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.2.2\\n\"\n\n#: vncviewer/CConn.cxx:103\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"Bağlı olunan soket: %s\"\n\n#: vncviewer/CConn.cxx:110\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"%s ana makinesinin, %d bağlantı noktasına bağlı\"\n\n#: vncviewer/CConn.cxx:114\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"\\\"%s\\\" makinesine bağlanılamadı:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:159\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Masaüstü adı: %.80s\"\n\n#: vncviewer/CConn.cxx:164\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Ana makine: %.80s bağlantı noktası: %d\"\n\n#: vncviewer/CConn.cxx:169\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Boyut: %d x %d\"\n\n#: vncviewer/CConn.cxx:177\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Piksel biçimi: %s\"\n\n#: vncviewer/CConn.cxx:184\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(sunucu varsayılanı %s)\"\n\n#: vncviewer/CConn.cxx:189\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"İstenen kodlama: %s\"\n\n#: vncviewer/CConn.cxx:194\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Son kullanılan kodlama: %s\"\n\n#: vncviewer/CConn.cxx:199\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Hat hızı tahmini: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Protokol sürümü: %d.%d\"\n\n#: vncviewer/CConn.cxx:209\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Güvenlik yöntemi: %s\"\n\n#: vncviewer/CConn.cxx:270 vncviewer/CConn.cxx:272\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"Oturum kurulmadan bağlantı sunucu tarafından kesildi.\"\n\n#: vncviewer/CConn.cxx:332\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"SetDesktopSize başarısız: %d\"\n\n#: vncviewer/CConn.cxx:404\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"Sunucudan gelen geçersiz SetColourMapEntries!\"\n\n#: vncviewer/CConn.cxx:512\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Verim %d kbit/s - %d kalitesine değiştiriliyor\"\n\n#: vncviewer/CConn.cxx:534\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Verim %d kbit/s - tam renkli artık etkin\"\n\n#: vncviewer/CConn.cxx:537\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Verim %d kbit/s - tam renkli artık devre dışı\"\n\n#: vncviewer/CConn.cxx:563\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"%s piksel biçimi kullanılıyor\"\n\n#: vncviewer/DesktopWindow.cxx:145\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Geçersiz geometri belirtildi!\"\n\n#: vncviewer/DesktopWindow.cxx:166\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Geçerli monitöre sığması için pencere boyutu azaltılıyor\"\n\n#: vncviewer/DesktopWindow.cxx:648\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Yanlışlıkla tam ekran isteğini önlemek için pencere boyutu ayarlanıyor\"\n\n#: vncviewer/DesktopWindow.cxx:696\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Bağlam menüsünü açmak için %s tuşuna basın\"\n\n#: vncviewer/DesktopWindow.cxx:1083 vncviewer/DesktopWindow.cxx:1091\n#: vncviewer/DesktopWindow.cxx:1111\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Klavye yakalanamadı\"\n\n#: vncviewer/DesktopWindow.cxx:1401\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Yeniden boyutlandırma isteği için geçersiz ekran düzeni hesaplandı!\"\n\n#: vncviewer/EmulateMB.cxx:226 vncviewer/EmulateMB.cxx:289\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"3 düğme emülasyonu için geçersiz durum\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:52\n#: vncviewer/MonitorIndicesParameter.cxx:105\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Sistem monitörü yapılandırması alınamadı\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:83\n#, c-format\nmsgid \"Invalid configuration specified for %s\"\nmsgstr \"%s için geçersiz yapılandırma belirtildi\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:91\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"%d monitör dizini mevcut değil\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:169\n#: vncviewer/MonitorIndicesParameter.cxx:189\n#, c-format\nmsgid \"Invalid monitor index '%s'\"\nmsgstr \"Geçersiz monitör dizini '%s'\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:177\n#, c-format\nmsgid \"Unexpected character '%c'\"\nmsgstr \"Beklenmeyen karakter '%c'\"\n\n#: vncviewer/OptionsDialog.cxx:63\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"VNC Görüntüleyici: Bağlantı Seçenekleri\"\n\n#: vncviewer/OptionsDialog.cxx:89 vncviewer/ServerDialog.cxx:108\n#: vncviewer/vncviewer.cxx:417\nmsgid \"Cancel\"\nmsgstr \"İptal\"\n\n#: vncviewer/OptionsDialog.cxx:94 vncviewer/vncviewer.cxx:416\nmsgid \"OK\"\nmsgstr \"Tamam\"\n\n#: vncviewer/OptionsDialog.cxx:484\nmsgid \"Compression\"\nmsgstr \"Sıkıştırma\"\n\n#: vncviewer/OptionsDialog.cxx:501\nmsgid \"Auto select\"\nmsgstr \"Otomatik seç\"\n\n#: vncviewer/OptionsDialog.cxx:516\nmsgid \"Preferred encoding\"\nmsgstr \"Tercih edilen kodlama\"\n\n#: vncviewer/OptionsDialog.cxx:574\nmsgid \"Color level\"\nmsgstr \"Renk seviyesi\"\n\n#: vncviewer/OptionsDialog.cxx:585\nmsgid \"Full\"\nmsgstr \"Tam dolu\"\n\n#: vncviewer/OptionsDialog.cxx:592\nmsgid \"Medium\"\nmsgstr \"Orta\"\n\n#: vncviewer/OptionsDialog.cxx:599\nmsgid \"Low\"\nmsgstr \"Düşük\"\n\n#: vncviewer/OptionsDialog.cxx:606\nmsgid \"Very low\"\nmsgstr \"Çok düşük\"\n\n#: vncviewer/OptionsDialog.cxx:624\nmsgid \"Custom compression level:\"\nmsgstr \"Özel sıkıştırma seviyesi:\"\n\n#: vncviewer/OptionsDialog.cxx:630\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"kalite (0=hızlı, 9=en iyi)\"\n\n#: vncviewer/OptionsDialog.cxx:637\nmsgid \"Allow JPEG compression:\"\nmsgstr \"JPEG sıkıştırmasına izin ver:\"\n\n#: vncviewer/OptionsDialog.cxx:643\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"kalite (0=düşük, 9=yüksek)\"\n\n#: vncviewer/OptionsDialog.cxx:654\nmsgid \"Security\"\nmsgstr \"Güvenlik\"\n\n#: vncviewer/OptionsDialog.cxx:676\nmsgid \"Encryption\"\nmsgstr \"Şifreleme\"\n\n#: vncviewer/OptionsDialog.cxx:687 vncviewer/OptionsDialog.cxx:750\n#: vncviewer/OptionsDialog.cxx:854\nmsgid \"None\"\nmsgstr \"Yok\"\n\n#: vncviewer/OptionsDialog.cxx:694\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"Adsız sertifikalı  TLS\"\n\n#: vncviewer/OptionsDialog.cxx:700\nmsgid \"TLS with X509 certificates\"\nmsgstr \"X509 sertifikalı TLS\"\n\n#: vncviewer/OptionsDialog.cxx:707\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"X509 CA sertifikası yolu\"\n\n#: vncviewer/OptionsDialog.cxx:714\nmsgid \"Path to X509 CRL file\"\nmsgstr \"X509  CRL  dosyası  yolu\"\n\n#: vncviewer/OptionsDialog.cxx:739\nmsgid \"Authentication\"\nmsgstr \"Doğrulama\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Standart VNC (şifreleme olmadan güvensiz)\"\n\n#: vncviewer/OptionsDialog.cxx:762\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Kullanıcı adı ve şifre (şifreleme olmadan güvensiz)\"\n\n#: vncviewer/OptionsDialog.cxx:781\nmsgid \"Input\"\nmsgstr \"Girdi\"\n\n#: vncviewer/OptionsDialog.cxx:794\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Yalnızca görüntüleme (fare ve klavyeyi yoksay)\"\n\n#: vncviewer/OptionsDialog.cxx:801\nmsgid \"Mouse\"\nmsgstr \"Fare\"\n\n#: vncviewer/OptionsDialog.cxx:815\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Orta fare düğmesini taklit et\"\n\n#: vncviewer/OptionsDialog.cxx:821\nmsgid \"Show dot when no cursor\"\nmsgstr \"İmleç yokken nokta göster\"\n\n#: vncviewer/OptionsDialog.cxx:835\nmsgid \"Keyboard\"\nmsgstr \"Tuş takımı\"\n\n#: vncviewer/OptionsDialog.cxx:849\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Sistem tuşlarını doğrudan sunucuya aktar (tam ekran)\"\n\n#: vncviewer/OptionsDialog.cxx:852\nmsgid \"Menu key\"\nmsgstr \"Menü tuşu\"\n\n#: vncviewer/OptionsDialog.cxx:871\nmsgid \"Clipboard\"\nmsgstr \"Pano\"\n\n#: vncviewer/OptionsDialog.cxx:885\nmsgid \"Accept clipboard from server\"\nmsgstr \"Sunucudan panoyu kabul et\"\n\n#: vncviewer/OptionsDialog.cxx:893\nmsgid \"Also set primary selection\"\nmsgstr \"Birincil seçim olarak da ayarla\"\n\n#: vncviewer/OptionsDialog.cxx:900\nmsgid \"Send clipboard to server\"\nmsgstr \"Panodan sunucuya gönder\"\n\n#: vncviewer/OptionsDialog.cxx:908\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Birincil seçimi pano olarak gönder\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Display\"\nmsgstr \"Görüntü\"\n\n#: vncviewer/OptionsDialog.cxx:941\nmsgid \"Display mode\"\nmsgstr \"Ekran kipi\"\n\n#: vncviewer/OptionsDialog.cxx:956\nmsgid \"Windowed\"\nmsgstr \"Pencereli\"\n\n#: vncviewer/OptionsDialog.cxx:964\nmsgid \"Full screen on current monitor\"\nmsgstr \"Mevcut monitörde tam ekran\"\n\n#: vncviewer/OptionsDialog.cxx:972\nmsgid \"Full screen on all monitors\"\nmsgstr \"Tüm monitörlerde tam ekranı etkinleştir\"\n\n#: vncviewer/OptionsDialog.cxx:980\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Seçilen monitör(ler)de tam ekranı etkinleştir\"\n\n#: vncviewer/OptionsDialog.cxx:1007\nmsgid \"Misc.\"\nmsgstr \"Çeşitli\"\n\n#: vncviewer/OptionsDialog.cxx:1015\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Paylaşılan (diğer görüntüleyenlerin bağlantısını kesme)\"\n\n#: vncviewer/OptionsDialog.cxx:1021\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Bağlantı hatalarında yeniden bağlanmayı iste\"\n\n#: vncviewer/ServerDialog.cxx:58\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"VNC Görüntüleyici: Bağlantı Bilgileri\"\n\n#: vncviewer/ServerDialog.cxx:65 vncviewer/ServerDialog.cxx:70\nmsgid \"VNC server:\"\nmsgstr \"VNC sunucusu:\"\n\n#: vncviewer/ServerDialog.cxx:81\nmsgid \"Options...\"\nmsgstr \"Seçenekler...\"\n\n#: vncviewer/ServerDialog.cxx:86\nmsgid \"Load...\"\nmsgstr \"Yükle...\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save As...\"\nmsgstr \"Farklı Kaydet...\"\n\n#: vncviewer/ServerDialog.cxx:103\nmsgid \"About...\"\nmsgstr \"Hakkında...\"\n\n#: vncviewer/ServerDialog.cxx:113\nmsgid \"Connect\"\nmsgstr \"Bağlan\"\n\n#: vncviewer/ServerDialog.cxx:145\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Sunucu geçmişi yüklenemiyor:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:173 vncviewer/ServerDialog.cxx:212\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"TigerVNC yapılandırması (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:174\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"TigerVNC yapılandırma dosyasını seçin\"\n\n#: vncviewer/ServerDialog.cxx:196 vncviewer/vncviewer.cxx:552\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Belirtilen yapılandırma dosyası yüklenemiyor:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:213\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"TigerVNC yapılandırmasını dosyaya kaydedin\"\n\n#: vncviewer/ServerDialog.cxx:239\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s zaten mevcut. Üzerine yazmak istiyor musunuz?\"\n\n#: vncviewer/ServerDialog.cxx:240 vncviewer/vncviewer.cxx:414\nmsgid \"No\"\nmsgstr \"Hayır\"\n\n#: vncviewer/ServerDialog.cxx:240\nmsgid \"Overwrite\"\nmsgstr \"Üzerine yaz\"\n\n#: vncviewer/ServerDialog.cxx:256\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Belirtilen yapılandırma dosyası kaydedilemiyor:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:290\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Varsayılan yapılandırma kaydedilemiyor:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:303\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Sunucu geçmişi kaydedilemiyor:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:320 vncviewer/ServerDialog.cxx:387\n#: vncviewer/parameters.cxx:635 vncviewer/parameters.cxx:740\n#: vncviewer/vncviewer.cxx:459\nmsgid \"Could not obtain the home directory path\"\nmsgstr \"VNC ana dizini edinilemedi\"\n\n#: vncviewer/ServerDialog.cxx:333 vncviewer/ServerDialog.cxx:396\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:753\n#, c-format\nmsgid \"Could not open \\\"%s\\\": %s\"\nmsgstr \"\\\"%s\\\" açılamadı: %s\"\n\n#: vncviewer/ServerDialog.cxx:348 vncviewer/ServerDialog.cxx:356\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:773\n#: vncviewer/parameters.cxx:804 vncviewer/parameters.cxx:833\n#: vncviewer/parameters.cxx:839\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"%d satırını %s dosyasından okumak başarısız: %s\"\n\n#: vncviewer/ServerDialog.cxx:357 vncviewer/parameters.cxx:774\nmsgid \"Line too long\"\nmsgstr \"Satır çok uzun\"\n\n#: vncviewer/UserDialog.cxx:98\nmsgid \"Opening password file failed\"\nmsgstr \"Parola dosyası açılamadı\"\n\n#: vncviewer/UserDialog.cxx:118\nmsgid \"VNC authentication\"\nmsgstr \"VNC doğrulaması\"\n\n#: vncviewer/UserDialog.cxx:125\nmsgid \"This connection is secure\"\nmsgstr \"Bu bağlantı güvenlidir\"\n\n#: vncviewer/UserDialog.cxx:129\nmsgid \"This connection is not secure\"\nmsgstr \"Bu bağlantı güvenli değil\"\n\n#: vncviewer/UserDialog.cxx:146\nmsgid \"Username:\"\nmsgstr \"Kullanıcı adı:\"\n\n#: vncviewer/UserDialog.cxx:159\nmsgid \"Password:\"\nmsgstr \"Şifre:\"\n\n#: vncviewer/UserDialog.cxx:198\nmsgid \"Authentication cancelled\"\nmsgstr \"Doğrulama iptal edildi\"\n\n#: vncviewer/Viewport.cxx:391\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Klavye LED durumu güncellenemedi: %lu\"\n\n#: vncviewer/Viewport.cxx:397 vncviewer/Viewport.cxx:403\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"Klavye LED durumu güncellenemedi: %d\"\n\n#: vncviewer/Viewport.cxx:433\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Klavye LED durumu güncellenemedi\"\n\n#: vncviewer/Viewport.cxx:460 vncviewer/Viewport.cxx:468\n#: vncviewer/Viewport.cxx:485\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Klavye LED durumu alınamadı: %d\"\n\n#: vncviewer/Viewport.cxx:849\nmsgid \"No key code specified on key press\"\nmsgstr \"Tuşa basıldığında tuş kodu belirtilmedi\"\n\n#: vncviewer/Viewport.cxx:1008\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Genişletilmiş sanal tuş 0x%02x için hiçbir tarama kodu yok\"\n\n#: vncviewer/Viewport.cxx:1010\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Sanal tuş 0x%02x için tarama kodu yok\"\n\n#: vncviewer/Viewport.cxx:1016\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Geçersiz tarama kodu 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1046\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Genişletilmiş sanal tuş 0x%02x için simge yok\"\n\n#: vncviewer/Viewport.cxx:1048\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Sanal tuş 0x%02x için simge yok\"\n\n#: vncviewer/Viewport.cxx:1154\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"Tuş kodu 0x%02x için simge yok (mevcut durumda)\"\n\n#: vncviewer/Viewport.cxx:1187\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Tuş kodu %d için simge yok (mevcut durumda)\"\n\n#: vncviewer/Viewport.cxx:1247\nmsgctxt \"ContextMenu|\"\nmsgid \"Dis&connect\"\nmsgstr \"Bağlantıyı &Kes\"\n\n#: vncviewer/Viewport.cxx:1250\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&Tam Ekran\"\n\n#: vncviewer/Viewport.cxx:1253\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"K&üçült\"\n\n#: vncviewer/Viewport.cxx:1255\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Pencereyi &oturuma tekrar boyutlandır\"\n\n#: vncviewer/Viewport.cxx:1260\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:1263\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1269\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"%s gönder\"\n\n#: vncviewer/Viewport.cxx:1275\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Ctrl-Alt-Del &Gönder\"\n\n#: vncviewer/Viewport.cxx:1278\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"Ekranı &yenile\"\n\n#: vncviewer/Viewport.cxx:1281\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"&Seçenekler...\"\n\n#: vncviewer/Viewport.cxx:1283\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Bağlantı &bilgisi...\"\n\n#: vncviewer/Viewport.cxx:1285\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"TigerVNC görüntüleyici &hakkında...\"\n\n#: vncviewer/Viewport.cxx:1374\nmsgid \"VNC connection info\"\nmsgstr \"VNC Bağlantı bilgisi\"\n\n#: vncviewer/Win32TouchHandler.cxx:47\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Pencere, hareketler yerine dokunma için kaydedildi\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Hareket yapılandırması ayarlanamadı (hata 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Hareket bilgileri alınamadı (hata 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:358\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Geçersiz fare düğmesi %d, 1 ile 7 arasında bir sayı olmalıdır.\"\n\n#: vncviewer/Win32TouchHandler.cxx:423\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"İşlenmeyen anahtar 0x%x - klavye olayı oluşturulamıyor.\"\n\n#: vncviewer/XInputTouchHandler.cxx:102 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"0x%08lx penceresi için X Giriş 2 olay maskesi alınamıyor\"\n\n#: vncviewer/XInputTouchHandler.cxx:104\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"Pencere 0x%08lx'te X Girişi 2 olay maskesi yok\"\n\n#: vncviewer/XInputTouchHandler.cxx:112 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"Pencere 0x%08lx'te birden fazla X Girişi 2 olay maskesi var\"\n\n#: vncviewer/XInputTouchHandler.cxx:143\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Başarısızlık yakalama cihazı %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.cxx:406 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"TigerVNC Görüntüleyici\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"VNC sunucusuna bağlanın ve uzak masaüstünü görüntüleyin\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Sanal Ağ Bilgi İşlem (VNC), ağdaki başka bir bilgisayarda çalışan sanal masaüstü ortamını görüntülemenize ve etkileşimde bulunmanıza olanak tanıyan bir uzak görüntüleme sistemidir. VNC'yi kullanarak uzaktaki bir makinede grafik uygulamaları çalıştırabilir ve bu uygulamaların yalnızca ekranını yerel cihazınıza gönderebilirsiniz. Bu paket, VNC sunucusu çalıştıran diğer masaüstlerine bağlanmanızı sağlayacak bir istemci içerir. VNC platformdan bağımsızdır ve hem sunucu hem de istemci olarak çeşitli işletim sistemlerini ve mimarileri destekler.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC, RealVNC 4 ve X.org kod tabanlarını temel alan yüksek hızlı bir VNC sürümüdür. TigerVNC, TightVNC'nin Unix ve Linux platformlarında yeni nesil geliştirme çalışması olarak başladı, ancak TightVNC'nin Windows platformlarına odaklanabilmesi için 2009'un başlarında ana projesinden ayrıldı. TigerVNC, libjpeg-turbo JPEG codec bileşeninin kullanımıyla büyük ölçüde hızlandırılan bir Sıkı kodlama çeşidini destekler.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC Viewer connection to a CentOS machine\"\nmsgstr \"TigerVNC Görüntüleyici, CentOS makinesine bağlantı\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC Viewer connection to a macOS machine\"\nmsgstr \"TigerVNC Görüntüleyici, macOS makinesine bağlantı\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC Viewer connection to a Windows machine\"\nmsgstr \"TigerVNC Görüntüleyici, Windows makinesine bağlantı\"\n\n#: vncviewer/parameters.cxx:308 vncviewer/parameters.cxx:333\n#: vncviewer/parameters.cxx:350 vncviewer/parameters.cxx:390\n#: vncviewer/parameters.cxx:410\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Parametrenin adı çok büyük\"\n\n#: vncviewer/parameters.cxx:312 vncviewer/parameters.cxx:317\n#: vncviewer/parameters.cxx:368\nmsgid \"The parameter is too large\"\nmsgstr \"Parametre çok büyük\"\n\n#: vncviewer/parameters.cxx:375 vncviewer/parameters.cxx:696\n#: vncviewer/parameters.cxx:818\nmsgid \"Invalid format or too large value\"\nmsgstr \"Geçersiz biçim veya çok büyük değer\"\n\n#: vncviewer/parameters.cxx:429 vncviewer/parameters.cxx:460\nmsgid \"Failed to create registry key\"\nmsgstr \"Kayıt defteri anahtarı oluşturulamadı\"\n\n#: vncviewer/parameters.cxx:448 vncviewer/parameters.cxx:503\n#: vncviewer/parameters.cxx:545 vncviewer/parameters.cxx:612\nmsgid \"Failed to close registry key\"\nmsgstr \"Kayıt defteri anahtarı kapatılamadı\"\n\n#: vncviewer/parameters.cxx:466 vncviewer/parameters.cxx:483\n#: vncviewer/parameters.cxx:654 vncviewer/parameters.cxx:664\n#: vncviewer/parameters.cxx:675\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"\\\"%s\\\" kaydedilemedi: %s\"\n\n#: vncviewer/parameters.cxx:479 vncviewer/parameters.cxx:567\n#: vncviewer/parameters.cxx:677 vncviewer/parameters.cxx:714\nmsgid \"Unknown parameter type\"\nmsgstr \"Bilinmeyen parametre türü\"\n\n#: vncviewer/parameters.cxx:496\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"\\\"%s\\\" kaldırılamadı: %s\"\n\n#: vncviewer/parameters.cxx:518 vncviewer/parameters.cxx:590\nmsgid \"Failed to open registry key\"\nmsgstr \"Kayıt defteri anahtarı açılamadı\"\n\n#: vncviewer/parameters.cxx:535\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"%d sunucu geçmişi girişi okunamadı: %s\"\n\n#: vncviewer/parameters.cxx:571 vncviewer/parameters.cxx:601\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"\\\"%s\\\" parametresi okunamadı: %s\"\n\n#: vncviewer/parameters.cxx:655 vncviewer/parameters.cxx:666\nmsgid \"Could not encode parameter\"\nmsgstr \"Parametre kodlanamadı\"\n\n#: vncviewer/parameters.cxx:783\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Yapılandırma dosyası %s geçersiz bir biçimde\"\n\n#: vncviewer/parameters.cxx:805\nmsgid \"Invalid format\"\nmsgstr \"Geçersiz biçim\"\n\n#: vncviewer/parameters.cxx:840\nmsgid \"Unknown parameter\"\nmsgstr \"Bilinmeyen parametre\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"İşlenmeyen bir pencereye ilişkin ileti (0x%x) alındı\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"İşaretçi yakalama için geçersiz pencere 0x%08lx belirtildi\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Dokunma işleyicisi oluşturulamadı: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Olay işleyicisi pencereye eklenemedi (hata 0x%x)\"\n\n#: vncviewer/touch.cxx:212\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"X Giriş etkinliği için etkinlik verileri alınamadı\"\n\n#: vncviewer/touch.cxx:225\nmsgid \"X Input event for unknown window\"\nmsgstr \"Bilinmeyen pencere için X Giriş olayı\"\n\n#: vncviewer/touch.cxx:251\nmsgid \"X Input extension not available.\"\nmsgstr \"X Giriş uzantısı mevcut değil.\"\n\n#: vncviewer/touch.cxx:258\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Giriş 2 (veya daha yenisi) mevcut değil.\"\n\n#: vncviewer/touch.cxx:263\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Giriş 2.2 (veya daha yenisi) mevcut değil. Dokunma hareketleri desteklenmeyecektir.\"\n\n#: vncviewer/vncviewer.cxx:107\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC Görüntüleyici v%s\\n\"\n\"Derlenme: %s\\n\"\n\"Telif Hakkı (C) 1999-%d TigerVNC Takımı ve diğer birçok kişi (bkz. README.rst)\\n\"\n\"TigerVNC hakkında bilgi için http://www.tigervnc.org adresine bakın.\"\n\n#: vncviewer/vncviewer.cxx:161\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Sunucuyla iletişim kurulurken beklenmeyen bir hata oluştu:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:177\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"TigerVNC Görüntüleyici Hakkında\"\n\n#: vncviewer/vncviewer.cxx:198\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Dahili FLTK hatası. Çıkışıyor.\"\n\n#: vncviewer/vncviewer.cxx:217\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Yeniden bağlanma denensin mi?\"\n\n#: vncviewer/vncviewer.cxx:248 vncviewer/vncviewer.cxx:260\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Yeni TigerVNC Görüntüleyici başlatılırken hata oluştu: %s\"\n\n#: vncviewer/vncviewer.cxx:269\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"Sonlandırma sinyali %d alındı. TigerVNC Görüntüleyici çıkacak.\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Yes\"\nmsgstr \"Evet\"\n\n#: vncviewer/vncviewer.cxx:418\nmsgid \"Close\"\nmsgstr \"Kapat\"\n\n#: vncviewer/vncviewer.cxx:423\nmsgid \"About\"\nmsgstr \"Hakkında\"\n\n#: vncviewer/vncviewer.cxx:426\nmsgid \"Hide\"\nmsgstr \"Gizle\"\n\n#: vncviewer/vncviewer.cxx:429\nmsgid \"Quit\"\nmsgstr \"Çık\"\n\n#: vncviewer/vncviewer.cxx:433\nmsgid \"Services\"\nmsgstr \"Hizmetler\"\n\n#: vncviewer/vncviewer.cxx:434\nmsgid \"Hide Others\"\nmsgstr \"Diğerlerini Gizle\"\n\n#: vncviewer/vncviewer.cxx:435\nmsgid \"Show All\"\nmsgstr \"Tümü Göster\"\n\n#: vncviewer/vncviewer.cxx:444\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Dosya\"\n\n#: vncviewer/vncviewer.cxx:447\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Yeni Bağlantı\"\n\n#: vncviewer/vncviewer.cxx:463\n#, c-format\nmsgid \"Could not create VNC home directory: %s\"\nmsgstr \"VNC ana dizini oluşturulamadı: %s\"\n\n#: vncviewer/vncviewer.cxx:562\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors artık eski, bunun yerine FullScreenMode seçeneğini 'all' yapın\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:768 vncviewer/vncviewer.cxx:769\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"-listen ve -via parametreleri uyumsuzdur\"\n\n#: vncviewer/vncviewer.cxx:783\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"%d bağlantı noktasında dinleniyor\"\n\n#: vncviewer/vncviewer.cxx:816\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Gelen VNC bağlantısını beklerken hata:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"Uzak Masaüstü Görüntüleyici\"\n"
  },
  {
    "path": "po/uk.po",
    "content": "# Ukrainian translation of tigervnc\n# Copyright (C) 2014 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n#\n# Yuri Chornoivan <yurchor@ukr.net>, 2014, 2015, 2016, 2017, 2018, 2019, 2021, 2022, 2024, 2025.\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.15.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-11-07 10:53+0100\\n\"\n\"PO-Revision-Date: 2025-11-13 14:45+0200\\n\"\n\"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\\n\"\n\"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\\n\"\n\"Language: uk\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\\n\"\n\"X-Generator: Lokalize 23.04.3\\n\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"З’єднано з сокетом %s\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"З’єднано з вузлом %s, порт %d\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не вдалося з'єднатися з «%s»:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Назва робочої станції: %.80s\"\n\n#: vncviewer/CConn.cxx:193\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Вузол: %.80s порт: %d\"\n\n#: vncviewer/CConn.cxx:197\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Розмір: %d x %d\"\n\n#: vncviewer/CConn.cxx:204\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Формат у пікселях: %s\"\n\n#: vncviewer/CConn.cxx:207\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Запит щодо кодування: %s\"\n\n#: vncviewer/CConn.cxx:211\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Останнє використане кодування: %s\"\n\n#: vncviewer/CConn.cxx:215\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Оцінка швидкості лінії: %d кбіт/с\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Версія протоколу: %d.%d\"\n\n#: vncviewer/CConn.cxx:223\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Метод захисту: %s\"\n\n#: vncviewer/CConn.cxx:284 vncviewer/CConn.cxx:286\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"З'єднання було розірвано сервером до того, як виникла можливість розпочати сеанс.\"\n\n#: vncviewer/CConn.cxx:296\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"Розпізнавання не пройдено: %s\"\n\n#: vncviewer/CConn.cxx:297\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не вдалося пройти розпізнавання на сервері. Причина, яку вказано сервером:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:526\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Пропускна здатність %d кбіт/с — змінюємо якість на %d\"\n\n#: vncviewer/CConn.cxx:557\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"Пропускна здатність %d кбіт/с — увімкнено повноцінні кольори\"\n\n#: vncviewer/CConn.cxx:560\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"Пропускна здатність %d кбіт/с — вимкнено повноцінні кольори\"\n\n#: vncviewer/CConn.cxx:579\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Використовуємо формат у пікселях %s\"\n\n#: vncviewer/DesktopWindow.cxx:152\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Вказано некоректні геометричні параметри!\"\n\n#: vncviewer/DesktopWindow.cxx:173\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"Зменшуємо розмір вікна, щоб умістити його на поточному моніторі\"\n\n#: vncviewer/DesktopWindow.cxx:244\n#, c-format\nmsgid \"Press %sM to open the context menu\"\nmsgstr \"Натисніть %sM, щоб відкрити контекстне меню\"\n\n#: vncviewer/DesktopWindow.cxx:312\n#, c-format\nmsgid \"%s - TigerVNC (keyboard grabbed)\"\nmsgstr \"%s - TigerVNC (клавіатуру перехоплено)\"\n\n#: vncviewer/DesktopWindow.cxx:314\n#, c-format\nmsgid \"%s - TigerVNC\"\nmsgstr \"%s - TigerVNC\"\n\n#: vncviewer/DesktopWindow.cxx:705\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"Коригувати розміри вікна, щоб уникнути випадкового запиту щодо переходу у повноекранний режим\"\n\n#: vncviewer/DesktopWindow.cxx:915\n#, c-format\nmsgid \"Press %sEnter to leave full-screen mode\"\nmsgstr \"Натисніть %sEnter, щоб вийти з повноекранного режиму\"\n\n#: vncviewer/DesktopWindow.cxx:1204 vncviewer/DesktopWindow.cxx:1205\n#: vncviewer/DesktopWindow.cxx:1213 vncviewer/DesktopWindow.cxx:1214\n#: vncviewer/DesktopWindow.cxx:1239 vncviewer/DesktopWindow.cxx:1240\nmsgid \"Failure grabbing control of the keyboard\"\nmsgstr \"Не вдалося перехопити керування клавіатурою\"\n\n#: vncviewer/DesktopWindow.cxx:1258\n#, c-format\nmsgid \"Press %s to release keyboard control from the session\"\nmsgstr \"Натисніть %s, щоб зняти керування клавіатурою з боку сеансу\"\n\n#: vncviewer/DesktopWindow.cxx:1525\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Результати обчислення компонування вікна для запиту щодо зміни розмірів є некоректними!\"\n\n#: vncviewer/EmulateMB.cxx:227 vncviewer/EmulateMB.cxx:290\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"Некоректний стан для емуляції 3 кнопок\"\n\n#: vncviewer/KeyboardWin32.cxx:248\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Немає коду сканування для віртуальної клавіші розширення 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Немає коду сканування для віртуальної клавіші 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:256\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Некоректний код сканування 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:284\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Немає символу для віртуальної клавіші розширення 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:286\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Немає символу для віртуальної клавіші 0x%02x\"\n\n#: vncviewer/KeyboardWin32.cxx:553\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Не вдалося оновити стан лампочки клавіатури: %lu\"\n\n#: vncviewer/KeyboardX11.cxx:167\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Немає символу для клавіші з кодом %d (у поточному стані)\"\n\n#: vncviewer/KeyboardX11.cxx:218\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Не вдалося отримати стан лампочки клавіатури: %d\"\n\n#: vncviewer/KeyboardX11.cxx:263\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Не вдалося оновити стан лампочки клавіатури\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:53\n#: vncviewer/MonitorIndicesParameter.cxx:85\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"Не вдалося отримати налаштування монітора з боку системи\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:73\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"Монітора із індексом %d не існує\"\n\n#: vncviewer/OptionsDialog.cxx:70\nmsgid \"TigerVNC options\"\nmsgstr \"Параметри TigerVNC\"\n\n#: vncviewer/OptionsDialog.cxx:104 vncviewer/ServerDialog.cxx:110\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"Скасувати\"\n\n#: vncviewer/OptionsDialog.cxx:109 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"Гаразд\"\n\n#: vncviewer/OptionsDialog.cxx:532\nmsgid \"Compression\"\nmsgstr \"Стискання\"\n\n#: vncviewer/OptionsDialog.cxx:549\nmsgid \"Auto select\"\nmsgstr \"Автовибір\"\n\n#: vncviewer/OptionsDialog.cxx:556\nmsgid \"Allow JPEG compression\"\nmsgstr \"Дозволити стискання JPEG\"\n\n#: vncviewer/OptionsDialog.cxx:566\nmsgid \"Preferred encoding\"\nmsgstr \"Бажане кодування\"\n\n#: vncviewer/OptionsDialog.cxx:634\nmsgid \"Color level\"\nmsgstr \"Рівень відтворення кольору\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Full\"\nmsgstr \"Повний\"\n\n#: vncviewer/OptionsDialog.cxx:653\nmsgid \"Medium\"\nmsgstr \"Середній\"\n\n#: vncviewer/OptionsDialog.cxx:660\nmsgid \"Low\"\nmsgstr \"Низький\"\n\n#: vncviewer/OptionsDialog.cxx:667\nmsgid \"Very low\"\nmsgstr \"Дуже низький\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Custom compression level\"\nmsgstr \"Нетиповий рівень стискання\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"рівень (0=швидко, 9=найкраще)\"\n\n#: vncviewer/OptionsDialog.cxx:721\nmsgid \"Quality level\"\nmsgstr \"Рівень якості\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"якість (0=найгірша, 9=найкраща)\"\n\n#: vncviewer/OptionsDialog.cxx:756\nmsgid \"Security\"\nmsgstr \"Захист\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Encryption\"\nmsgstr \"Шифрування\"\n\n#: vncviewer/OptionsDialog.cxx:782 vncviewer/OptionsDialog.cxx:849\nmsgid \"None\"\nmsgstr \"Немає\"\n\n#: vncviewer/OptionsDialog.cxx:789\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS із анонімними сертифікатами\"\n\n#: vncviewer/OptionsDialog.cxx:795\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS з сертифікатами X509\"\n\n#: vncviewer/OptionsDialog.cxx:802\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Шлях до сертифіката CA X509\"\n\n#: vncviewer/OptionsDialog.cxx:809\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Шлях до файла CRL X509\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Authentication\"\nmsgstr \"Розпізнавання\"\n\n#: vncviewer/OptionsDialog.cxx:855\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"Стандартний VNC (без захисту і шифрування)\"\n\n#: vncviewer/OptionsDialog.cxx:861\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Ім’я користувача і пароль (без захисту і шифрування)\"\n\n#: vncviewer/OptionsDialog.cxx:889\nmsgid \"Input\"\nmsgstr \"Введення\"\n\n#: vncviewer/OptionsDialog.cxx:902\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Лише перегляд (ігнорувати сигнали від миші і клавіатури)\"\n\n#: vncviewer/OptionsDialog.cxx:909\nmsgid \"Mouse\"\nmsgstr \"Миша\"\n\n#: vncviewer/OptionsDialog.cxx:921\nmsgid \"Emulate middle mouse button\"\nmsgstr \"Емулювати середню кнопку миші\"\n\n#: vncviewer/OptionsDialog.cxx:927\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"Показувати локальний курсор, якщо його не надано сервером\"\n\n#: vncviewer/OptionsDialog.cxx:932\nmsgid \"Cursor type\"\nmsgstr \"Тип курсора\"\n\n#: vncviewer/OptionsDialog.cxx:934\nmsgid \"Dot\"\nmsgstr \"Крапка\"\n\n#: vncviewer/OptionsDialog.cxx:935\nmsgid \"System\"\nmsgstr \"Системний\"\n\n#: vncviewer/OptionsDialog.cxx:955\nmsgid \"Keyboard\"\nmsgstr \"Клавіатура\"\n\n#: vncviewer/OptionsDialog.cxx:966\nmsgid \"Always send all keyboard input in full screen\"\nmsgstr \"Завжди надсилати усіх вхідні дані з клавіатури у повноекранному режимі\"\n\n#: vncviewer/OptionsDialog.cxx:983\nmsgid \"Clipboard\"\nmsgstr \"Буфер обміну\"\n\n#: vncviewer/OptionsDialog.cxx:995\nmsgid \"Accept clipboard from server\"\nmsgstr \"Приймати вміст буфера з сервера\"\n\n#: vncviewer/OptionsDialog.cxx:1003\nmsgid \"Also set primary selection\"\nmsgstr \"Також встановити основне позначене\"\n\n#: vncviewer/OptionsDialog.cxx:1010\nmsgid \"Send clipboard to server\"\nmsgstr \"Надіслати вміст буфера обміну до сервера\"\n\n#: vncviewer/OptionsDialog.cxx:1018\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Надіслати основне позначене як буфер обміну\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Keyboard shortcuts\"\nmsgstr \"Клавіатурні скорочення\"\n\n#: vncviewer/OptionsDialog.cxx:1046\nmsgid \"Modifier keys for keyboard shortcuts:\"\nmsgstr \"Клавіші-модифікатори для скорочень:\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1059 vncviewer/ShortcutHandler.cxx:209\nmsgid \"Ctrl\"\nmsgstr \"Ctrl\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1067 vncviewer/ShortcutHandler.cxx:217\nmsgid \"Shift\"\nmsgstr \"Shift\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1075 vncviewer/ShortcutHandler.cxx:225\nmsgid \"Alt\"\nmsgstr \"Alt\"\n\n#. TRANSLATORS: This refers to the\n#. keyboard key\n#. *\n#: vncviewer/OptionsDialog.cxx:1083 vncviewer/ShortcutHandler.cxx:233\nmsgid \"Win\"\nmsgstr \"Win\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1089\nmsgid \"⌃ Ctrl\"\nmsgstr \"⌃ Ctrl\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1091\nmsgid \"⇧ Shift\"\nmsgstr \"⇧ Shift\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1093\nmsgid \"⌥ Option\"\nmsgstr \"⌥ Option\"\n\n#. TRANSLATORS: This refers to the keyboard key\n#: vncviewer/OptionsDialog.cxx:1095\nmsgid \"⌘ Cmd\"\nmsgstr \"⌘ Cmd\"\n\n#: vncviewer/OptionsDialog.cxx:1109\nmsgid \"Display\"\nmsgstr \"Дисплей\"\n\n#: vncviewer/OptionsDialog.cxx:1123\nmsgid \"Display mode\"\nmsgstr \"Режим показу\"\n\n#: vncviewer/OptionsDialog.cxx:1136\nmsgid \"Windowed\"\nmsgstr \"У вікні\"\n\n#: vncviewer/OptionsDialog.cxx:1144\nmsgid \"Full screen on current monitor\"\nmsgstr \"Повноекранний режим на поточному моніторі\"\n\n#: vncviewer/OptionsDialog.cxx:1152\nmsgid \"Full screen on all monitors\"\nmsgstr \"Повноекранний режимі на усіх моніторах\"\n\n#: vncviewer/OptionsDialog.cxx:1160\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"Повноекранний режим на позначених моніторах\"\n\n#: vncviewer/OptionsDialog.cxx:1189\nmsgid \"Miscellaneous\"\nmsgstr \"Інше\"\n\n#: vncviewer/OptionsDialog.cxx:1197\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Спільний (не від’єднувати інші засоби перегляду)\"\n\n#: vncviewer/OptionsDialog.cxx:1203\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"Питати про повторне з'єднання при помилка з'єднання\"\n\n#: vncviewer/OptionsDialog.cxx:1310\nmsgid \"All keyboard shortcuts are disabled.\"\nmsgstr \"Усі клавіатурні скорочення вимкнено.\"\n\n#: vncviewer/OptionsDialog.cxx:1321\n#, c-format\nmsgid \"To release keyboard control from the session, press %s.\"\nmsgstr \"Щоб зняти керування клавіатурою з сеансу, натисніть %s.\"\n\n#: vncviewer/OptionsDialog.cxx:1326\n#, c-format\nmsgid \"To pass all keyboard input to the session, press %sG.\"\nmsgstr \"Щоб передавати усі вхідні дані з клавіатури до сеансу, натисніть %sG.\"\n\n#: vncviewer/OptionsDialog.cxx:1331\n#, c-format\nmsgid \"To toggle full-screen mode, press %sEnter.\"\nmsgstr \"Щоб увімкнути або вимкнути повноекранний режим, натисніть %sEnter.\"\n\n#: vncviewer/OptionsDialog.cxx:1335\n#, c-format\nmsgid \"To open the session context menu, press %sM.\"\nmsgstr \"Щоб відкрити контекстне меню сеансу, натисніть %sM.\"\n\n#: vncviewer/OptionsDialog.cxx:1339\n#, c-format\nmsgid \"To send a key combination that includes %s directly to the session, press %sSpace, release the space bar without releasing %s, and press the desired key.\"\nmsgstr \"Щоб надіслати комбінацію клавіш, яка містить %s, безпосередньо до сеансу, натисніть %sПробіл, відпустіть клавішу пробілу, не відпускаючи %s, і натисніть бажану клавішу.\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"VNC server:\"\nmsgstr \"Сервер VNC:\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Options...\"\nmsgstr \"Параметри…\"\n\n#: vncviewer/ServerDialog.cxx:87\nmsgid \"Load...\"\nmsgstr \"Завантажити…\"\n\n#: vncviewer/ServerDialog.cxx:91\nmsgid \"Save as...\"\nmsgstr \"Зберегти як…\"\n\n#: vncviewer/ServerDialog.cxx:105\nmsgid \"About...\"\nmsgstr \"Про програму…\"\n\n#: vncviewer/ServerDialog.cxx:114\nmsgid \"Connect\"\nmsgstr \"З'єднатися\"\n\n#: vncviewer/ServerDialog.cxx:146\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не вдалося завантажити журнал сервера:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:175 vncviewer/ServerDialog.cxx:215\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"налаштування TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:176\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Виберіть файл налаштувань TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не вдалося завантажити вказаний файл налаштувань:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:216\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Зберегти налаштування TigerVNC до файла\"\n\n#: vncviewer/ServerDialog.cxx:242\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s вже існує. Перезаписати?\"\n\n#: vncviewer/ServerDialog.cxx:243 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"Ні\"\n\n#: vncviewer/ServerDialog.cxx:243\nmsgid \"Overwrite\"\nmsgstr \"Перезаписати\"\n\n#: vncviewer/ServerDialog.cxx:259\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не вдалося зберегти вказаний файл налаштувань:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:293\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не вдалося зберегти типові налаштування:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:305\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не вдалося зберегти журнал сервера:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:433\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"Не вдалося визначити каталог стану VNC\"\n\n#: vncviewer/ServerDialog.cxx:364 vncviewer/ServerDialog.cxx:441\n#: vncviewer/parameters.cxx:758 vncviewer/parameters.cxx:838\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"Не вдалося відкрити «%s»\"\n\n#: vncviewer/ServerDialog.cxx:379 vncviewer/ServerDialog.cxx:388\n#: vncviewer/parameters.cxx:852 vncviewer/parameters.cxx:859\n#: vncviewer/parameters.cxx:893 vncviewer/parameters.cxx:929\n#: vncviewer/parameters.cxx:937\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"Не вдалося прочитати рядок %d у файлі «%s»\"\n\n#: vncviewer/ServerDialog.cxx:392 vncviewer/parameters.cxx:863\nmsgid \"Line too long\"\nmsgstr \"Занадто довгий рядок\"\n\n#: vncviewer/UserDialog.cxx:130\nmsgid \"Opening password file failed\"\nmsgstr \"Спроба відкриття файла паролів зазнала невдачі\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"VNC authentication\"\nmsgstr \"Розпізнавання VNC\"\n\n#: vncviewer/UserDialog.cxx:157\nmsgid \"This connection is secure\"\nmsgstr \"Це з'єднання є безпечним\"\n\n#: vncviewer/UserDialog.cxx:161\nmsgid \"This connection is not secure\"\nmsgstr \"Це з'єднання не є безпечним\"\n\n#: vncviewer/UserDialog.cxx:183\nmsgid \"Username:\"\nmsgstr \"Користувач:\"\n\n#: vncviewer/UserDialog.cxx:196\nmsgid \"Password:\"\nmsgstr \"Пароль:\"\n\n#: vncviewer/UserDialog.cxx:204\nmsgid \"Keep password for reconnect\"\nmsgstr \"Зберігати пароль для повторного з'єднання\"\n\n#: vncviewer/Viewport.cxx:767 vncviewer/Viewport.cxx:846\n#: vncviewer/vncviewer.cxx:157\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Під час обміну даними з сервером сталася неочікувана помилка:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/Viewport.cxx:905\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"Від'єд&натися\"\n\n#: vncviewer/Viewport.cxx:908\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"&На весь екран\"\n\n#: vncviewer/Viewport.cxx:911\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"М&інімізувати\"\n\n#: vncviewer/Viewport.cxx:913\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Змінити &розміри вікна відповідно до сеансу\"\n\n#: vncviewer/Viewport.cxx:918\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:921\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:925\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"На&діслати Ctrl-Alt-Del\"\n\n#: vncviewer/Viewport.cxx:928\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&Оновити вміст екрана\"\n\n#: vncviewer/Viewport.cxx:931\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"П&араметри…\"\n\n#: vncviewer/Viewport.cxx:933\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Дані щодо з’&єднання…\"\n\n#: vncviewer/Viewport.cxx:935\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC...\"\nmsgstr \"Про &TigerVNC…\"\n\n#: vncviewer/Viewport.cxx:1027\nmsgid \"VNC connection info\"\nmsgstr \"Дані щодо з’єднання VNC\"\n\n#: vncviewer/Win32TouchHandler.cxx:46\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"Вікно зареєстровано для сенсорних дій, а не для жестів\"\n\n#: vncviewer/Win32TouchHandler.cxx:81\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"Не вдалося встановити налаштування жестів (помилка 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:93\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"Не вдалося отримати відомості щодо жестів (помилка 0x%x)\"\n\n#: vncviewer/Win32TouchHandler.cxx:361\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"Некоректна кнопка миші, %d, номер кнопки має бути числом від 1 до 7.\"\n\n#: vncviewer/Win32TouchHandler.cxx:426\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"Непридатна до обробки клавіша 0x%x — не вдалося створити подію клавіатури.\"\n\n#: vncviewer/XInputTouchHandler.cxx:103 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"Не вдалося отримати маску події X Input 2 для вікна 0x%08lx\"\n\n#: vncviewer/XInputTouchHandler.cxx:105\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"У вікна 0x%08lx немає маски подій X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:113 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"У вікна 0x%08lx є декілька масок подій X Input 2\"\n\n#: vncviewer/XInputTouchHandler.cxx:144\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"Помилка під час спроби захопити пристрій %i\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.desktop.in.in:2\nmsgid \"TigerVNC\"\nmsgstr \"TigerVNC\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"З'єднання із сервером VNC і показ віддаленої стільниці\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Віртуальна мережева взаємодія комп'ютерів (Virtual Network Computing або VNC) є системою віддаленої стільниці, за допомогою якої ви можете переглядати та взаємодіяти із віртуальним стільничним середовищем, яке запущено на іншому комп'ютері у мережі. За допомогою VNC ви можете запускати програми із графічним інтерфейсом на віддаленому комп'ютері і отримувати лише зображення з цих програм на вашому локальному пристрої. У цьому пакунку міститься клієнтська частина, за допомогою якої ви можете з'єднуватися з іншими стільничними середовищами, де запущено сервер VNC. Протокол VNC є незалежним від платформи, у ньому передбачено підтримку різних операційних систем та апаратних архітектур, як на сервері, так і на клієнті.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC — високошвидкісна версія VNC на основі програмного коду RealVNC 4 та X.org. Роботу над TigerVNC було розпочато у межах побудови наступного покоління для TightVNC на платформах Unix та Linux, але програма відокремилася від батьківського проєкту на початку 2009 року, коли проєкт TightVNC зосередився на платформах Windows. У TigerVNC передбачено підтримку варіанта кодування Tight, який значно пришвидшено використанням кодека JPEG libjpeg-turbo.\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC connection to a CentOS machine\"\nmsgstr \"З'єднання TigerVNC зі комп'ютером, де працює CentOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC connection to a macOS machine\"\nmsgstr \"З'єднання TigerVNC із комп'ютером, де працює macOS\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC connection to a Windows machine\"\nmsgstr \"З'єднання TigerVNC із комп'ютером, де працює Windows\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"Команда TigerVNC\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:411\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:468\n#: vncviewer/parameters.cxx:488\nmsgid \"The name of the parameter is too large\"\nmsgstr \"Назва параметра є надто довгою\"\n\n#: vncviewer/parameters.cxx:390 vncviewer/parameters.cxx:395\n#: vncviewer/parameters.cxx:446\nmsgid \"The parameter is too large\"\nmsgstr \"Параметр є надто великим\"\n\n#: vncviewer/parameters.cxx:453 vncviewer/parameters.cxx:797\n#: vncviewer/parameters.cxx:909\nmsgid \"Invalid format or too large value\"\nmsgstr \"Некоректне форматування або надто велике значення\"\n\n#: vncviewer/parameters.cxx:508 vncviewer/parameters.cxx:541\nmsgid \"Failed to create registry key\"\nmsgstr \"Не вдалося створити ключ реєстру\"\n\n#: vncviewer/parameters.cxx:529 vncviewer/parameters.cxx:602\n#: vncviewer/parameters.cxx:646 vncviewer/parameters.cxx:724\nmsgid \"Failed to close registry key\"\nmsgstr \"Не вдалося закрити ключ реєстру\"\n\n#: vncviewer/parameters.cxx:548 vncviewer/parameters.cxx:581\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:778\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"Не вдалося зберегти «%s»: %s\"\n\n#: vncviewer/parameters.cxx:561 vncviewer/parameters.cxx:595\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"Не вдалося вилучити «%s»: %s\"\n\n#: vncviewer/parameters.cxx:619 vncviewer/parameters.cxx:697\nmsgid \"Failed to open registry key\"\nmsgstr \"Не вдалося відкрити ключ реєстру\"\n\n#: vncviewer/parameters.cxx:636\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"Не вдалося прочитати запис журналу сервера %d: %s\"\n\n#: vncviewer/parameters.cxx:678 vncviewer/parameters.cxx:708\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"Не вдалося прочитати параметр «%s»: %s\"\n\n#: vncviewer/parameters.cxx:747 vncviewer/parameters.cxx:825\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"Не вдалося визначити шлях до каталогу налаштувань VNC\"\n\n#: vncviewer/parameters.cxx:767 vncviewer/parameters.cxx:779\nmsgid \"Could not encode parameter\"\nmsgstr \"Не вдалося закодувати параметр\"\n\n#: vncviewer/parameters.cxx:873\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Файл налаштувань %s збережено у некоректному форматі\"\n\n#: vncviewer/parameters.cxx:896\nmsgid \"Invalid format\"\nmsgstr \"Некоректне форматування\"\n\n#: vncviewer/parameters.cxx:940\nmsgid \"Unknown parameter\"\nmsgstr \"Невідомий параметр\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"Отримано повідомлення (0x%x) для вікна, обробка якого не здійснюється\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"Для захоплення вказівника вказано некоректне вікно 0x%08lx\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"Не вдалося створити обробник сенсорних даних: %s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"Не вдалося долучити обробник подій до вікна (помилка 0x%x)\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"Не вдалося отримати дані події для події X Input\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"Подія X Input для невідомого вікна\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"Розширення X Input є недоступним.\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"Немає доступу до X Input 2 (або новішої версії).\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"Немає доступу до X Input 2.2 (або новішої версії). Ви не зможете скористатися підтримкою сенсорних жестів.\"\n\n#: vncviewer/vncviewer.cxx:103\n#, c-format\nmsgid \"\"\n\"TigerVNC v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC, v%s\\n\"\n\"Зібрано: %s\\n\"\n\"Авторські права належать команді TigerVNC та багатьом іншим (див. файл README.rst), 1999–%d\\n\"\n\"Докладніший опис TigerVNC можна знайти на https://www.tigervnc.org.\"\n\n#: vncviewer/vncviewer.cxx:173\nmsgid \"About TigerVNC\"\nmsgstr \"Про TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Внутрішня помилка FLTK. Завершуємо роботу.\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"Спробувати встановити з'єднання ще раз?\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new connection: %s\"\nmsgstr \"Не вдалося встановити нове з'єднання: %s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC will now exit.\"\nmsgstr \"Отримано сигнал переривання %d. Зараз TigerVNC завершить роботу.\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"Так\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"Закрити\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"Про програму\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"Сховати\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"Вийти\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"Служби\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"Сховати решту\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"Показати всі\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Файл\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"&Створити з'єднання\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Користування: %s [параметри] [вузол][:номерДисплея]\\n\"\n\"       %s [параметри] [вузол][::порт]\\n\"\n\"       %s [параметри] [сокет unix]\\n\"\n\"       %s [параметри] -listen [порт]\\n\"\n\"       %s [параметри] [файл .tigervnc]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main TigerVNC window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Параметри:\\n\"\n\"\\n\"\n\"  -display дисплейX  - визначити дисплей X для показу вікна переглядача\\n\"\n\"  -geometry геометрія - початкова позиція головного вікна TigerVNC.\\n\"\n\"                       Див. сторінку man, щоб дізнатися більше.\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"Параметри можна увімкнути за допомогою -<парам> або вимкнути за допомогою -<парам>=0\\n\"\n\"Параметри, які приймають значення можна вказати у формі -<парам> <значення>\\n\"\n\"Інші коректні форми — <парам>=<значення> -<парам>=<значення> --<парам>=<значення>\\n\"\n\"Назви параметрів слід вказувати з врахуванням регістру символів. Параметри:\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors вважається застарілим, замість нього слід встановити для FullScreenMode значення «all»\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor з застарілим, натомість встановіть для AlwaysCursor значення 1, а для CursorType значення 'Dot'\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc вважається застарілим, будь ласка, ознайомтеся із «man vncviewer», щоб дізнатися більше про перенесення даних.\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc вважається застарілим, будь ласка, переходьте на %%APPDATA%%\\\\TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"Не вдалося створити каталог налаштувань VNC «%s»: %s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"Не вдалося визначити шлях до каталогу даних VNC\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"Не вдалося створити каталог даних VNC «%s»: %s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"Не вдалося створити каталог стану VNC «%s»: %s\"\n\n#: vncviewer/vncviewer.cxx:705\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s: невідомий параметр «%s»\\n\"\n\n#: vncviewer/vncviewer.cxx:707 vncviewer/vncviewer.cxx:715\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"Див. «%s --help», щоб дізнатися більше.\\n\"\n\n#: vncviewer/vncviewer.cxx:714\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s: зайвий аргумент «%s»\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:750 vncviewer/vncviewer.cxx:751\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Параметри -listen і -via є несумісними\"\n\n#: vncviewer/vncviewer.cxx:765\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"Не вдалося виконати стеження за вхідними з'єднаннями\"\n\n#: vncviewer/vncviewer.cxx:767\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Очікуємо на дані на порту %d\"\n\n#: vncviewer/vncviewer.cxx:796\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Помилка під час очікування на вхідне з'єднання VNC:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:817\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"Не вдалося налаштувати зашифрований тунель:\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:3\nmsgid \"Remote desktop viewer\"\nmsgstr \"Засіб перегляду віддаленої стільниці\"\n\n#, c-format\n#~ msgid \"(server default %s)\"\n#~ msgstr \"(типовий для сервера %s)\"\n\n#, c-format\n#~ msgid \"SetDesktopSize failed: %d\"\n#~ msgstr \"Помилка SetDesktopSize: %d\"\n\n#~ msgid \"Invalid SetColourMapEntries from server!\"\n#~ msgstr \"Некоректне значення SetColourMapEntries від сервера!\"\n\n#, c-format\n#~ msgid \"Invalid configuration specified for %s\"\n#~ msgstr \"Вказано некоректні налаштування для %s\"\n\n#, c-format\n#~ msgid \"Invalid monitor index '%s'\"\n#~ msgstr \"Некоректний індекс монітора, «%s»\"\n\n#, c-format\n#~ msgid \"Unexpected character '%c'\"\n#~ msgstr \"Неочікуваний символ «%c»\"\n\n#~ msgid \"Pass system keys directly to server (full screen)\"\n#~ msgstr \"Передавати натискання системних клавіш безпосередньо до сервера (повноекранний режим)\"\n\n#~ msgid \"Menu key\"\n#~ msgstr \"Клавіша меню\"\n\n#~ msgid \"VNC viewer: Connection details\"\n#~ msgstr \"Засіб перегляду VNC: подробиці з’єднання\"\n\n#, c-format\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Send %s\"\n#~ msgstr \"Надіслати %s\"\n\n#~ msgid \"TigerVNC viewer\"\n#~ msgstr \"Засіб перегляду TigerVNC\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"Показувати крапку, якщо немає курсора\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"Не вдалося оновити стан лампочки клавіатури: %d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"Не вказано коду клавіші при натисканні\"\n\n#, c-format\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"Немає символу для клавіші з кодом 0x%02x (у поточному стані)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"Невідомий тип параметра\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"Засіб перегляду VNC: параметри з’єднання\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"Інше\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"Не вдалося отримати назву монітора, оскільки не вдалося знайти RandR X11\"\n\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"Не вдалося отримати відомості щодо CRTC %d\"\n\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"Не вдалося отримати відомості щодо виведення %d для CRTC %d\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"Екран\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"Змінювати розміри віддаленого сеансу під час з’єднання\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"Змінювати розміри віддаленого сеансу відповідно до локального вікна\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"Увімкнути повноекранний режим\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"Повністю (усі доступні кольори)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"Середній (256 кольори)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"Низький (64 кольори)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"Дуже низький (8 кольорів)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"рівень (1=швидко, 6=найякісніше [4-6 використовувати не варто])\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"Повноекранний режим\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"Ви&йти із засобу перегляду\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"Закрити &меню\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"Не вдалося записати параметр %s типу %s до реєстру: %ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"Назва параметра %s є надто довгою для читання з реєстру\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"Параметр %s є надто довгим для читання з реєстру\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"Не вдалося записати файл налаштувань, оскільки не вдалося визначити шлях до домашнього каталогу.\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"Не вдалося записати файл налаштувань, оскільки не вдалося відкрити %s: %s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"Не вдалося прочитати файл налаштувань, оскільки не вдалося визначити шлях до домашнього каталогу.\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"Невідомий параметр %s у рядку %d файла %s\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"Не вдалося створити домашній каталог VNC: не вдалося отримати шлях до домашнього каталогу.\"\n\n#~ msgid \"tigervnc\"\n#~ msgstr \"tigervnc\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"Увімкнути неперервне оновлення\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"вимкнено\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"увімкнено\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"Використовуємо кодування %s\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"Недостатньо пам’яті для буфера кадрів\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"Не вдалося створити пристрій буфера кадрів\"\n\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"Не вдалося створити растрові дані буфера кадрів\"\n\n#~ msgid \"Unable to create platform specific framebuffer: %s\"\n#~ msgstr \"Не вдалося створити специфічний для платформи буфер кадрів: %s\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"Використовуємо незалежний від платформи буфер кадрів\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"не вдалося створити розділ DIB\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"Помилка CreateCompatibleDC\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"Помилка SelectObject\"\n\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"Помилка BitBlt\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"Для дисплея не вказано формат у пікселях для типової глибини\"\n\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"Не вдалося визначити відповідний формат зображення\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"Передбачено підтримку лише дисплеїв з True Color\"\n\n#~ msgid \"Using default colormap and visual, TrueColor, depth %d.\"\n#~ msgstr \"Використовуємо типову карту кольорів і відтворення, TrueColor, глибина %d.\"\n\n#~ msgid \"Unknown encoding %d\"\n#~ msgstr \"Невідоме кодування %d\"\n\n#~ msgid \"Unknown encoding\"\n#~ msgstr \"Невідоме кодування\"\n\n#~ msgid \"Bad Name/Value pair on line: %d in file: %s\"\n#~ msgstr \"Помилкова пара назва/значення у рядку %d файла %s\"\n\n#~ msgid \"CleanupSignalHandler called\"\n#~ msgstr \"Викликано CleanupSignalHandler\"\n\n#~ msgid \"Could not convert the parameter-name %s to wchar_t* when reading from the Registry, the buffersize is to small.\"\n#~ msgstr \"Не вдалося перетворити назву параметра %s на wchar_t* під час читання даних з реєстру. Розмір буфера є надто малим.\"\n\n#~ msgid \"Could not convert the parameter-name %s to wchar_t* when writing to the Registry, the buffersize is to small.\"\n#~ msgstr \"Не вдалося перетворити назву параметра %s на wchar_t* під час запису даних до реєстру. Розмір буфера є надто малим.\"\n\n#~ msgid \"Could not convert the parameter-value %s to wchar_t* when writing to the Registry, the buffersize is to small.\"\n#~ msgstr \"Не вдалося перетворити значення параметра %s на wchar_t* під час запису даних до реєстру. Розмір буфера є надто малим.\"\n\n#~ msgid \"Could not convert the parameter-value for %s to utf8 char* when reading from the Registry, the buffer dest is to small.\"\n#~ msgstr \"Не вдалося перетворити значення параметра %s на utf8 char* під час читання з реєстру. Буфер призначення є надто малим.\"\n\n#~ msgid \"Could not read the line(%d) in the configuration file,the buffersize is to small.\"\n#~ msgstr \"Не вдалося прочитати рядок %d у файлі налаштувань. Розмір буфера є надто малим.\"\n\n#~ msgid \"Decoding: The size of the buffer dest is to small, it needs to be 1 byte bigger.\"\n#~ msgstr \"Декодування: розмір буфера призначення є надто малим. Його слід збільшити на 1 байт.\"\n\n#~ msgid \"Encoding backslash: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Кодування зворотної похилої риски: розмір буфера призначення є надто малим. Його слід збільшити на понад %d байтів.\"\n\n#~ msgid \"Encoding escape sequence: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Кодування екранованої послідовності: розмір буфера призначення є надто малим. Його слід збільшити на понад %d байтів.\"\n\n#~ msgid \"Encoding normal character: The size of the buffer dest is to small, it needs to be more than %d bytes bigger.\"\n#~ msgstr \"Кодування звичайного символу: розмір буфера призначення є надто малим. Його слід збільшити на понад %d байтів.\"\n\n#~ msgid \"Error(%d) closing key:  Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Помилка (%d) закриття ключа:  Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) closing key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Помилка (%d) закриття ключа: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) creating key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Помилка (%d) під час створення ключа: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) opening key: Software\\\\TigerVNC\\\\vncviewer\"\n#~ msgstr \"Помилка (%d) під час відкриття ключа: Software\\\\TigerVNC\\\\vncviewer\"\n\n#~ msgid \"Error(%d) reading %s from Registry.\"\n#~ msgstr \"Помилка (%d) під час читання %s з реєстру.\"\n\n#~ msgid \"Error(%d) writing %d(REG_DWORD) to Registry.\"\n#~ msgstr \"Помилка (%d) під час запису %d(REG_DWORD) до реєстру.\"\n\n#~ msgid \"Error(%d) writing %s(REG_SZ) to Registry.\"\n#~ msgstr \"Помилка (%d) під час запису %s(REG_SZ) до реєстру.\"\n\n#~ msgid \"\"\n#~ \"Line 1 in file %s\\n\"\n#~ \"must contain the TigerVNC configuration file identifier string:\\n\"\n#~ \"\\\"%s\\\"\"\n#~ msgstr \"\"\n#~ \"Рядок 1 у файлі %s\\n\"\n#~ \"має містити рядок ідентифікатор файла налаштувань TigerVNC:\\n\"\n#~ \"«%s»\"\n\n#~ msgid \"Multiple characters given for key code %d (0x%04x): '%s'\"\n#~ msgstr \"З клавішею з кодом %d (0x%04x) пов’язано декілька символів: «%s»\"\n\n#~ msgid \"The parameterArray contains a object of a invalid type at line %d.\"\n#~ msgstr \"Змінна parameterArray містить об’єкт некоректного типу у рядку %d.\"\n\n#~ msgid \"The value of the parameter %s on line %d in file %s is invalid.\"\n#~ msgstr \"Значення параметра %s у рядку %d файла %s є некоректним.\"\n\n#~ msgid \"Unknown FLTK key code %d (0x%04x)\"\n#~ msgstr \"Невідомий код клавіші FLTK, %d (0x%04x)\"\n\n#~ msgid \"Unknown decimal separator: '%s'\"\n#~ msgstr \"Невідомий десятковий роздільник: «%s»\"\n\n#~ msgid \"Unknown escape sequence at character %d\"\n#~ msgstr \"Невідома послідовність екранування на позиції %d\"\n"
  },
  {
    "path": "po/vi.po",
    "content": "# Vietnamese translations for tigervnc package\n# Bản dịch Tiếng Việt dành cho gói tigervnc\n# This file is distributed under the same license as the tigervnc package.\n# Trần Ngọc Quân <vnwildman@gmail.com>, 2014, 2015, 2016, 2017, 2018.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.8.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2018-06-13 14:22+0000\\n\"\n\"PO-Revision-Date: 2018-07-04 14:52+0700\\n\"\n\"Last-Translator: Trần Ngọc Quân <vnwildman@gmail.com>\\n\"\n\"Language-Team: Vietnamese <translation-team-vi@lists.sourceforge.net>\\n\"\n\"Language: vi\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Generator: Gtranslator 2.91.7\\n\"\n\n#: vncviewer/CConn.cxx:116\n#, c-format\nmsgid \"connected to socket %s\"\nmsgstr \"đã kết nối đến ổ cắm mạng %s\"\n\n#: vncviewer/CConn.cxx:123\n#, c-format\nmsgid \"connected to host %s port %d\"\nmsgstr \"đã kết nối đến máy %s cổng %d\"\n\n#: vncviewer/CConn.cxx:184\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"Tên máy tính: %.80s\"\n\n#: vncviewer/CConn.cxx:189\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"Máy: %.80s cổng: %d\"\n\n#: vncviewer/CConn.cxx:194\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"Cỡ: %d x %d\"\n\n#: vncviewer/CConn.cxx:202\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"Định dạng điểm ảnh: %s\"\n\n#: vncviewer/CConn.cxx:209\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"(máy chủ mặc định %s)\"\n\n#: vncviewer/CConn.cxx:214\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"Bộ mã đã yêu cầu: %s\"\n\n#: vncviewer/CConn.cxx:219\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"Bảng mã dùng lần cuối: %s\"\n\n#: vncviewer/CConn.cxx:224\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"Ước tính tốc độ đường dây: %d kbit/s\"\n\n#: vncviewer/CConn.cxx:229\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"Phiên bản giao thức: %d.%d\"\n\n#: vncviewer/CConn.cxx:234\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"Phương thức bảo mật: %s\"\n\n#: vncviewer/CConn.cxx:358\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"SetDesktopSize gặp lỗi: %d\"\n\n#: vncviewer/CConn.cxx:428\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"SetColourMapEntries từ máy phục vụ không hợp lệ!\"\n\n#: vncviewer/CConn.cxx:479\nmsgid \"Enabling continuous updates\"\nmsgstr \"Đang bật cập nhật liên tục\"\n\n#: vncviewer/CConn.cxx:556\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"Băng thông %d kbit/s - đổi thành chất lượng %d\"\n\n#: vncviewer/CConn.cxx:578\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now %s\"\nmsgstr \"Băng thông %d kbit/s - màu đầy đủ giờ là %s\"\n\n#: vncviewer/CConn.cxx:580\nmsgid \"disabled\"\nmsgstr \"tắt\"\n\n#: vncviewer/CConn.cxx:580\nmsgid \"enabled\"\nmsgstr \"bật\"\n\n#: vncviewer/CConn.cxx:590\n#, c-format\nmsgid \"Using %s encoding\"\nmsgstr \"Đang dùng bảng mã %s\"\n\n#: vncviewer/CConn.cxx:637\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"Đang dùng định dạng điểm ảnh %s\"\n\n#: vncviewer/DesktopWindow.cxx:122\nmsgid \"Invalid geometry specified!\"\nmsgstr \"Hình dạng đã cho không hợp lệ!\"\n\n#: vncviewer/DesktopWindow.cxx:451\nmsgid \"Adjusting window size to avoid accidental full screen request\"\nmsgstr \"Chỉnh cỡ cửa sổ để tránh yêu cầu toàm màn hình ngẫu nhiên\"\n\n#: vncviewer/DesktopWindow.cxx:495\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"Nhấn vào %s to open the context menu để mở trình đơn ngữ cảnh\"\n\n#: vncviewer/DesktopWindow.cxx:794 vncviewer/DesktopWindow.cxx:802\n#: vncviewer/DesktopWindow.cxx:822\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"Gặp lỗi khi điều khiển bàn phím\"\n\n#: vncviewer/DesktopWindow.cxx:896\nmsgid \"Failure grabbing mouse\"\nmsgstr \"Gặp lỗi khi điều khiển chuột\"\n\n#: vncviewer/DesktopWindow.cxx:1120\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"Bố cục màn hình đã tính toán không hợp lệ cho yêu cầu đổi cỡ!\"\n\n#: vncviewer/OptionsDialog.cxx:57\nmsgid \"VNC Viewer: Connection Options\"\nmsgstr \"Bộ xem VNC: Các tùy chọn kết nối\"\n\n#: vncviewer/OptionsDialog.cxx:83 vncviewer/ServerDialog.cxx:91\n#: vncviewer/vncviewer.cxx:282\nmsgid \"Cancel\"\nmsgstr \"Thôi\"\n\n#: vncviewer/OptionsDialog.cxx:88 vncviewer/vncviewer.cxx:281\nmsgid \"OK\"\nmsgstr \"Đồng ý\"\n\n#: vncviewer/OptionsDialog.cxx:423\nmsgid \"Compression\"\nmsgstr \"Nén\"\n\n#: vncviewer/OptionsDialog.cxx:439\nmsgid \"Auto select\"\nmsgstr \"Chọn tự động\"\n\n#: vncviewer/OptionsDialog.cxx:451\nmsgid \"Preferred encoding\"\nmsgstr \"Bảng mã ưa thích\"\n\n#: vncviewer/OptionsDialog.cxx:499\nmsgid \"Color level\"\nmsgstr \"Mức màu\"\n\n#: vncviewer/OptionsDialog.cxx:510\nmsgid \"Full (all available colors)\"\nmsgstr \"Đầy đủ (mọi màu sẵn có)\"\n\n#: vncviewer/OptionsDialog.cxx:517\nmsgid \"Medium (256 colors)\"\nmsgstr \"Trung bình (256 màu)\"\n\n#: vncviewer/OptionsDialog.cxx:524\nmsgid \"Low (64 colors)\"\nmsgstr \"Thấp (64 màu)\"\n\n#: vncviewer/OptionsDialog.cxx:531\nmsgid \"Very low (8 colors)\"\nmsgstr \"Rất thấp (8 màu)\"\n\n#: vncviewer/OptionsDialog.cxx:548\nmsgid \"Custom compression level:\"\nmsgstr \"Mức nén tự chọn:\"\n\n#: vncviewer/OptionsDialog.cxx:554\nmsgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\nmsgstr \"mức độ (1=nhanh, 6=tốt nhất [4-6 là hữu dụng hơn cả])\"\n\n#: vncviewer/OptionsDialog.cxx:561\nmsgid \"Allow JPEG compression:\"\nmsgstr \"Cho phép nén JPEG:\"\n\n#: vncviewer/OptionsDialog.cxx:567\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"Chất lượng (0=kém, 9=tốt nhất)\"\n\n#: vncviewer/OptionsDialog.cxx:578\nmsgid \"Security\"\nmsgstr \"Bảo mật\"\n\n#: vncviewer/OptionsDialog.cxx:593\nmsgid \"Encryption\"\nmsgstr \"Mã hóa\"\n\n#: vncviewer/OptionsDialog.cxx:604 vncviewer/OptionsDialog.cxx:657\n#: vncviewer/OptionsDialog.cxx:737\nmsgid \"None\"\nmsgstr \"Không có gì\"\n\n#: vncviewer/OptionsDialog.cxx:610\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"TLS với chứng nhận nặc danh\"\n\n#: vncviewer/OptionsDialog.cxx:616\nmsgid \"TLS with X509 certificates\"\nmsgstr \"TLS với chứng nhận X509\"\n\n#: vncviewer/OptionsDialog.cxx:623\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"Đường dẫn chứng nhận CA X509\"\n\n#: vncviewer/OptionsDialog.cxx:630\nmsgid \"Path to X509 CRL file\"\nmsgstr \"Đường dẫn đến tập tin CRL X509\"\n\n#: vncviewer/OptionsDialog.cxx:646\nmsgid \"Authentication\"\nmsgstr \"Xác thực\"\n\n#: vncviewer/OptionsDialog.cxx:663\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"VNC tiêu chuẩn (không bảo mật, không mã hóa)\"\n\n#: vncviewer/OptionsDialog.cxx:669\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"Tài khoản và mật khẩu (không bảo mật, không mã hóa)\"\n\n#: vncviewer/OptionsDialog.cxx:688\nmsgid \"Input\"\nmsgstr \"Đầu vào\"\n\n#: vncviewer/OptionsDialog.cxx:696\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"Chỉ xem (không bắt chuột và bàn phím)\"\n\n#: vncviewer/OptionsDialog.cxx:702\nmsgid \"Accept clipboard from server\"\nmsgstr \"Chấp nhận clipboard từ máy chủ\"\n\n#: vncviewer/OptionsDialog.cxx:710\nmsgid \"Also set primary selection\"\nmsgstr \"Cũng đặt chọn chính\"\n\n#: vncviewer/OptionsDialog.cxx:717\nmsgid \"Send clipboard to server\"\nmsgstr \"Gửi clipboard đến máy chủ\"\n\n#: vncviewer/OptionsDialog.cxx:725\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"Gửi chọn chính là clipboard\"\n\n#: vncviewer/OptionsDialog.cxx:732\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"Gửi các phím hệ thống trực tiếp đến máy phục vụ (toàn màn hình)\"\n\n#: vncviewer/OptionsDialog.cxx:735\nmsgid \"Menu key\"\nmsgstr \"Phím trình đơn\"\n\n#: vncviewer/OptionsDialog.cxx:751\nmsgid \"Screen\"\nmsgstr \"Màn hình\"\n\n#: vncviewer/OptionsDialog.cxx:759\nmsgid \"Resize remote session on connect\"\nmsgstr \"Đổi cỡ phiên máy từ xa khi kết nối\"\n\n#: vncviewer/OptionsDialog.cxx:772\nmsgid \"Resize remote session to the local window\"\nmsgstr \"Đổi cỡ phiên thành cửa sổ nội bộ\"\n\n#: vncviewer/OptionsDialog.cxx:778\nmsgid \"Full-screen mode\"\nmsgstr \"Chế độ toàn màn hình\"\n\n#: vncviewer/OptionsDialog.cxx:784\nmsgid \"Enable full-screen mode over all monitors\"\nmsgstr \"Bật chế độ toàn màn hình qua tất cả các màn hình\"\n\n#: vncviewer/OptionsDialog.cxx:793\nmsgid \"Misc.\"\nmsgstr \"Linh tinh\"\n\n#: vncviewer/OptionsDialog.cxx:801\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"Đã chia sẻ (đừng ngắt kết nối các bộ xem khác)\"\n\n#: vncviewer/OptionsDialog.cxx:807\nmsgid \"Show dot when no cursor\"\nmsgstr \"Hiển thị chấm khi không có con trỏ\"\n\n#: vncviewer/ServerDialog.cxx:42\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"Phần mềm xem VNC: Chi tiết kết nối\"\n\n#: vncviewer/ServerDialog.cxx:49 vncviewer/ServerDialog.cxx:54\nmsgid \"VNC server:\"\nmsgstr \"Máy phục vụ VNC:\"\n\n#: vncviewer/ServerDialog.cxx:64\nmsgid \"Options...\"\nmsgstr \"Tùy chọn…\"\n\n#: vncviewer/ServerDialog.cxx:69\nmsgid \"Load...\"\nmsgstr \"Tải…\"\n\n#: vncviewer/ServerDialog.cxx:74\nmsgid \"Save As...\"\nmsgstr \"Lưu thành…\"\n\n#: vncviewer/ServerDialog.cxx:86\nmsgid \"About...\"\nmsgstr \"Giới thiệu…\"\n\n#: vncviewer/ServerDialog.cxx:96\nmsgid \"Connect\"\nmsgstr \"Kết nối\"\n\n#: vncviewer/ServerDialog.cxx:137 vncviewer/ServerDialog.cxx:171\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"Cấu hình TigerVNC (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:138\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"Chọn một tập tin cấu hình TigerVNC\"\n\n#: vncviewer/ServerDialog.cxx:172\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"Lưu cấu hình TigerVNC vào tập tin\"\n\n#: vncviewer/ServerDialog.cxx:197\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s đã sẵn có. Bạn có muốn ghi đè không?\"\n\n#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:279\nmsgid \"No\"\nmsgstr \"Không\"\n\n#: vncviewer/ServerDialog.cxx:198\nmsgid \"Overwrite\"\nmsgstr \"Ghi đè\"\n\n#: vncviewer/UserDialog.cxx:85\nmsgid \"Opening password file failed\"\nmsgstr \"Gặp lỗi khi mở tập tin mật khẩu\"\n\n#: vncviewer/UserDialog.cxx:105\nmsgid \"VNC authentication\"\nmsgstr \"Xác thực VNC\"\n\n#: vncviewer/UserDialog.cxx:112\nmsgid \"This connection is secure\"\nmsgstr \"Kết nối này là an toàn\"\n\n#: vncviewer/UserDialog.cxx:116\nmsgid \"This connection is not secure\"\nmsgstr \"Kết nối này là không an toàn\"\n\n#: vncviewer/UserDialog.cxx:133\nmsgid \"Username:\"\nmsgstr \"Tài khoản:\"\n\n#: vncviewer/UserDialog.cxx:140\nmsgid \"Password:\"\nmsgstr \"Mật khẩu:\"\n\n#: vncviewer/UserDialog.cxx:179\nmsgid \"Authentication cancelled\"\nmsgstr \"Xác thực bị hủy bỏ\"\n\n#: vncviewer/Viewport.cxx:377\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"Gặp lỗi khi cập nhật trạng thái LED bàn phím: %lu\"\n\n#: vncviewer/Viewport.cxx:383 vncviewer/Viewport.cxx:389\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"Gặp lỗi khi cập nhật trạng thái LED bàn phím: %d\"\n\n#: vncviewer/Viewport.cxx:419\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"Gặp lỗi khi cập nhật trạng thái LED bàn phím\"\n\n#: vncviewer/Viewport.cxx:446 vncviewer/Viewport.cxx:454\n#: vncviewer/Viewport.cxx:471\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"Gặp lỗi khi lấy trạng thái LED bàn phím: %d\"\n\n#: vncviewer/Viewport.cxx:817\nmsgid \"No key code specified on key press\"\nmsgstr \"Không có mã mô tả cho phím bấm\"\n\n#: vncviewer/Viewport.cxx:959\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"Không có mã quét cho phím ảo mở rộng 0x%02x\"\n\n#: vncviewer/Viewport.cxx:961\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"Không có mã quét cho phím ảo 0x%02x\"\n\n#: vncviewer/Viewport.cxx:967\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"Mã quét không hợp lệ 0x%02x\"\n\n#: vncviewer/Viewport.cxx:997\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"Không có ký hiệu cho phím ảo mở rộng 0x%02x\"\n\n#: vncviewer/Viewport.cxx:999\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"Không có ký hiệu cho phím ảo 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1086\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"Không có ký hiệu cho mã phím 0x%02x (trong trạng thái hiện tại)\"\n\n#: vncviewer/Viewport.cxx:1119\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"Không có ký hiệu cho mã phím %d (trong trạng thái hiện tại)\"\n\n#: vncviewer/Viewport.cxx:1170\nmsgctxt \"ContextMenu|\"\nmsgid \"E&xit viewer\"\nmsgstr \"T&hoát khỏi bộ xem\"\n\n#: vncviewer/Viewport.cxx:1173\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"T&oàn màn hình\"\n\n#: vncviewer/Viewport.cxx:1176\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"Thu &nhỏ\"\n\n#: vncviewer/Viewport.cxx:1178\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"Đổi cỡ Cửa &sổ sang phiên\"\n\n#: vncviewer/Viewport.cxx:1183\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:1186\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1192\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"Gửi %s\"\n\n#: vncviewer/Viewport.cxx:1198\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"Gửi Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:1201\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"&Làm mới màn hình\"\n\n#: vncviewer/Viewport.cxx:1204\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"Tù&y chọn…\"\n\n#: vncviewer/Viewport.cxx:1206\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"Thông t&in về kết nối…\"\n\n#: vncviewer/Viewport.cxx:1208\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"Giới thiệu Bộ xem &TigerVNC…\"\n\n#: vncviewer/Viewport.cxx:1211\nmsgctxt \"ContextMenu|\"\nmsgid \"Dismiss &menu\"\nmsgstr \"Thải bỏ &Trình đơn\"\n\n#: vncviewer/Viewport.cxx:1300\nmsgid \"VNC connection info\"\nmsgstr \"Thông tin kết nối VNC\"\n\n#: vncviewer/parameters.cxx:279 vncviewer/parameters.cxx:313\n#, c-format\nmsgid \"The name of the parameter %s was too large to write to the registry\"\nmsgstr \"Tên của tham số %s là quá lớn để ghi vào đăng ký\"\n\n#: vncviewer/parameters.cxx:285 vncviewer/parameters.cxx:292\n#, c-format\nmsgid \"The parameter %s was too large to write to the registry\"\nmsgstr \"Tham số %s là quá lớn để ghi vào đăng ký\"\n\n#: vncviewer/parameters.cxx:298 vncviewer/parameters.cxx:319\n#, c-format\nmsgid \"Failed to write parameter %s of type %s to the registry: %ld\"\nmsgstr \"Gặp lỗi khi ghi tham số %s của kiểu %s vào sổ đăng ký: %ld\"\n\n#: vncviewer/parameters.cxx:334 vncviewer/parameters.cxx:373\n#, c-format\nmsgid \"The name of the parameter %s was too large to read from the registry\"\nmsgstr \"Tên của tham số %s là quá lớn để đọc từ sổ đăng ký\"\n\n#: vncviewer/parameters.cxx:343 vncviewer/parameters.cxx:382\n#, c-format\nmsgid \"Failed to read parameter %s from the registry: %ld\"\nmsgstr \"Gặp lỗi khi đọc tham số %s từ sổ đăng ký: %ld\"\n\n#: vncviewer/parameters.cxx:352\n#, c-format\nmsgid \"The parameter %s was too large to read from the registry\"\nmsgstr \"Tham số %s là quá lớn để đọc từ sổ đăng ký\"\n\n#: vncviewer/parameters.cxx:402\n#, c-format\nmsgid \"Failed to create registry key: %ld\"\nmsgstr \"Gặp lỗi khi tạo khóa đăng ký: %ld\"\n\n#: vncviewer/parameters.cxx:416 vncviewer/parameters.cxx:465\n#: vncviewer/parameters.cxx:527 vncviewer/parameters.cxx:660\n#, c-format\nmsgid \"Unknown parameter type for parameter %s\"\nmsgstr \"Không hiểu kiểu tham số cho đối số %s\"\n\n#: vncviewer/parameters.cxx:423 vncviewer/parameters.cxx:472\n#, c-format\nmsgid \"Failed to close registry key: %ld\"\nmsgstr \"Gặp lỗi khi đóng khóa đăng ký: %ld\"\n\n#: vncviewer/parameters.cxx:439\n#, c-format\nmsgid \"Failed to open registry key: %ld\"\nmsgstr \"Gặp lỗi khi mở khóa đăng ký: %ld\"\n\n#: vncviewer/parameters.cxx:496\nmsgid \"Failed to write configuration file, can't obtain home directory path.\"\nmsgstr \"Gặp lỗi khi ghi tập tin cấu hình, không thể lấy đường dẫn thư mục riêng.\"\n\n#: vncviewer/parameters.cxx:509\n#, c-format\nmsgid \"Failed to write configuration file, can't open %s: %s\"\nmsgstr \"Gặp lỗi khi ghi tập tin cấu hình, không thể mở %s: %s\"\n\n#: vncviewer/parameters.cxx:554\nmsgid \"Failed to read configuration file, can't obtain home directory path.\"\nmsgstr \"Gặp lỗi khi đọc tập tin cấu hình, không thể lấy đường dẫn thư mục riêng.\"\n\n#: vncviewer/parameters.cxx:567\n#, c-format\nmsgid \"Failed to read configuration file, can't open %s: %s\"\nmsgstr \"Gặp lỗi khi đọc tập tin cấu hình, không thể mở %s: %s\"\n\n#: vncviewer/parameters.cxx:580 vncviewer/parameters.cxx:585\n#: vncviewer/parameters.cxx:610 vncviewer/parameters.cxx:623\n#: vncviewer/parameters.cxx:639\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"Gặp lỗi khi đọc dòng %d trong tập tin %s: %s\"\n\n#: vncviewer/parameters.cxx:586\nmsgid \"Line too long\"\nmsgstr \"Dòng quá dài\"\n\n#: vncviewer/parameters.cxx:593\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"Tập tin cấu hình %s ở định dạng không hợp lệ\"\n\n#: vncviewer/parameters.cxx:611\nmsgid \"Invalid format\"\nmsgstr \"Định dạng không hợp lệ\"\n\n#: vncviewer/parameters.cxx:624 vncviewer/parameters.cxx:640\nmsgid \"Invalid format or too large value\"\nmsgstr \"Định dạng không hợp lệ hay giá trị quá lớn\"\n\n#: vncviewer/parameters.cxx:667\n#, c-format\nmsgid \"Unknown parameter %s on line %d in file %s\"\nmsgstr \"Không hiểu tham số %s trên dòng %d ở tập tin %s\"\n\n#: vncviewer/vncviewer.cxx:100\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer %d-bit v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See http://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC Viewer %d-bít v%s\\n\"\n\"Biên dịch vào: %s\\n\"\n\"Copyright (C) 1999-%d Nhóm TigerVNC và nhiều người khác (xem README.rst)\\n\"\n\"Truy cập http://www.tigervnc.org để biết thêm thông tin về TigerVNC.\"\n\n#: vncviewer/vncviewer.cxx:127\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"Giới thiệu về bộ xem TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:140\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"Lỗi bên trong FLTK. Nên thoát.\"\n\n#: vncviewer/vncviewer.cxx:158 vncviewer/vncviewer.cxx:170\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"Gặp lỗi khi khởi chạy bộ xem TigerVNC mới: %s\"\n\n#: vncviewer/vncviewer.cxx:179\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"Đã nhận được tín hiệu kết thúc %d. Bộ xem TigerVNC bây giờ sẽ thoát.\"\n\n#: vncviewer/vncviewer.cxx:271 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"Bộ xem TigerVNC\"\n\n#: vncviewer/vncviewer.cxx:280\nmsgid \"Yes\"\nmsgstr \"Có\"\n\n#: vncviewer/vncviewer.cxx:283\nmsgid \"Close\"\nmsgstr \"Đóng\"\n\n#: vncviewer/vncviewer.cxx:288\nmsgid \"About\"\nmsgstr \"Giới thiệu\"\n\n#: vncviewer/vncviewer.cxx:291\nmsgid \"Hide\"\nmsgstr \"Ẩn\"\n\n#: vncviewer/vncviewer.cxx:294\nmsgid \"Quit\"\nmsgstr \"Thoát\"\n\n#: vncviewer/vncviewer.cxx:298\nmsgid \"Services\"\nmsgstr \"Dịch vụ\"\n\n#: vncviewer/vncviewer.cxx:299\nmsgid \"Hide Others\"\nmsgstr \"Ẩn các cái khác\"\n\n#: vncviewer/vncviewer.cxx:300\nmsgid \"Show All\"\nmsgstr \"Hiện tất cả\"\n\n#: vncviewer/vncviewer.cxx:309\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"&Chính\"\n\n#: vncviewer/vncviewer.cxx:312\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"Kết nối &mới\"\n\n#: vncviewer/vncviewer.cxx:324\nmsgid \"Could not create VNC home directory: can't obtain home directory path.\"\nmsgstr \"Không thể tạo thư mục cá nhân cho VNC: không thể lấy đường dẫn thư mục cá nhân.\"\n\n#: vncviewer/vncviewer.cxx:329\n#, c-format\nmsgid \"Could not create VNC home directory: %s.\"\nmsgstr \"Không thể tạo thư mục cá nhân cho VNC: %s.\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:581 vncviewer/vncviewer.cxx:583\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"Các tham số -listen và -via xung khắc nhau\"\n\n#: vncviewer/vncviewer.cxx:598\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"Đang nghe trên cổng %d\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"Trình xem màn hình từ xa\"\n\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"Kết nối đến máy phục vụ VNC và hiển thị màn hình từ xa\"\n\n#: vncviewer/vncviewer.desktop.in.in:7\nmsgid \"tigervnc\"\nmsgstr \"tigervnc\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"Không đủ bộ nhớ cho bộ đệm khung\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"Không thể tạo thiết bị bộ đệm khung\"\n\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"Không thể tạo ánh xạ bộ đệm khung\"\n\n#~ msgid \"Unable to create platform specific framebuffer: %s\"\n#~ msgstr \"Không thể tạo bộ đệm khung đặc tả nền tảng: %s\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"Đang sử dụng bộ đệm khung độc lập nên tảng\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"không thể tạo phần DIB\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"CreateCompatibleDC gặp lỗi\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"SelectObject gặp lỗi\"\n\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"BitBlt gặp lỗi\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"Hiển thị định dạng pixmap thiếu cho độ sâu mặc định\"\n\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"Không thể tìm thấy định dạng phù hợp pixmap\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"Chỉ hỗ trợ hiển thị màu thật\"\n\n#~ msgid \"Using default colormap and visual, TrueColor, depth %d.\"\n#~ msgstr \"Đang dùng bản đồ màu mặc định và ảo, TrueColor, độ sâu %d.\"\n\n#~ msgid \"Could not create framebuffer image\"\n#~ msgstr \"Không thể tạo ảnh bộ đệm khung\"\n\n#~ msgid \"Unknown encoding %d\"\n#~ msgstr \"Bảng mã chưa biết %d\"\n\n#~ msgid \"Unknown encoding\"\n#~ msgstr \"Bảng mã chưa biết\"\n\n#~ msgid \"Alt\"\n#~ msgstr \"Alt\"\n\n#~ msgid \"CleanupSignalHandler called\"\n#~ msgstr \"CleanupSignalHandler được gọi\"\n\n#, fuzzy\n#~ msgid \"Error(%d) reading %s from Registry.\"\n#~ msgstr \"Gặp lỗi khi đọc từ máy phục vụ\"\n"
  },
  {
    "path": "po/zh_CN.po",
    "content": "# TigerVNC in zh_CN\n# Copyright (C) 2015 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n# Mingcong Bai <jeffbai@aosc.xyz>, 2015.\n# Mingye Wang (Artoria2e5) <arthur200126@gmail.com>, 2016, 2024.\n# Boyuan Yang <073plan@gmail.com>, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.13.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2024-06-20 15:01+0200\\n\"\n\"PO-Revision-Date: 2024-09-02 12:19+0800\\n\"\n\"Last-Translator: Mingye Wang (Artoria2e5) <arthur200126@gmail.com>\\n\"\n\"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\\n\"\n\"Language: zh_CN\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.5\\n\"\n\n#: vncviewer/CConn.cxx:99\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"连接到套接字 %s\"\n\n#: vncviewer/CConn.cxx:106\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"已连接到主机 %s 的端口 %d\"\n\n#: vncviewer/CConn.cxx:111\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"未能连接到 “%s”：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:155\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"桌面名称：%.80s\"\n\n#: vncviewer/CConn.cxx:160\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"主机：%.80s 端口：%d\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"尺寸：%d x %d\"\n\n#: vncviewer/CConn.cxx:173\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"像素格式：%s\"\n\n#: vncviewer/CConn.cxx:180\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"（服务器默认值 %s）\"\n\n#: vncviewer/CConn.cxx:185\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"请求的编码：%s\"\n\n#: vncviewer/CConn.cxx:190\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"最近使用的编码：%s\"\n\n#: vncviewer/CConn.cxx:195\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"线路速度估计值：%d kbit/s\"\n\n#: vncviewer/CConn.cxx:200\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"协议版本：%d.%d\"\n\n#: vncviewer/CConn.cxx:205\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"安全方式：%s\"\n\n#: vncviewer/CConn.cxx:266 vncviewer/CConn.cxx:268\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"在建立会话之前，服务器已断开连接。\"\n\n#: vncviewer/CConn.cxx:326\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"SetDesktopSize 函数失败：%d\"\n\n#: vncviewer/CConn.cxx:399\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"来自服务器的 SetColourMapEntries 信号无效！\"\n\n#: vncviewer/CConn.cxx:507\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"吞吐量 %d kbit/s - 改变质量级别为 %d\"\n\n#: vncviewer/CConn.cxx:529\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"吞吐量 %d kbit/s - 现已启用全彩\"\n\n#: vncviewer/CConn.cxx:532\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"吞吐量 %d kbit/s - 现已禁用全彩\"\n\n#: vncviewer/CConn.cxx:558\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"正在使用像素格式 %s\"\n\n#: vncviewer/DesktopWindow.cxx:146\nmsgid \"Invalid geometry specified!\"\nmsgstr \"指定的几何尺寸无效！\"\n\n#: vncviewer/DesktopWindow.cxx:167\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"减小窗口大小以适应当前显示器\"\n\n#: vncviewer/DesktopWindow.cxx:648\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"正在调整窗口大小以避免意外的全屏请求\"\n\n#: vncviewer/DesktopWindow.cxx:696\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"按下 %s 以打开上下文菜单\"\n\n#: vncviewer/DesktopWindow.cxx:1097 vncviewer/DesktopWindow.cxx:1105\n#: vncviewer/DesktopWindow.cxx:1125\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"占用键盘失败\"\n\n#: vncviewer/DesktopWindow.cxx:1415\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"大小改变请求计算得到了无效的屏幕布局！\"\n\n#: vncviewer/EmulateMB.cxx:226 vncviewer/EmulateMB.cxx:289\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"三按钮仿真的状态无效\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:52\n#: vncviewer/MonitorIndicesParameter.cxx:102\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"未能获取系统显示器配置\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:80\n#, c-format\nmsgid \"Invalid configuration specified for %s\"\nmsgstr \"为 %s 指定的配置无效\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:88\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"显示器索引%d不存在\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:166\n#: vncviewer/MonitorIndicesParameter.cxx:186\n#, c-format\nmsgid \"Invalid monitor index '%s'\"\nmsgstr \"显示器索引 '%s' 无效\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:174\n#, c-format\nmsgid \"Unexpected character '%c'\"\nmsgstr \"意料之外的字符 '%c'\"\n\n#: vncviewer/OptionsDialog.cxx:64\nmsgid \"TigerVNC Options\"\nmsgstr \"TigerVNC 选项\"\n\n#: vncviewer/OptionsDialog.cxx:97 vncviewer/ServerDialog.cxx:102\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Cancel\"\nmsgstr \"取消\"\n\n#: vncviewer/OptionsDialog.cxx:102 vncviewer/vncviewer.cxx:394\nmsgid \"OK\"\nmsgstr \"确定\"\n\n#: vncviewer/OptionsDialog.cxx:502\nmsgid \"Compression\"\nmsgstr \"压缩\"\n\n#: vncviewer/OptionsDialog.cxx:518\nmsgid \"Auto select\"\nmsgstr \"自动选择\"\n\n#: vncviewer/OptionsDialog.cxx:529\nmsgid \"Preferred encoding\"\nmsgstr \"首选编码\"\n\n#: vncviewer/OptionsDialog.cxx:590\nmsgid \"Color level\"\nmsgstr \"颜色级别\"\n\n#: vncviewer/OptionsDialog.cxx:602\nmsgid \"Full\"\nmsgstr \"全部\"\n\n#: vncviewer/OptionsDialog.cxx:609\nmsgid \"Medium\"\nmsgstr \"中\"\n\n#: vncviewer/OptionsDialog.cxx:616\nmsgid \"Low\"\nmsgstr \"低\"\n\n#: vncviewer/OptionsDialog.cxx:623\nmsgid \"Very low\"\nmsgstr \"非常低\"\n\n#: vncviewer/OptionsDialog.cxx:645\nmsgid \"Custom compression level:\"\nmsgstr \"自定义压缩级别：\"\n\n#: vncviewer/OptionsDialog.cxx:652\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"级别（0=最快，9=最好）\"\n\n#: vncviewer/OptionsDialog.cxx:659\nmsgid \"Allow JPEG compression:\"\nmsgstr \"允许 JPEG 压缩：\"\n\n#: vncviewer/OptionsDialog.cxx:666\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"质量（0=最差，9=最好）\"\n\n#: vncviewer/OptionsDialog.cxx:677\nmsgid \"Security\"\nmsgstr \"安全\"\n\n#: vncviewer/OptionsDialog.cxx:691\nmsgid \"Encryption\"\nmsgstr \"加密\"\n\n#: vncviewer/OptionsDialog.cxx:703 vncviewer/OptionsDialog.cxx:770\n#: vncviewer/OptionsDialog.cxx:876\nmsgid \"None\"\nmsgstr \"无\"\n\n#: vncviewer/OptionsDialog.cxx:710\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"带有匿名证书的 TLS\"\n\n#: vncviewer/OptionsDialog.cxx:716\nmsgid \"TLS with X509 certificates\"\nmsgstr \"带有 X509 证书的 TLS\"\n\n#: vncviewer/OptionsDialog.cxx:723\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"X509 CA 证书路径\"\n\n#: vncviewer/OptionsDialog.cxx:730\nmsgid \"Path to X509 CRL file\"\nmsgstr \"X509 CRL 文件路径\"\n\n#: vncviewer/OptionsDialog.cxx:758\nmsgid \"Authentication\"\nmsgstr \"认证\"\n\n#: vncviewer/OptionsDialog.cxx:776\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"标准 VNC（不安全且无加密）\"\n\n#: vncviewer/OptionsDialog.cxx:782\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"用户名及密码（不安全且无加密）\"\n\n#: vncviewer/OptionsDialog.cxx:805\nmsgid \"Input\"\nmsgstr \"输入\"\n\n#: vncviewer/OptionsDialog.cxx:818\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"仅显示（忽略鼠标及键盘）\"\n\n#: vncviewer/OptionsDialog.cxx:825\nmsgid \"Mouse\"\nmsgstr \"鼠标\"\n\n#: vncviewer/OptionsDialog.cxx:837\nmsgid \"Emulate middle mouse button\"\nmsgstr \"模拟鼠标中键\"\n\n#: vncviewer/OptionsDialog.cxx:843\nmsgid \"Show dot when no cursor\"\nmsgstr \"无光标时显示一个点\"\n\n#: vncviewer/OptionsDialog.cxx:859\nmsgid \"Keyboard\"\nmsgstr \"键盘\"\n\n#: vncviewer/OptionsDialog.cxx:871\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"将系统键位直接传递到服务器（全屏）\"\n\n#: vncviewer/OptionsDialog.cxx:874\nmsgid \"Menu key\"\nmsgstr \"菜单键\"\n\n#: vncviewer/OptionsDialog.cxx:895\nmsgid \"Clipboard\"\nmsgstr \"剪贴板\"\n\n#: vncviewer/OptionsDialog.cxx:907\nmsgid \"Accept clipboard from server\"\nmsgstr \"接受来自服务器的剪切板内容\"\n\n#: vncviewer/OptionsDialog.cxx:915\nmsgid \"Also set primary selection\"\nmsgstr \"同样设定鼠标选择内容\"\n\n#: vncviewer/OptionsDialog.cxx:922\nmsgid \"Send clipboard to server\"\nmsgstr \"发送剪切板内容到服务器\"\n\n#: vncviewer/OptionsDialog.cxx:930\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"将鼠标选择内容作为剪切板内容发送\"\n\n#: vncviewer/OptionsDialog.cxx:951\nmsgid \"Display\"\nmsgstr \"显示\"\n\n#: vncviewer/OptionsDialog.cxx:965\nmsgid \"Display mode\"\nmsgstr \"显示模式\"\n\n#: vncviewer/OptionsDialog.cxx:978\nmsgid \"Windowed\"\nmsgstr \"窗口化\"\n\n#: vncviewer/OptionsDialog.cxx:986\nmsgid \"Full screen on current monitor\"\nmsgstr \"在当前显示器上全屏显示\"\n\n#: vncviewer/OptionsDialog.cxx:994\nmsgid \"Full screen on all monitors\"\nmsgstr \"为所有显示器开启全屏模式\"\n\n#: vncviewer/OptionsDialog.cxx:1002\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"为选定显示器开启全屏模式\"\n\n#: vncviewer/OptionsDialog.cxx:1031\nmsgid \"Miscellaneous\"\nmsgstr \"杂项\"\n\n#: vncviewer/OptionsDialog.cxx:1039\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"共享（不要断开其他查看器）\"\n\n#: vncviewer/OptionsDialog.cxx:1045\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"连接错误时询问是否重新连接\"\n\n#: vncviewer/ServerDialog.cxx:58\nmsgid \"VNC Viewer: Connection Details\"\nmsgstr \"VNC 查看器：连接细节\"\n\n#: vncviewer/ServerDialog.cxx:68\nmsgid \"VNC server:\"\nmsgstr \"VNC 服务器：\"\n\n#: vncviewer/ServerDialog.cxx:75\nmsgid \"Options...\"\nmsgstr \"选项...\"\n\n#: vncviewer/ServerDialog.cxx:79\nmsgid \"Load...\"\nmsgstr \"载入...\"\n\n#: vncviewer/ServerDialog.cxx:83\nmsgid \"Save As...\"\nmsgstr \"保存为...\"\n\n#: vncviewer/ServerDialog.cxx:97\nmsgid \"About...\"\nmsgstr \"关于...\"\n\n#: vncviewer/ServerDialog.cxx:106\nmsgid \"Connect\"\nmsgstr \"连接\"\n\n#: vncviewer/ServerDialog.cxx:143\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"未能加载服务器历史记录：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:172 vncviewer/ServerDialog.cxx:212\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"TigerVNC 配置（*.tigervnc）\"\n\n#: vncviewer/ServerDialog.cxx:173\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"选择 TigerVNC 配置文件\"\n\n#: vncviewer/ServerDialog.cxx:195 vncviewer/vncviewer.cxx:515\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"未能加载指定的配置文件：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:213\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"将 TigerVNC 配置保存到文件\"\n\n#: vncviewer/ServerDialog.cxx:239\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s 已经存在。是否要覆盖？\"\n\n#: vncviewer/ServerDialog.cxx:240 vncviewer/vncviewer.cxx:392\nmsgid \"No\"\nmsgstr \"否\"\n\n#: vncviewer/ServerDialog.cxx:240\nmsgid \"Overwrite\"\nmsgstr \"覆盖\"\n\n#: vncviewer/ServerDialog.cxx:256\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"未能保存指定的配置文件：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:290\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"未能保存默认配置：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:303\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"未能保存服务器历史记录：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:320 vncviewer/ServerDialog.cxx:386\nmsgid \"Could not obtain the state directory path\"\nmsgstr \"未能获取状态目录路径\"\n\n#: vncviewer/ServerDialog.cxx:332 vncviewer/ServerDialog.cxx:394\n#: vncviewer/parameters.cxx:644 vncviewer/parameters.cxx:750\n#, c-format\nmsgid \"Could not open \\\"%s\\\": %s\"\nmsgstr \"未能打开“%s”： %s\"\n\n#: vncviewer/ServerDialog.cxx:347 vncviewer/ServerDialog.cxx:355\n#: vncviewer/parameters.cxx:764 vncviewer/parameters.cxx:770\n#: vncviewer/parameters.cxx:801 vncviewer/parameters.cxx:830\n#: vncviewer/parameters.cxx:836\n#, c-format\nmsgid \"Failed to read line %d in file %s: %s\"\nmsgstr \"未能读取文件 %2$s 的第 %1$d 行：%3$s\"\n\n#: vncviewer/ServerDialog.cxx:356 vncviewer/parameters.cxx:771\nmsgid \"Line too long\"\nmsgstr \"行过长\"\n\n#: vncviewer/UserDialog.cxx:99\nmsgid \"Opening password file failed\"\nmsgstr \"打开密码文件失败\"\n\n#: vncviewer/UserDialog.cxx:118\nmsgid \"VNC authentication\"\nmsgstr \"VNC 认证\"\n\n#: vncviewer/UserDialog.cxx:125\nmsgid \"This connection is secure\"\nmsgstr \"此连接是安全的\"\n\n#: vncviewer/UserDialog.cxx:129\nmsgid \"This connection is not secure\"\nmsgstr \"此连接不安全\"\n\n#: vncviewer/UserDialog.cxx:151\nmsgid \"Username:\"\nmsgstr \"用户名：\"\n\n#: vncviewer/UserDialog.cxx:164\nmsgid \"Password:\"\nmsgstr \"密码：\"\n\n#: vncviewer/UserDialog.cxx:207\nmsgid \"Authentication cancelled\"\nmsgstr \"认证已取消\"\n\n#: vncviewer/Viewport.cxx:390\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"未能更新键盘 LED 状态：%lu\"\n\n#: vncviewer/Viewport.cxx:396 vncviewer/Viewport.cxx:402\n#, c-format\nmsgid \"Failed to update keyboard LED state: %d\"\nmsgstr \"未能更新键盘 LED 状态：%d\"\n\n#: vncviewer/Viewport.cxx:432\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"未能更新键盘 LED 状态\"\n\n#: vncviewer/Viewport.cxx:459 vncviewer/Viewport.cxx:467\n#: vncviewer/Viewport.cxx:484\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"未能获取键盘 LED 指示灯状态：%d\"\n\n#: vncviewer/Viewport.cxx:839\nmsgid \"No key code specified on key press\"\nmsgstr \"按下按键时未指定键码\"\n\n#: vncviewer/Viewport.cxx:990\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"扩展虚拟键 0x%02x 无扫描码\"\n\n#: vncviewer/Viewport.cxx:992\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"虚拟键 0x%02x 无扫描码\"\n\n#: vncviewer/Viewport.cxx:998\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"无效的键盘扫描码 0x%02x\"\n\n#: vncviewer/Viewport.cxx:1028\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"扩展虚拟键 0x%02x 无符号\"\n\n#: vncviewer/Viewport.cxx:1030\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"虚拟键 0x%02x 无符号\"\n\n#: vncviewer/Viewport.cxx:1136\n#, c-format\nmsgid \"No symbol for key code 0x%02x (in the current state)\"\nmsgstr \"键位码 0x%02x 无符号（当前状态）\"\n\n#: vncviewer/Viewport.cxx:1169\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"键位码 %d 无符号（当前状态）\"\n\n#: vncviewer/Viewport.cxx:1229\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"断开（&E）\"\n\n#: vncviewer/Viewport.cxx:1232\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"全屏(&F)\"\n\n#: vncviewer/Viewport.cxx:1235\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"最小化(&Z)\"\n\n#: vncviewer/Viewport.cxx:1237\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"改变窗口大小以适应会话(&W)\"\n\n#: vncviewer/Viewport.cxx:1242\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:1245\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:1251\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"发送 %s\"\n\n#: vncviewer/Viewport.cxx:1257\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"发送 Ctrl-Alt-&Del\"\n\n#: vncviewer/Viewport.cxx:1260\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"刷新屏幕(&R)\"\n\n#: vncviewer/Viewport.cxx:1263\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"选项...(&O)\"\n\n#: vncviewer/Viewport.cxx:1265\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"连接信息...(&I)\"\n\n#: vncviewer/Viewport.cxx:1267\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"关于 &TigerVNC 查看器...\"\n\n#: vncviewer/Viewport.cxx:1356\nmsgid \"VNC connection info\"\nmsgstr \"VNC 连接信息\"\n\n#: vncviewer/Win32TouchHandler.cxx:47\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"窗口为触摸而不是手势注册\"\n\n#: vncviewer/Win32TouchHandler.cxx:82\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"未能设置手势配置（错误 0x%x）\"\n\n#: vncviewer/Win32TouchHandler.cxx:94\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"未能获取手势信息（错误 0x%x）\"\n\n#: vncviewer/Win32TouchHandler.cxx:359\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"无效的鼠标按钮%d，必须是介于 1 和 7 之间的数字。\"\n\n#: vncviewer/Win32TouchHandler.cxx:424\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"未处理的键 0x%x - 未能生成键盘事件。\"\n\n#: vncviewer/XInputTouchHandler.cxx:102 vncviewer/touch.cxx:108\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"未能获取窗口 0x%08lx 的 X Input 2 事件掩码\"\n\n#: vncviewer/XInputTouchHandler.cxx:104\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"窗口 0x%08lx 没有 X Input 2 事件掩码\"\n\n#: vncviewer/XInputTouchHandler.cxx:112 vncviewer/touch.cxx:115\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"窗口 0x%08lx 具有多个 X Input 2 事件掩码\"\n\n#: vncviewer/XInputTouchHandler.cxx:143\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"抓取设备 %i 失败\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\n#: vncviewer/vncviewer.cxx:389 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC Viewer\"\nmsgstr \"TigerVNC 查看器\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"连接到 VNC 服务器并显示远程桌面\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"虚拟网络计算（VNC）是一种远程显示系统，允许您查看网络上另一台计算机上运行的虚拟桌面环境并与之交互。通过 VNC，您可以在远程计算机上运行图形应用程序，并仅将这些应用程序显示的内容发送到本地设备。此软件包含有一个客户端，通过该客户端，您可以连接到运行 VNC 服务器的其他桌面。VNC 支持各种操作系统和架构作为服务器和客户端。\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC 是基于 RealVNC 4 和 X.org 代码库的高速 VNC 版本。TigerVNC 最初是 Unix 和 Linux 平台上 TightVNC 的下一代开发工作，但它在 2009 年初从其父项目中分离出来，以便 TightVNC 专注于 Windows 平台。TigerVNC 支持 Tight 编码的一种变体，通过使用 libjpeg-turbo JPEG 编解码器大大加速。\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC Viewer connection to a CentOS machine\"\nmsgstr \"TigerVNC Viewer 连接到 CentOS 机器\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC Viewer connection to a macOS machine\"\nmsgstr \"TigerVNC Viewer 连接到 macOS 机器\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC Viewer connection to a Windows machine\"\nmsgstr \"TigerVNC Viewer 连接到 Windows 机器\"\n\n#: vncviewer/parameters.cxx:307 vncviewer/parameters.cxx:332\n#: vncviewer/parameters.cxx:349 vncviewer/parameters.cxx:389\n#: vncviewer/parameters.cxx:409\nmsgid \"The name of the parameter is too large\"\nmsgstr \"参数名称太大\"\n\n#: vncviewer/parameters.cxx:311 vncviewer/parameters.cxx:316\n#: vncviewer/parameters.cxx:367\nmsgid \"The parameter is too large\"\nmsgstr \"参数太大\"\n\n#: vncviewer/parameters.cxx:374 vncviewer/parameters.cxx:694\n#: vncviewer/parameters.cxx:815\nmsgid \"Invalid format or too large value\"\nmsgstr \"格式无效或值太大\"\n\n#: vncviewer/parameters.cxx:428 vncviewer/parameters.cxx:459\nmsgid \"Failed to create registry key\"\nmsgstr \"创建注册键值失败\"\n\n#: vncviewer/parameters.cxx:447 vncviewer/parameters.cxx:502\n#: vncviewer/parameters.cxx:544 vncviewer/parameters.cxx:611\nmsgid \"Failed to close registry key\"\nmsgstr \"关闭注册键值失败\"\n\n#: vncviewer/parameters.cxx:465 vncviewer/parameters.cxx:482\n#: vncviewer/parameters.cxx:652 vncviewer/parameters.cxx:662\n#: vncviewer/parameters.cxx:673\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"未能保存 “%s”：%s\"\n\n#: vncviewer/parameters.cxx:478 vncviewer/parameters.cxx:566\n#: vncviewer/parameters.cxx:675 vncviewer/parameters.cxx:712\nmsgid \"Unknown parameter type\"\nmsgstr \"未知参数类型\"\n\n#: vncviewer/parameters.cxx:495\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"未能移除 “%s”：%s\"\n\n#: vncviewer/parameters.cxx:517 vncviewer/parameters.cxx:589\nmsgid \"Failed to open registry key\"\nmsgstr \"无法打开注册键值\"\n\n#: vncviewer/parameters.cxx:534\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"无法读取服务器历史记录条目 %d：%s\"\n\n#: vncviewer/parameters.cxx:570 vncviewer/parameters.cxx:600\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"无法读取参数 %s：%s\"\n\n#: vncviewer/parameters.cxx:634 vncviewer/parameters.cxx:738\nmsgid \"Could not obtain the config directory path\"\nmsgstr \"无法获取配置目录路径\"\n\n#: vncviewer/parameters.cxx:653 vncviewer/parameters.cxx:664\nmsgid \"Could not encode parameter\"\nmsgstr \"无法对参数进行编码\"\n\n#: vncviewer/parameters.cxx:780\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"配置文件 %s 的格式无效\"\n\n#: vncviewer/parameters.cxx:802\nmsgid \"Invalid format\"\nmsgstr \"格式无效\"\n\n#: vncviewer/parameters.cxx:837\nmsgid \"Unknown parameter\"\nmsgstr \"未知参数\"\n\n#: vncviewer/touch.cxx:76\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"未处理窗口收到了消息（0x%x）\"\n\n#: vncviewer/touch.cxx:139 vncviewer/touch.cxx:161\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"为指针抓取指定的窗口 0x%08lx 无效\"\n\n#: vncviewer/touch.cxx:184 vncviewer/touch.cxx:185\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"未能创建触摸处理程序 %s\"\n\n#: vncviewer/touch.cxx:189\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"未能将事件处理程序附加到窗口（错误 0x%x）\"\n\n#: vncviewer/touch.cxx:216\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"未能获取 X Input 事件的事件数据\"\n\n#: vncviewer/touch.cxx:229\nmsgid \"X Input event for unknown window\"\nmsgstr \"未知窗口的 X Input 事件\"\n\n#: vncviewer/touch.cxx:255\nmsgid \"X Input extension not available.\"\nmsgstr \"X Input 扩展不可用。\"\n\n#: vncviewer/touch.cxx:262\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"X Input 2（或更高版本）不可用。\"\n\n#: vncviewer/touch.cxx:267\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"X Input 2.2（或更高版本）不可用。不支持触摸手势。\"\n\n#: vncviewer/vncviewer.cxx:104\n#, c-format\nmsgid \"\"\n\"TigerVNC Viewer v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC 查看器 v%s\\n\"\n\"构建于：%s\\n\"\n\"版权所有 1999-%d TigerVNC 团队及众多开发者（参见 README.txt）\\n\"\n\"访问 http://www.tigervnc.org 以获取更多关于 TigerVNC 的信息。\"\n\n#: vncviewer/vncviewer.cxx:158\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"与服务器通信时发生意外错误：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:174\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"关于 TigerVNC 查看器\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"FLTK 内部错误。现在将退出。\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"尝试重新连接？\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"启动 TigerVNC 查看器出错：%s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC Viewer will now exit.\"\nmsgstr \"收到终端信号 %d 。TigerVNC 现在将退出。\"\n\n#: vncviewer/vncviewer.cxx:393\nmsgid \"Yes\"\nmsgstr \"是\"\n\n#: vncviewer/vncviewer.cxx:396\nmsgid \"Close\"\nmsgstr \"关闭\"\n\n#: vncviewer/vncviewer.cxx:401\nmsgid \"About\"\nmsgstr \"关于\"\n\n#: vncviewer/vncviewer.cxx:404\nmsgid \"Hide\"\nmsgstr \"隐藏\"\n\n#: vncviewer/vncviewer.cxx:407\nmsgid \"Quit\"\nmsgstr \"退出\"\n\n#: vncviewer/vncviewer.cxx:411\nmsgid \"Services\"\nmsgstr \"服务\"\n\n#: vncviewer/vncviewer.cxx:412\nmsgid \"Hide Others\"\nmsgstr \"隐藏其他\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Show All\"\nmsgstr \"全部显示\"\n\n#: vncviewer/vncviewer.cxx:422\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"文件(&F)\"\n\n#: vncviewer/vncviewer.cxx:425\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"新建连接(&N)\"\n\n#: vncviewer/vncviewer.cxx:525\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"FullScreenAllMonitors 已弃用，请将 FullScreenMode 改为“all”\"\n\n#: vncviewer/vncviewer.cxx:721\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc 已弃用，请查阅 'man vncviewer' 以获取新路径。\"\n\n#: vncviewer/vncviewer.cxx:725\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc 已弃用，请切换到 %%APPDATA%%\\\\TigerVNC 位置。\"\n\n#: vncviewer/vncviewer.cxx:730\n#, c-format\nmsgid \"Could not create VNC config directory: %s\"\nmsgstr \"未能创建 VNC 配置目录：%s\"\n\n#: vncviewer/vncviewer.cxx:735\n#, c-format\nmsgid \"Could not create VNC data directory: %s\"\nmsgstr \"未能创建 VNC 数据目录：%s\"\n\n#: vncviewer/vncviewer.cxx:740\n#, c-format\nmsgid \"Could not create VNC state directory: %s\"\nmsgstr \"未能创建 VNC 状态目录：%s\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:755 vncviewer/vncviewer.cxx:756\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"-listen 及 -via 参数不兼容\"\n\n#: vncviewer/vncviewer.cxx:770\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"未能侦听传入连接\"\n\n#: vncviewer/vncviewer.cxx:772\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"正在监听端口 %d\"\n\n#: vncviewer/vncviewer.cxx:805\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"等待传入 VNC 连接失败：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote Desktop Viewer\"\nmsgstr \"远程桌面查看器\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"已启动持续更新\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"已禁用\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"已启用\"\n\n#, c-format\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"使用 %s 编码\"\n\n#~ msgid \"Not enough memory for framebuffer\"\n#~ msgstr \"帧缓冲内存不足\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"完整（所有可用颜色）\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"中等（256 色）\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"低（64 色）\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"非常低（8 色）\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"级别（1=快速，6=最佳 [4-6 使用较少]）\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"屏幕\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"连接到远程会话时改变屏幕大小\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"改变远程会话屏幕大小以适应本地窗口大小\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"全屏模式\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"杂项\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"退出查看器(&X)\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"忽略菜单(&M)\"\n\n#, c-format\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"将 %2$s 类型的参数 %1$s 写入到注册表失败：%3$ld\"\n\n#, c-format\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"参数 %s 的名称过大，因而无法从注册表读取\"\n\n#, c-format\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"参数 %s 过大，因而无法从注册表读取\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"无法写入配置文件，无法获取家目录路径。\"\n\n#, c-format\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"无法写入配置文件，无法打开 %s：%s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"无法读取配置文件，无法获取家目录路径。\"\n\n#, c-format\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"未知参数 %1$s 于文件 %3$s 的第 %2$d 行\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"无法创建 VNC 家目录：无法获取家目录路径。\"\n\n#~ msgid \"Unknown encoding %d\"\n#~ msgstr \"未知编码 %d\"\n\n#~ msgid \"Unknown encoding\"\n#~ msgstr \"未知编码\"\n\n#~ msgid \"Could not create framebuffer device\"\n#~ msgstr \"无法创建帧缓冲设备\"\n\n#~ msgid \"Could not create framebuffer bitmap\"\n#~ msgstr \"无法创建帧缓冲位图\"\n\n#~ msgid \"Using platform independent framebuffer\"\n#~ msgstr \"使用独立于平台的帧缓冲 (framebuffer)\"\n\n#~ msgid \"unable to create DIB section\"\n#~ msgstr \"无法创建 DIB 会话\"\n\n#~ msgid \"CreateCompatibleDC failed\"\n#~ msgstr \"CreateCompatibleDC 函数失败\"\n\n#~ msgid \"SelectObject failed\"\n#~ msgstr \"SelectObject 函数失败\"\n\n#~ msgid \"BitBlt failed\"\n#~ msgstr \"BitBlt 函数失败\"\n\n#~ msgid \"Display lacks pixmap format for default depth\"\n#~ msgstr \"显示器缺少当前色深需要的像素映射\"\n\n#~ msgid \"Couldn't find suitable pixmap format\"\n#~ msgstr \"找不到合适的像素映射格式\"\n\n#~ msgid \"Only true colour displays supported\"\n#~ msgstr \"仅支持真彩色显示\"\n\n#~ msgid \"Using default colormap and visual, TrueColor, depth %d.\"\n#~ msgstr \"正在使用默认的颜色映射及视觉效果，真彩色，色深 %d。\"\n"
  },
  {
    "path": "po/zh_TW.po",
    "content": "# Chinese (Traditional) translation of tigervnc\n# Copyright (C) 2019 the TigerVNC Team (msgids)\n# This file is distributed under the same license as the tigervnc package.\n#\n# pan93412 <pan93412@gmail.com>, 2019.\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: tigervnc 1.14.90\\n\"\n\"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\\n\"\n\"POT-Creation-Date: 2025-01-14 16:15+0100\\n\"\n\"PO-Revision-Date: 2025-02-02 00:23+0800\\n\"\n\"Last-Translator: Yi-Jyun Pan <pan93412@gmail.com>\\n\"\n\"Language-Team: Chinese (traditional) <zh-l10n@lists.slat.org>\\n\"\n\"Language: zh_TW\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=1; plural=0;\\n\"\n\"X-Bugs: Report translation errors to the Language-Team address.\\n\"\n\"X-Generator: Poedit 3.5\\n\"\n\n#: vncviewer/CConn.cxx:102\n#, c-format\nmsgid \"Connected to socket %s\"\nmsgstr \"已連線到 socket %s\"\n\n#: vncviewer/CConn.cxx:109\n#, c-format\nmsgid \"Connected to host %s port %d\"\nmsgstr \"已連線到主機位址 %s (連線埠 %d)\"\n\n#: vncviewer/CConn.cxx:114\n#, c-format\nmsgid \"\"\n\"Failed to connect to \\\"%s\\\":\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"無法連線至「%s」：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:151\n#, c-format\nmsgid \"Desktop name: %.80s\"\nmsgstr \"桌面名稱：%.80s\"\n\n#: vncviewer/CConn.cxx:154\n#, c-format\nmsgid \"Host: %.80s port: %d\"\nmsgstr \"主機名稱：%.80s 連線埠：%d\"\n\n#: vncviewer/CConn.cxx:158\n#, c-format\nmsgid \"Size: %d x %d\"\nmsgstr \"大小：%d x %d\"\n\n#: vncviewer/CConn.cxx:165\n#, c-format\nmsgid \"Pixel format: %s\"\nmsgstr \"像素格式：%s\"\n\n#: vncviewer/CConn.cxx:170\n#, c-format\nmsgid \"(server default %s)\"\nmsgstr \"（伺服器預設值：%s）\"\n\n#: vncviewer/CConn.cxx:173\n#, c-format\nmsgid \"Requested encoding: %s\"\nmsgstr \"請求的編碼方式：%s\"\n\n#: vncviewer/CConn.cxx:177\n#, c-format\nmsgid \"Last used encoding: %s\"\nmsgstr \"上次使用的編碼方式：%s\"\n\n#: vncviewer/CConn.cxx:181\n#, c-format\nmsgid \"Line speed estimate: %d kbit/s\"\nmsgstr \"估計線速：%d kbit/秒\"\n\n#: vncviewer/CConn.cxx:185\n#, c-format\nmsgid \"Protocol version: %d.%d\"\nmsgstr \"協定版本：%d.%d\"\n\n#: vncviewer/CConn.cxx:189\n#, c-format\nmsgid \"Security method: %s\"\nmsgstr \"安全性方法：%s\"\n\n#: vncviewer/CConn.cxx:250 vncviewer/CConn.cxx:252\nmsgid \"The connection was dropped by the server before the session could be established.\"\nmsgstr \"在工作階段能夠建立前，連線就被伺服器丟棄。\"\n\n#: vncviewer/CConn.cxx:262\n#, c-format\nmsgid \"Authentication failed: %s\"\nmsgstr \"認證失敗：%s\"\n\n#: vncviewer/CConn.cxx:263\n#, c-format\nmsgid \"\"\n\"Failed to authenticate with the server. Reason given by the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"無法通過伺服器認證。伺服器提供的原因：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/CConn.cxx:335\n#, c-format\nmsgid \"SetDesktopSize failed: %d\"\nmsgstr \"執行 SetDesktopSize 失敗：%d\"\n\n#: vncviewer/CConn.cxx:408\nmsgid \"Invalid SetColourMapEntries from server!\"\nmsgstr \"伺服器傳來無效的 SetColourMapEntries！\"\n\n#: vncviewer/CConn.cxx:516\n#, c-format\nmsgid \"Throughput %d kbit/s - changing to quality %d\"\nmsgstr \"輸送量 %d kbit/秒 - 將品質等級變更至 %d\"\n\n#: vncviewer/CConn.cxx:538\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now enabled\"\nmsgstr \"輸送量 %d kbit/秒 - 全彩模式現已啟用\"\n\n#: vncviewer/CConn.cxx:541\n#, c-format\nmsgid \"Throughput %d kbit/s - full color is now disabled\"\nmsgstr \"輸送量 %d kbit/秒 - 全彩模式現已停用\"\n\n#: vncviewer/CConn.cxx:567\n#, c-format\nmsgid \"Using pixel format %s\"\nmsgstr \"使用像素格式 %s\"\n\n#: vncviewer/DesktopWindow.cxx:146\nmsgid \"Invalid geometry specified!\"\nmsgstr \"指定了無效的幾何大小！\"\n\n#: vncviewer/DesktopWindow.cxx:167\nmsgid \"Reducing window size to fit on current monitor\"\nmsgstr \"縮小視窗大小，使之能完全置於目前顯示器中\"\n\n#: vncviewer/DesktopWindow.cxx:646\nmsgid \"Adjusting window size to avoid accidental full-screen request\"\nmsgstr \"調整視窗大小，避免產生意外的全螢幕請求\"\n\n#: vncviewer/DesktopWindow.cxx:694\n#, c-format\nmsgid \"Press %s to open the context menu\"\nmsgstr \"按下 %s 鍵開啟內容選單\"\n\n#: vncviewer/DesktopWindow.cxx:1094 vncviewer/DesktopWindow.cxx:1102\n#: vncviewer/DesktopWindow.cxx:1122\nmsgid \"Failure grabbing keyboard\"\nmsgstr \"擷取鍵盤失敗\"\n\n#: vncviewer/DesktopWindow.cxx:1411\nmsgid \"Invalid screen layout computed for resize request!\"\nmsgstr \"為縮放請求計算的螢幕版面配置無效！\"\n\n#: vncviewer/EmulateMB.cxx:226 vncviewer/EmulateMB.cxx:289\nmsgid \"Invalid state for 3 button emulation\"\nmsgstr \"無效的 3 按鈕模擬狀態\"\n\n#: vncviewer/KeyboardWin32.cxx:242\n#, c-format\nmsgid \"No scan code for extended virtual key 0x%02x\"\nmsgstr \"沒有對應到延伸虛擬代碼 0x%02x 的掃描碼\"\n\n#: vncviewer/KeyboardWin32.cxx:244\n#, c-format\nmsgid \"No scan code for virtual key 0x%02x\"\nmsgstr \"沒有對應到虛擬按鍵 0x%02x 的掃描碼\"\n\n#: vncviewer/KeyboardWin32.cxx:250\n#, c-format\nmsgid \"Invalid scan code 0x%02x\"\nmsgstr \"掃描碼 0x%02x 無效\"\n\n#: vncviewer/KeyboardWin32.cxx:262\n#, c-format\nmsgid \"No symbol for extended virtual key 0x%02x\"\nmsgstr \"沒有對應到延伸虛擬代碼 0x%02x 的符號\"\n\n#: vncviewer/KeyboardWin32.cxx:264\n#, c-format\nmsgid \"No symbol for virtual key 0x%02x\"\nmsgstr \"沒有對應到虛擬按鍵 0x%02x 的符號\"\n\n#: vncviewer/KeyboardWin32.cxx:423\n#, c-format\nmsgid \"Failed to update keyboard LED state: %lu\"\nmsgstr \"更新鍵盤 LED 狀態失敗：%lu\"\n\n#: vncviewer/KeyboardX11.cxx:104\n#, c-format\nmsgid \"No symbol for key code %d (in the current state)\"\nmsgstr \"沒有對應到按鍵代碼 %d 的符號 (目前狀態)\"\n\n#: vncviewer/KeyboardX11.cxx:129\n#, c-format\nmsgid \"Failed to get keyboard LED state: %d\"\nmsgstr \"取得鍵盤 LED 狀態失敗：%d\"\n\n#: vncviewer/KeyboardX11.cxx:174\nmsgid \"Failed to update keyboard LED state\"\nmsgstr \"更新鍵盤 LED 狀態失敗\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:52\n#: vncviewer/MonitorIndicesParameter.cxx:100\nmsgid \"Failed to get system monitor configuration\"\nmsgstr \"無法取得系統顯示器設定\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:79\n#, c-format\nmsgid \"Invalid configuration specified for %s\"\nmsgstr \"為 %s 指定之組態無效\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:86\n#, c-format\nmsgid \"Monitor index %d does not exist\"\nmsgstr \"沒有索引編號是 %d 的顯示器\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:162\n#: vncviewer/MonitorIndicesParameter.cxx:182\n#, c-format\nmsgid \"Invalid monitor index '%s'\"\nmsgstr \"顯示器索引編號「%s」無效\"\n\n#: vncviewer/MonitorIndicesParameter.cxx:170\n#, c-format\nmsgid \"Unexpected character '%c'\"\nmsgstr \"遇到非預期字元「%c」\"\n\n#: vncviewer/OptionsDialog.cxx:64\nmsgid \"TigerVNC options\"\nmsgstr \"TigerVNC 選項\"\n\n#: vncviewer/OptionsDialog.cxx:97 vncviewer/ServerDialog.cxx:107\n#: vncviewer/vncviewer.cxx:397\nmsgid \"Cancel\"\nmsgstr \"取消\"\n\n#: vncviewer/OptionsDialog.cxx:102 vncviewer/vncviewer.cxx:396\nmsgid \"OK\"\nmsgstr \"確認\"\n\n#: vncviewer/OptionsDialog.cxx:514\nmsgid \"Compression\"\nmsgstr \"壓縮模式\"\n\n#: vncviewer/OptionsDialog.cxx:530\nmsgid \"Auto select\"\nmsgstr \"自動選擇\"\n\n#: vncviewer/OptionsDialog.cxx:541\nmsgid \"Preferred encoding\"\nmsgstr \"偏好編碼方式\"\n\n#: vncviewer/OptionsDialog.cxx:602\nmsgid \"Color level\"\nmsgstr \"色彩等級\"\n\n#: vncviewer/OptionsDialog.cxx:614\nmsgid \"Full\"\nmsgstr \"完整\"\n\n#: vncviewer/OptionsDialog.cxx:621\nmsgid \"Medium\"\nmsgstr \"中量\"\n\n#: vncviewer/OptionsDialog.cxx:628\nmsgid \"Low\"\nmsgstr \"少量\"\n\n#: vncviewer/OptionsDialog.cxx:635\nmsgid \"Very low\"\nmsgstr \"極少\"\n\n#: vncviewer/OptionsDialog.cxx:657\nmsgid \"Custom compression level:\"\nmsgstr \"自訂壓縮等級：\"\n\n#: vncviewer/OptionsDialog.cxx:664\nmsgid \"level (0=fast, 9=best)\"\nmsgstr \"級別 (0=速度最快、9=品質最好)\"\n\n#: vncviewer/OptionsDialog.cxx:671\nmsgid \"Allow JPEG compression:\"\nmsgstr \"允許 JPEG 壓縮方式：\"\n\n#: vncviewer/OptionsDialog.cxx:678\nmsgid \"quality (0=poor, 9=best)\"\nmsgstr \"品質 (0=最低、9=最好)\"\n\n#: vncviewer/OptionsDialog.cxx:689\nmsgid \"Security\"\nmsgstr \"安全性\"\n\n#: vncviewer/OptionsDialog.cxx:703\nmsgid \"Encryption\"\nmsgstr \"加密方式\"\n\n#: vncviewer/OptionsDialog.cxx:715 vncviewer/OptionsDialog.cxx:782\n#: vncviewer/OptionsDialog.cxx:905\nmsgid \"None\"\nmsgstr \"無\"\n\n#: vncviewer/OptionsDialog.cxx:722\nmsgid \"TLS with anonymous certificates\"\nmsgstr \"使用匿名憑證的 TLS\"\n\n#: vncviewer/OptionsDialog.cxx:728\nmsgid \"TLS with X509 certificates\"\nmsgstr \"使用 X509 憑證的 TLS\"\n\n#: vncviewer/OptionsDialog.cxx:735\nmsgid \"Path to X509 CA certificate\"\nmsgstr \"X509 CA 憑證位置\"\n\n#: vncviewer/OptionsDialog.cxx:742\nmsgid \"Path to X509 CRL file\"\nmsgstr \"X509 CRL 檔案位置\"\n\n#: vncviewer/OptionsDialog.cxx:770\nmsgid \"Authentication\"\nmsgstr \"認證方式\"\n\n#: vncviewer/OptionsDialog.cxx:788\nmsgid \"Standard VNC (insecure without encryption)\"\nmsgstr \"標準 VNC 認證方式 (若未開啟加密功能則不安全)\"\n\n#: vncviewer/OptionsDialog.cxx:794\nmsgid \"Username and password (insecure without encryption)\"\nmsgstr \"使用者與密碼認證方式 (若未開啟加密功能則不安全)\"\n\n#: vncviewer/OptionsDialog.cxx:822\nmsgid \"Input\"\nmsgstr \"輸入\"\n\n#: vncviewer/OptionsDialog.cxx:835\nmsgid \"View only (ignore mouse and keyboard)\"\nmsgstr \"僅供檢視模式 (忽略滑鼠與鍵盤動作)\"\n\n#: vncviewer/OptionsDialog.cxx:842\nmsgid \"Mouse\"\nmsgstr \"滑鼠\"\n\n#: vncviewer/OptionsDialog.cxx:854\nmsgid \"Emulate middle mouse button\"\nmsgstr \"模擬滑鼠中鍵\"\n\n#: vncviewer/OptionsDialog.cxx:860\nmsgid \"Show local cursor when not provided by server\"\nmsgstr \"如果伺服器沒有提供游標，則顯示本機游標\"\n\n#: vncviewer/OptionsDialog.cxx:865\nmsgid \"Cursor type\"\nmsgstr \"游標類型\"\n\n#: vncviewer/OptionsDialog.cxx:867\nmsgid \"Dot\"\nmsgstr \"點狀\"\n\n#: vncviewer/OptionsDialog.cxx:868\nmsgid \"System\"\nmsgstr \"系統\"\n\n#: vncviewer/OptionsDialog.cxx:888\nmsgid \"Keyboard\"\nmsgstr \"鍵盤\"\n\n#: vncviewer/OptionsDialog.cxx:900\nmsgid \"Pass system keys directly to server (full screen)\"\nmsgstr \"直接將系統鍵傳至伺服器 (全螢幕模式)\"\n\n#: vncviewer/OptionsDialog.cxx:903\nmsgid \"Menu key\"\nmsgstr \"選單鍵\"\n\n#: vncviewer/OptionsDialog.cxx:926\nmsgid \"Clipboard\"\nmsgstr \"剪貼板\"\n\n#: vncviewer/OptionsDialog.cxx:938\nmsgid \"Accept clipboard from server\"\nmsgstr \"接受來自伺服器的剪貼簿內容\"\n\n#: vncviewer/OptionsDialog.cxx:946\nmsgid \"Also set primary selection\"\nmsgstr \"亦設定主要選區\"\n\n#: vncviewer/OptionsDialog.cxx:953\nmsgid \"Send clipboard to server\"\nmsgstr \"將剪貼簿內容傳至伺服器\"\n\n#: vncviewer/OptionsDialog.cxx:961\nmsgid \"Send primary selection as clipboard\"\nmsgstr \"將主要選取區塊作為剪貼簿內容傳送\"\n\n#: vncviewer/OptionsDialog.cxx:982\nmsgid \"Display\"\nmsgstr \"顯示\"\n\n#: vncviewer/OptionsDialog.cxx:996\nmsgid \"Display mode\"\nmsgstr \"顯示模式\"\n\n#: vncviewer/OptionsDialog.cxx:1009\nmsgid \"Windowed\"\nmsgstr \"視窗模式\"\n\n#: vncviewer/OptionsDialog.cxx:1017\nmsgid \"Full screen on current monitor\"\nmsgstr \"在目前顯示器全螢幕\"\n\n#: vncviewer/OptionsDialog.cxx:1025\nmsgid \"Full screen on all monitors\"\nmsgstr \"在所有顯示器全螢幕\"\n\n#: vncviewer/OptionsDialog.cxx:1033\nmsgid \"Full screen on selected monitor(s)\"\nmsgstr \"在選取顯示器全螢幕\"\n\n#: vncviewer/OptionsDialog.cxx:1062\nmsgid \"Miscellaneous\"\nmsgstr \"雜項設定\"\n\n#: vncviewer/OptionsDialog.cxx:1070\nmsgid \"Shared (don't disconnect other viewers)\"\nmsgstr \"共用連線 (不斷開其他檢視器的連線)\"\n\n#: vncviewer/OptionsDialog.cxx:1076\nmsgid \"Ask to reconnect on connection errors\"\nmsgstr \"詢問是否要在連接發生錯誤時重新連線\"\n\n#: vncviewer/ServerDialog.cxx:63\nmsgid \"VNC viewer: Connection details\"\nmsgstr \"VNC 檢視器：連線詳細資訊\"\n\n#: vncviewer/ServerDialog.cxx:73\nmsgid \"VNC server:\"\nmsgstr \"VNC 伺服器：\"\n\n#: vncviewer/ServerDialog.cxx:80\nmsgid \"Options...\"\nmsgstr \"選項…\"\n\n#: vncviewer/ServerDialog.cxx:84\nmsgid \"Load...\"\nmsgstr \"載入…\"\n\n#: vncviewer/ServerDialog.cxx:88\nmsgid \"Save as...\"\nmsgstr \"另存新檔...\"\n\n#: vncviewer/ServerDialog.cxx:102\nmsgid \"About...\"\nmsgstr \"關於…\"\n\n#: vncviewer/ServerDialog.cxx:111\nmsgid \"Connect\"\nmsgstr \"連線\"\n\n#: vncviewer/ServerDialog.cxx:147\n#, c-format\nmsgid \"\"\n\"Unable to load the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"無法載入伺服器歷史記錄：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:176 vncviewer/ServerDialog.cxx:216\nmsgid \"TigerVNC configuration (*.tigervnc)\"\nmsgstr \"TigerVNC 組態設定 (*.tigervnc)\"\n\n#: vncviewer/ServerDialog.cxx:177\nmsgid \"Select a TigerVNC configuration file\"\nmsgstr \"請選取 TigerVNC 組態設定檔\"\n\n#: vncviewer/ServerDialog.cxx:199 vncviewer/vncviewer.cxx:517\n#, c-format\nmsgid \"\"\n\"Unable to load the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"無法載入指定設定檔：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:217\nmsgid \"Save the TigerVNC configuration to file\"\nmsgstr \"將 TigerVNC 組態設定儲存為檔案\"\n\n#: vncviewer/ServerDialog.cxx:243\n#, c-format\nmsgid \"%s already exists. Do you want to overwrite?\"\nmsgstr \"%s 已存在，是否覆寫？\"\n\n#: vncviewer/ServerDialog.cxx:244 vncviewer/vncviewer.cxx:394\nmsgid \"No\"\nmsgstr \"否\"\n\n#: vncviewer/ServerDialog.cxx:244\nmsgid \"Overwrite\"\nmsgstr \"覆寫\"\n\n#: vncviewer/ServerDialog.cxx:260\n#, c-format\nmsgid \"\"\n\"Unable to save the specified configuration file:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"無法儲存指定設定檔：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:294\n#, c-format\nmsgid \"\"\n\"Unable to save the default configuration:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"無法儲存預設設定檔：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:306\n#, c-format\nmsgid \"\"\n\"Unable to save the server history:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"無法儲存伺服器歷程記錄：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/ServerDialog.cxx:351 vncviewer/ServerDialog.cxx:429\n#: vncviewer/vncviewer.cxx:580\nmsgid \"Could not determine VNC state directory path\"\nmsgstr \"無法決定 VNC 狀態目錄的路徑\"\n\n#: vncviewer/ServerDialog.cxx:363 vncviewer/ServerDialog.cxx:437\n#: vncviewer/parameters.cxx:671 vncviewer/parameters.cxx:752\n#, c-format\nmsgid \"Could not open \\\"%s\\\"\"\nmsgstr \"無法開啟「%s」\"\n\n#: vncviewer/ServerDialog.cxx:378 vncviewer/ServerDialog.cxx:387\n#: vncviewer/parameters.cxx:766 vncviewer/parameters.cxx:773\n#: vncviewer/parameters.cxx:807 vncviewer/parameters.cxx:837\n#: vncviewer/parameters.cxx:844\n#, c-format\nmsgid \"Failed to read line %d in file \\\"%s\\\"\"\nmsgstr \"無法讀取「%2$s」檔案的第 %1$d 列\"\n\n#: vncviewer/ServerDialog.cxx:390 vncviewer/parameters.cxx:776\nmsgid \"Line too long\"\nmsgstr \"行字數過長\"\n\n#: vncviewer/UserDialog.cxx:123\nmsgid \"Opening password file failed\"\nmsgstr \"開啟密碼檔失敗\"\n\n#: vncviewer/UserDialog.cxx:143\nmsgid \"VNC authentication\"\nmsgstr \"VNC 認證\"\n\n#: vncviewer/UserDialog.cxx:150\nmsgid \"This connection is secure\"\nmsgstr \"此連線階段安全\"\n\n#: vncviewer/UserDialog.cxx:154\nmsgid \"This connection is not secure\"\nmsgstr \"此連線階段不安全\"\n\n#: vncviewer/UserDialog.cxx:176\nmsgid \"Username:\"\nmsgstr \"使用者名稱：\"\n\n#: vncviewer/UserDialog.cxx:189\nmsgid \"Password:\"\nmsgstr \"密碼：\"\n\n#: vncviewer/UserDialog.cxx:197\nmsgid \"Keep password for reconnect\"\nmsgstr \"留存密碼供重新連線使用\"\n\n#: vncviewer/Viewport.cxx:695\nmsgctxt \"ContextMenu|\"\nmsgid \"Disconn&ect\"\nmsgstr \"中斷連線(&E)\"\n\n#: vncviewer/Viewport.cxx:698\nmsgctxt \"ContextMenu|\"\nmsgid \"&Full screen\"\nmsgstr \"全螢幕(&F)\"\n\n#: vncviewer/Viewport.cxx:701\nmsgctxt \"ContextMenu|\"\nmsgid \"Minimi&ze\"\nmsgstr \"最小化(&Z)\"\n\n#: vncviewer/Viewport.cxx:703\nmsgctxt \"ContextMenu|\"\nmsgid \"Resize &window to session\"\nmsgstr \"將視窗縮放至與連線階段同大小(&W)\"\n\n#: vncviewer/Viewport.cxx:708\nmsgctxt \"ContextMenu|\"\nmsgid \"&Ctrl\"\nmsgstr \"&Ctrl\"\n\n#: vncviewer/Viewport.cxx:711\nmsgctxt \"ContextMenu|\"\nmsgid \"&Alt\"\nmsgstr \"&Alt\"\n\n#: vncviewer/Viewport.cxx:717\n#, c-format\nmsgctxt \"ContextMenu|\"\nmsgid \"Send %s\"\nmsgstr \"傳送 %s 鍵\"\n\n#: vncviewer/Viewport.cxx:724\nmsgctxt \"ContextMenu|\"\nmsgid \"Send Ctrl-Alt-&Del\"\nmsgstr \"傳送 Ctrl-Alt-&Del 鍵\"\n\n#: vncviewer/Viewport.cxx:727\nmsgctxt \"ContextMenu|\"\nmsgid \"&Refresh screen\"\nmsgstr \"重新整理螢幕(&R)\"\n\n#: vncviewer/Viewport.cxx:730\nmsgctxt \"ContextMenu|\"\nmsgid \"&Options...\"\nmsgstr \"選項(&O)…\"\n\n#: vncviewer/Viewport.cxx:732\nmsgctxt \"ContextMenu|\"\nmsgid \"Connection &info...\"\nmsgstr \"連線資訊(&I)…\"\n\n#: vncviewer/Viewport.cxx:734\nmsgctxt \"ContextMenu|\"\nmsgid \"About &TigerVNC viewer...\"\nmsgstr \"關於 TigerVNC 檢視器(&T)…\"\n\n#: vncviewer/Viewport.cxx:830\nmsgid \"VNC connection info\"\nmsgstr \"VNC 連線資訊\"\n\n#: vncviewer/Win32TouchHandler.cxx:48\nmsgid \"Window is registered for touch instead of gestures\"\nmsgstr \"視窗已被註冊用來接收觸控（而非手勢）操作\"\n\n#: vncviewer/Win32TouchHandler.cxx:83\n#, c-format\nmsgid \"Failed to set gesture configuration (error 0x%x)\"\nmsgstr \"無法設定手勢設定（錯誤 0x%x）\"\n\n#: vncviewer/Win32TouchHandler.cxx:95\n#, c-format\nmsgid \"Failed to get gesture information (error 0x%x)\"\nmsgstr \"無法取得手勢資訊（錯誤 0x%x）\"\n\n#: vncviewer/Win32TouchHandler.cxx:360\n#, c-format\nmsgid \"Invalid mouse button %d, must be a number between 1 and 7.\"\nmsgstr \"無效的滑鼠按鍵編號 %d，必須是介於 1 到 7 之間的數字。\"\n\n#: vncviewer/Win32TouchHandler.cxx:425\n#, c-format\nmsgid \"Unhandled key 0x%x - can't generate keyboard event.\"\nmsgstr \"未接管的按鍵 0x%x - 無法產生鍵盤事件。\"\n\n#: vncviewer/XInputTouchHandler.cxx:102 vncviewer/touch.cxx:107\n#, c-format\nmsgid \"Unable to get X Input 2 event mask for window 0x%08lx\"\nmsgstr \"無法取得視窗 0x%08lx 的 X Input 2 事件遮罩\"\n\n#: vncviewer/XInputTouchHandler.cxx:104\n#, c-format\nmsgid \"Window 0x%08lx has no X Input 2 event mask\"\nmsgstr \"視窗 0x%08lx 沒有 X Input 2 事件遮罩\"\n\n#: vncviewer/XInputTouchHandler.cxx:112 vncviewer/touch.cxx:114\n#, c-format\nmsgid \"Window 0x%08lx has more than one X Input 2 event mask\"\nmsgstr \"視窗 0x%08lx 有超過一個 X Input 2 事件遮罩\"\n\n#: vncviewer/XInputTouchHandler.cxx:143\n#, c-format\nmsgid \"Failure grabbing device %i\"\nmsgstr \"擷取裝置 %i 失敗\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:13\nmsgid \"TigerVNC Viewer\"\nmsgstr \"TigerVNC 檢視器\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:14\n#: vncviewer/vncviewer.desktop.in.in:5\nmsgid \"Connect to VNC server and display remote desktop\"\nmsgstr \"連線到 VNC 伺服器並顯示遠端桌面\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:17\nmsgid \"Virtual Network Computing (VNC) is a remote display system that allows you to view and interact with a virtual desktop environment running on another computer on the network. Using VNC, you can run graphical applications on a remote machine and send only the display from these applications to your local device. This package contains a client which will enable you to connect to other desktops running a VNC server. VNC is platform-independent and supports various operating systems and architectures as both servers and clients.\"\nmsgstr \"Virtual Network Computing (VNC) 是個遠端顯示系統，讓您能檢視網路上其他電腦的虛擬桌面環境並與之互動。您可以使用 VNC 來執行圖形化的應用程式，並只回傳這些應用程式的顯示畫面到您的本地裝置。本套件包含 VNC 用戶端，讓您可以連線到其他執行著 VNC 伺服器的桌面。VNC 不受平台侷限，無論是伺服器還是用戶端，都支援各種作業系統和架構。\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:23\nmsgid \"TigerVNC is a high-speed version of VNC based on the RealVNC 4 and X.org code bases. TigerVNC started as a next-generation development effort for TightVNC on Unix and Linux platforms, but it split from its parent project in early 2009 so that TightVNC could focus on Windows platforms. TigerVNC supports a variant of Tight encoding that is greatly accelerated by the use of the libjpeg-turbo JPEG codec.\"\nmsgstr \"TigerVNC 是以 RealVNC 4 和 X.org 程式碼為基礎打造的 VNC 高速版本。TigerVNC 原先是 TightVNC 在 Unix 和 Linux 平台上的下一代開發成果，但在 2009 年初從原本的專案中分離，讓 TigerVNC 得以專注在 Windows 平台上。TigerVNC 支援 Tight 編碼的變體版本，透過 libjpeg-turbo JPEG 編解碼器，使其速度獲得相當大的提升。\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:33\nmsgid \"TigerVNC viewer connection to a CentOS machine\"\nmsgstr \"連線至 CentOS 機器的 TigerVNC 檢視器\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:37\nmsgid \"TigerVNC viewer connection to a macOS machine\"\nmsgstr \"連線至 macOS 機器的 TigerVNC 檢視器\"\n\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:41\nmsgid \"TigerVNC viewer connection to a Windows machine\"\nmsgstr \"連線至 Windows 機器的 TigerVNC 檢視器\"\n\n#. developer_name tag deprecated with Appstream 1.0\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:46\n#: vncviewer/org.tigervnc.vncviewer.metainfo.xml.in:48\nmsgid \"The TigerVNC team\"\nmsgstr \"TigerVNC 團隊\"\n\n#: vncviewer/parameters.cxx:319 vncviewer/parameters.cxx:344\n#: vncviewer/parameters.cxx:361 vncviewer/parameters.cxx:401\n#: vncviewer/parameters.cxx:421\nmsgid \"The name of the parameter is too large\"\nmsgstr \"參數名稱過長\"\n\n#: vncviewer/parameters.cxx:323 vncviewer/parameters.cxx:328\n#: vncviewer/parameters.cxx:379\nmsgid \"The parameter is too large\"\nmsgstr \"參數過長\"\n\n#: vncviewer/parameters.cxx:386 vncviewer/parameters.cxx:712\n#: vncviewer/parameters.cxx:822\nmsgid \"Invalid format or too large value\"\nmsgstr \"格式無效或數值過大\"\n\n#: vncviewer/parameters.cxx:440 vncviewer/parameters.cxx:473\nmsgid \"Failed to create registry key\"\nmsgstr \"無法建立登錄機碼\"\n\n#: vncviewer/parameters.cxx:461 vncviewer/parameters.cxx:528\n#: vncviewer/parameters.cxx:571 vncviewer/parameters.cxx:638\nmsgid \"Failed to close registry key\"\nmsgstr \"無法關閉登錄機碼\"\n\n#: vncviewer/parameters.cxx:479 vncviewer/parameters.cxx:506\n#: vncviewer/parameters.cxx:680 vncviewer/parameters.cxx:692\n#, c-format\nmsgid \"Failed to save \\\"%s\\\": %s\"\nmsgstr \"無法儲存「%s」：%s\"\n\n#: vncviewer/parameters.cxx:489 vncviewer/parameters.cxx:520\n#, c-format\nmsgid \"Failed to remove \\\"%s\\\": %s\"\nmsgstr \"無法移除「%s」：%s\"\n\n#: vncviewer/parameters.cxx:544 vncviewer/parameters.cxx:616\nmsgid \"Failed to open registry key\"\nmsgstr \"無法開啟登錄機碼\"\n\n#: vncviewer/parameters.cxx:561\n#, c-format\nmsgid \"Failed to read server history entry %d: %s\"\nmsgstr \"無法讀取伺服器歷史記錄的第 %d 條項目：%s\"\n\n#: vncviewer/parameters.cxx:597 vncviewer/parameters.cxx:627\n#, c-format\nmsgid \"Failed to read parameter \\\"%s\\\": %s\"\nmsgstr \"無法讀取「%s」參數：%s\"\n\n#: vncviewer/parameters.cxx:661 vncviewer/parameters.cxx:740\n#: vncviewer/vncviewer.cxx:546\nmsgid \"Could not determine VNC config directory path\"\nmsgstr \"無法決定 VNC 組態目錄的路徑\"\n\n#: vncviewer/parameters.cxx:682 vncviewer/parameters.cxx:694\nmsgid \"Could not encode parameter\"\nmsgstr \"無法對參數進行編碼\"\n\n#: vncviewer/parameters.cxx:785\n#, c-format\nmsgid \"Configuration file %s is in an invalid format\"\nmsgstr \"組態檔案 %s 格式無效\"\n\n#: vncviewer/parameters.cxx:809\nmsgid \"Invalid format\"\nmsgstr \"格式無效\"\n\n#: vncviewer/parameters.cxx:846\nmsgid \"Unknown parameter\"\nmsgstr \"未知參數\"\n\n#: vncviewer/touch.cxx:75\n#, c-format\nmsgid \"Got message (0x%x) for an unhandled window\"\nmsgstr \"收到對未處理視窗的訊息 (0x%x)\"\n\n#: vncviewer/touch.cxx:138 vncviewer/touch.cxx:160\n#, c-format\nmsgid \"Invalid window 0x%08lx specified for pointer grab\"\nmsgstr \"指定要擷取指標的視窗 0x%08lx 無效\"\n\n#: vncviewer/touch.cxx:183 vncviewer/touch.cxx:184\n#, c-format\nmsgid \"Failed to create touch handler: %s\"\nmsgstr \"無法建立觸控處理常式：%s\"\n\n#: vncviewer/touch.cxx:188\n#, c-format\nmsgid \"Couldn't attach event handler to window (error 0x%x)\"\nmsgstr \"無法將事件處理常式連接到視窗上（錯誤 0x%x）\"\n\n#: vncviewer/touch.cxx:215\nmsgid \"Failed to get event data for X Input event\"\nmsgstr \"無法取得 X Input 事件資料\"\n\n#: vncviewer/touch.cxx:228\nmsgid \"X Input event for unknown window\"\nmsgstr \"未知視窗的 X Input 事件\"\n\n#: vncviewer/touch.cxx:254\nmsgid \"X Input extension not available.\"\nmsgstr \"不支援 X Input 擴充方法。\"\n\n#: vncviewer/touch.cxx:261\nmsgid \"X Input 2 (or newer) is not available.\"\nmsgstr \"不支援 X Input 2（或新版）。\"\n\n#: vncviewer/touch.cxx:266\nmsgid \"X Input 2.2 (or newer) is not available. Touch gestures will not be supported.\"\nmsgstr \"不支援 X Input 2.2（或新版）。將不支援觸控手勢。\"\n\n#: vncviewer/vncviewer.cxx:104\n#, c-format\nmsgid \"\"\n\"TigerVNC viewer v%s\\n\"\n\"Built on: %s\\n\"\n\"Copyright (C) 1999-%d TigerVNC team and many others (see README.rst)\\n\"\n\"See https://www.tigervnc.org for information on TigerVNC.\"\nmsgstr \"\"\n\"TigerVNC 檢視器 v%s\\n\"\n\"編譯時間：%s\\n\"\n\"著作權所有 (C) 1999-%d TigerVNC 團隊以及其他人 (詳閱 README.rst)\\n\"\n\"前往 https://www.tigervnc.org 取得 TigerVNC 的相關資訊。\"\n\n#: vncviewer/vncviewer.cxx:158\n#, c-format\nmsgid \"\"\n\"An unexpected error occurred when communicating with the server:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"與伺服器通訊時發生非預期的錯誤：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:174\nmsgid \"About TigerVNC Viewer\"\nmsgstr \"關於 TigerVNC 檢視器\"\n\n#: vncviewer/vncviewer.cxx:195\nmsgid \"Internal FLTK error. Exiting.\"\nmsgstr \"內部 FLTK 錯誤。退出。\"\n\n#: vncviewer/vncviewer.cxx:214\n#, c-format\nmsgid \"\"\n\"%s\\n\"\n\"\\n\"\n\"Attempt to reconnect?\"\nmsgstr \"\"\n\"%s\\n\"\n\"\\n\"\n\"是否嘗試重新連線？\"\n\n#: vncviewer/vncviewer.cxx:245 vncviewer/vncviewer.cxx:257\n#, c-format\nmsgid \"Error starting new TigerVNC Viewer: %s\"\nmsgstr \"啟動新的 TigerVNC 檢視器時發生錯誤：%s\"\n\n#: vncviewer/vncviewer.cxx:266\n#, c-format\nmsgid \"Termination signal %d has been received. TigerVNC viewer will now exit.\"\nmsgstr \"接收到終止信號 %d。TigerVNC 檢視器現將結束。\"\n\n#: vncviewer/vncviewer.cxx:391 vncviewer/vncviewer.desktop.in.in:3\nmsgid \"TigerVNC viewer\"\nmsgstr \"TigerVNC 檢視器\"\n\n#: vncviewer/vncviewer.cxx:395\nmsgid \"Yes\"\nmsgstr \"確認\"\n\n#: vncviewer/vncviewer.cxx:398\nmsgid \"Close\"\nmsgstr \"關閉\"\n\n#: vncviewer/vncviewer.cxx:403\nmsgid \"About\"\nmsgstr \"關於\"\n\n#: vncviewer/vncviewer.cxx:406\nmsgid \"Hide\"\nmsgstr \"隱藏\"\n\n#: vncviewer/vncviewer.cxx:409\nmsgid \"Quit\"\nmsgstr \"關閉\"\n\n#: vncviewer/vncviewer.cxx:413\nmsgid \"Services\"\nmsgstr \"服務\"\n\n#: vncviewer/vncviewer.cxx:414\nmsgid \"Hide others\"\nmsgstr \"隱藏其他\"\n\n#: vncviewer/vncviewer.cxx:415\nmsgid \"Show all\"\nmsgstr \"全部顯示\"\n\n#: vncviewer/vncviewer.cxx:424\nmsgctxt \"SysMenu|\"\nmsgid \"&File\"\nmsgstr \"檔案(&F)\"\n\n#: vncviewer/vncviewer.cxx:427\nmsgctxt \"SysMenu|File|\"\nmsgid \"&New Connection\"\nmsgstr \"建立新連線(&N)\"\n\n#: vncviewer/vncviewer.cxx:450\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Usage: %s [parameters] [host][:displayNum]\\n\"\n\"       %s [parameters] [host][::port]\\n\"\n\"       %s [parameters] [unix socket]\\n\"\n\"       %s [parameters] -listen [port]\\n\"\n\"       %s [parameters] [.tigervnc file]\\n\"\nmsgstr \"\"\n\"\\n\"\n\"用法：%s [參數] [主機][:顯示器編號]\\n\"\n\"      %s [參數] [主機][::通訊埠]\\n\"\n\"      %s [參數] [unix 通訊端]\\n\"\n\"      %s [參數] -listen [通訊埠]\\n\"\n\"      %s [參數] [.tigervnc 檔案]\\n\"\n\n#: vncviewer/vncviewer.cxx:465\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Options:\\n\"\n\"\\n\"\n\"  -display Xdisplay  - Specifies the X display for the viewer window\\n\"\n\"  -geometry geometry - Initial position of the main VNC viewer window. See the\\n\"\n\"                       man page for details.\\n\"\nmsgstr \"\"\n\"\\n\"\n\"選項：\\n\"\n\"\\n\"\n\"  -display Xdisplay  - 指定檢視器視窗的 X 顯示器\\n\"\n\"  -geometry geometry - 設定 VNC 檢視器主視窗的初始位置。\\n\"\n\"                       詳細資訊請參閱 man 頁面。\\n\"\n\n#: vncviewer/vncviewer.cxx:472\n#, c-format\nmsgid \"\"\n\"\\n\"\n\"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n\"Parameters which take a value can be specified as -<param> <value>\\n\"\n\"Other valid forms are <param>=<value> -<param>=<value> --<param>=<value>\\n\"\n\"Parameter names are case-insensitive.  The parameters are:\\n\"\n\"\\n\"\nmsgstr \"\"\n\"\\n\"\n\"參數可用 -<param> 開啟，或用 -<param>=0 關閉\\n\"\n\"需要指定數值的參數可使用 -<param> <value> 的格式\\n\"\n\"其他有效格式包括 <param>=<value> -<param>=<value> —<param>=<value>\\n\"\n\"參數名稱不分大小寫。可用的參數如下：\\n\"\n\"\\n\"\n\n#: vncviewer/vncviewer.cxx:527\nmsgid \"FullScreenAllMonitors is deprecated, set FullScreenMode to 'all' instead\"\nmsgstr \"已棄用 FullScreenAllMonitors，請改設定 FullScreenMode 為 'all'\"\n\n#: vncviewer/vncviewer.cxx:532\nmsgid \"DotWhenNoCursor is deprecated, set AlwaysCursor to 1 and CursorType to 'Dot' instead\"\nmsgstr \"DotWhenNoCursor 選項已經過時，請改將 AlwaysCursor 設為 1，然後將 CursorType 設為「Dot」（點狀）\"\n\n#: vncviewer/vncviewer.cxx:553\nmsgid \"~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.\"\nmsgstr \"~/.vnc 已廢棄，請查閱「man vncviewer」了解可以遷移到的路徑。\"\n\n#: vncviewer/vncviewer.cxx:557\n#, c-format\nmsgid \"%%APPDATA%%\\\\vnc is deprecated, please switch to the %%APPDATA%%\\\\TigerVNC location.\"\nmsgstr \"%%APPDATA%%\\\\vnc 已廢棄，請改到 %%APPDATA%%\\\\TigerVNC 位置。\"\n\n#: vncviewer/vncviewer.cxx:562\n#, c-format\nmsgid \"Could not create VNC config directory \\\"%s\\\": %s\"\nmsgstr \"無法建立 VNC 組態目錄「%s」：%s\"\n\n#: vncviewer/vncviewer.cxx:568\nmsgid \"Could not determine VNC data directory path\"\nmsgstr \"無法決定 VNC 資料目錄的路徑\"\n\n#: vncviewer/vncviewer.cxx:574\n#, c-format\nmsgid \"Could not create VNC data directory \\\"%s\\\": %s\"\nmsgstr \"無法建立 VNC 資料目錄「%s」：%s\"\n\n#: vncviewer/vncviewer.cxx:586\n#, c-format\nmsgid \"Could not create VNC state directory \\\"%s\\\": %s\"\nmsgstr \"無法建立 VNC 狀態目錄「%s」：%s\"\n\n#: vncviewer/vncviewer.cxx:703\n#, c-format\nmsgid \"%s: Unrecognized option '%s'\\n\"\nmsgstr \"%s：不認識選項「%s」\\n\"\n\n#: vncviewer/vncviewer.cxx:705 vncviewer/vncviewer.cxx:713\n#, c-format\nmsgid \"See '%s --help' for more information.\\n\"\nmsgstr \"參閱「%s --help」深入了解。\\n\"\n\n#: vncviewer/vncviewer.cxx:712\n#, c-format\nmsgid \"%s: Extra argument '%s'\\n\"\nmsgstr \"%s：發現多餘引數「%s」\\n\"\n\n#. TRANSLATORS: \"Parameters\" are command line arguments, or settings\n#. from a file or the Windows registry.\n#: vncviewer/vncviewer.cxx:748 vncviewer/vncviewer.cxx:749\nmsgid \"Parameters -listen and -via are incompatible\"\nmsgstr \"-listen 與 -via 參數不相容\"\n\n#: vncviewer/vncviewer.cxx:763\nmsgid \"Unable to listen for incoming connections\"\nmsgstr \"無法監聽連入連線\"\n\n#: vncviewer/vncviewer.cxx:765\n#, c-format\nmsgid \"Listening on port %d\"\nmsgstr \"正於 %d 連線埠監聽\"\n\n#: vncviewer/vncviewer.cxx:794\n#, c-format\nmsgid \"\"\n\"Failure waiting for incoming VNC connection:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"等待連入 VNC 連線時發生錯誤：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.cxx:815\n#, c-format\nmsgid \"\"\n\"Failure setting up encrypted tunnel:\\n\"\n\"\\n\"\n\"%s\"\nmsgstr \"\"\n\"無法設定加密隧道：\\n\"\n\"\\n\"\n\"%s\"\n\n#: vncviewer/vncviewer.desktop.in.in:4\nmsgid \"Remote desktop viewer\"\nmsgstr \"遠端桌面檢視器\"\n\n#~ msgid \"Show dot when no cursor\"\n#~ msgstr \"若無游標則改顯示一個點\"\n\n#, c-format\n#~ msgid \"Failed to update keyboard LED state: %d\"\n#~ msgstr \"更新鍵盤 LED 狀態失敗：%d\"\n\n#~ msgid \"No key code specified on key press\"\n#~ msgstr \"沒有指定按下按鍵事件的按鍵代碼\"\n\n#, c-format\n#~ msgid \"No symbol for key code 0x%02x (in the current state)\"\n#~ msgstr \"沒有對應到按鍵代碼 0x%02x 的符號 (目前狀態)\"\n\n#~ msgid \"Unknown parameter type\"\n#~ msgstr \"參數類型未知\"\n\n#~ msgid \"VNC Viewer: Connection Options\"\n#~ msgstr \"VNC 檢視器：連線設定\"\n\n#~ msgid \"Misc.\"\n#~ msgstr \"雜項設定\"\n\n#~ msgid \"Failed to get monitor name because X11 RandR could not be found\"\n#~ msgstr \"因找不到 X11 RandR 而無法取得顯示器名稱\"\n\n#~ msgid \"Failed to get information about CRTC %d\"\n#~ msgstr \"無法取得 CRTC %d 的資訊\"\n\n#~ msgid \"Failed to get information about output %d for CRTC %d\"\n#~ msgstr \"無法取得 CRTC %2$d 輸出 %1$d 的資訊\"\n\n#~ msgid \"Screen\"\n#~ msgstr \"螢幕\"\n\n#~ msgid \"Resize remote session on connect\"\n#~ msgstr \"連線時調整遠端階段的大小\"\n\n#~ msgid \"Resize remote session to the local window\"\n#~ msgstr \"將遠端階段縮放至與本機視窗同大小\"\n\n#~ msgid \"Enable full-screen\"\n#~ msgstr \"啟用全螢幕\"\n\n#~ msgid \"Full (all available colors)\"\n#~ msgstr \"全彩 (所有可顯示的顏色)\"\n\n#~ msgid \"Medium (256 colors)\"\n#~ msgstr \"中等 (256 色)\"\n\n#~ msgid \"Low (64 colors)\"\n#~ msgstr \"較少 (64 色)\"\n\n#~ msgid \"Very low (8 colors)\"\n#~ msgstr \"極少 (8 色)\"\n\n#~ msgid \"level (1=fast, 6=best [4-6 are rarely useful])\"\n#~ msgstr \"等級 (1=壓縮最快、6=大小最小 [4-6 可用性較低])\"\n\n#~ msgid \"Full-screen mode\"\n#~ msgstr \"全螢幕模式\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"E&xit viewer\"\n#~ msgstr \"退出檢視器(&X)\"\n\n#~ msgctxt \"ContextMenu|\"\n#~ msgid \"Dismiss &menu\"\n#~ msgstr \"關閉選單(&M)\"\n\n#~ msgid \"Failed to write parameter %s of type %s to the registry: %ld\"\n#~ msgstr \"寫入參數 %s (類型 %s) 至登錄表失敗：%ld\"\n\n#~ msgid \"The name of the parameter %s was too large to read from the registry\"\n#~ msgstr \"參數 %s 之名稱過長以至於無法從登錄表讀取\"\n\n#~ msgid \"The parameter %s was too large to read from the registry\"\n#~ msgstr \"參數 %s 過長以至於無法從登錄表讀取\"\n\n#~ msgid \"Failed to write configuration file, can't obtain home directory path.\"\n#~ msgstr \"寫入組態檔案失敗，無法取得家目錄路徑。\"\n\n#~ msgid \"Failed to write configuration file, can't open %s: %s\"\n#~ msgstr \"寫入組態檔案失敗，無法開啟 %s：%s\"\n\n#~ msgid \"Failed to read configuration file, can't obtain home directory path.\"\n#~ msgstr \"讀取組態檔案失敗，無法取得家目錄路徑。\"\n\n#~ msgid \"Unknown parameter %s on line %d in file %s\"\n#~ msgstr \"檔案 %s 中第 %d 行發現不明參數 %s\"\n\n#~ msgid \"Could not create VNC home directory: can't obtain home directory path.\"\n#~ msgstr \"無法建立 VNC 家目錄：無法取得家目錄路徑。\"\n\n#~ msgid \"tigervnc\"\n#~ msgstr \"tigervnc\"\n\n#~ msgid \"Enabling continuous updates\"\n#~ msgstr \"啟用持續更新功能\"\n\n#~ msgid \"disabled\"\n#~ msgstr \"停用\"\n\n#~ msgid \"enabled\"\n#~ msgstr \"啟用\"\n\n#~ msgid \"Using %s encoding\"\n#~ msgstr \"使用 %s 編碼方式\"\n"
  },
  {
    "path": "release/.gitignore",
    "content": "maketarball\n"
  },
  {
    "path": "release/CMakeLists.txt",
    "content": "# This file is included from the top-level CMakeLists.txt.  We just store it\n# here to avoid cluttering up that file.\n\n\n#\n# Windows installer (Inno Setup)\n#\n\nif(WIN32)\n\nif(CMAKE_SIZEOF_VOID_P MATCHES 8)\n  set(INST_SUFFIX 64)\n  set(INST_DEFS -DWIN64)\nendif()\n\nconfigure_file(tigervnc.iss.in tigervnc.iss)\n\nadd_custom_command(OUTPUT ${CMAKE_PROJECT_NAME}${INST_SUFFIX}-${VERSION}.exe\n  COMMAND iscc -o. ${INST_DEFS} -F${CMAKE_PROJECT_NAME}${INST_SUFFIX}-${VERSION} tigervnc.iss\n  DEPENDS vncviewer tigervnc.iss)\nadd_custom_target(installer DEPENDS ${CMAKE_PROJECT_NAME}${INST_SUFFIX}-${VERSION}.exe)\n\nif(BUILD_WINVNC)\n  configure_file(winvnc.iss.in winvnc.iss)\n\n  add_custom_command(OUTPUT ${CMAKE_PROJECT_NAME}${INST_SUFFIX}-winvnc-${VERSION}.exe\n    COMMAND iscc -o. ${INST_DEFS} -F${CMAKE_PROJECT_NAME}${INST_SUFFIX}-winvnc-${VERSION} winvnc.iss\n    DEPENDS winvnc4 wm_hooks vncconfig winvnc.iss)\n  add_custom_target(winvnc_installer DEPENDS ${CMAKE_PROJECT_NAME}${INST_SUFFIX}-winvnc-${VERSION}.exe)\nendif()\n\nendif() # WIN32\n\n\n#\n# Mac DMG\n#\n\nif(APPLE)\n\nconfigure_file(makemacapp.in makemacapp)\nconfigure_file(Info.plist.in Info.plist)\n\nadd_custom_command(OUTPUT TigerVNC-${VERSION}.dmg\n  COMMAND sh makemacapp\n  DEPENDS vncviewer makemacapp Info.plist)\nadd_custom_target(dmg DEPENDS TigerVNC-${VERSION}.dmg)\n\nendif() # APPLE\n\n\n#\n# Binary tarball\n#\n\nif(UNIX)\n\nconfigure_file(maketarball.in maketarball)\n\nif(BUILD_JAVA)\n  set(TARBALL_JAVA_DEPENDENCY java)\nendif()\n\nset(PACKAGE_FILE ${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}-${VERSION}.tar.gz)\nadd_custom_command(OUTPUT ${PACKAGE_FILE}\n  COMMAND bash maketarball\n  DEPENDS maketarball vncviewer vncpasswd vncconfig ${TARBALL_JAVA_DEPENDENCY})\n\nadd_custom_target(tarball DEPENDS ${PACKAGE_FILE})\n\nendif() #UNIX\n\n#\n# Common\n#\n\ninstall(FILES ${CMAKE_SOURCE_DIR}/LICENCE.TXT DESTINATION ${CMAKE_INSTALL_FULL_DOCDIR})\ninstall(FILES ${CMAKE_SOURCE_DIR}/README.rst DESTINATION ${CMAKE_INSTALL_FULL_DOCDIR})\n"
  },
  {
    "path": "release/Info.plist.in",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>English</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>TigerVNC</string>\n\t<key>CFBundleExecutable</key>\n\t<string>vncviewer</string>\n\t<key>NSHighResolutionCapable</key>\n\t<false/>\n\t<key>CFBundleGetInfoString</key>\n\t<string>@VERSION@, Copyright (C) 1999-2026 TigerVNC team and many others (see README.rst)</string>\n\t<key>CFBundleIconFile</key>\n\t<string>tigervnc.icns</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.tigervnc.tigervnc</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleLongVersionString</key>\n\t<string>TigerVNC @VERSION@</string>\n\t<key>CFBundleName</key>\n\t<string>TigerVNC</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>@VERSION@</string>\n\t<key>CFBundleVersion</key>\n\t<string>@VERSION@f@BUILD@</string>\n\t<key>LSRequiresCarbon</key>\n\t<true/>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright (C) 1999-2026 TigerVNC team and many others (see README.rst)</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "release/makemacapp.in",
    "content": "#!/bin/sh\n\nset -u\nset -e\ntrap onexit INT\ntrap onexit TERM\ntrap onexit EXIT\n\nTMPDIR=\n\nonexit()\n{\n\tif [ ! \"$TMPDIR\" = \"\" ]; then\n\t\trm -rf $TMPDIR\n\tfi\n}\n\nusage()\n{\n\techo \"$0\"\n\texit 1\n}\n\nUNIVERSAL=0\n\nPACKAGE_NAME=TigerVNC\nVERSION=@VERSION@\nBUILD=@BUILD@\nSRCDIR=@CMAKE_SOURCE_DIR@\nBINDIR=@CMAKE_BINARY_DIR@\n\nif [ -f $PACKAGE_NAME.dmg ]; then\n\trm -f $PACKAGE_NAME.dmg\nfi\n\numask 022\nTMPDIR=`mktemp -d /tmp/$PACKAGE_NAME-build.XXXXXX`\nAPPROOT=\"$TMPDIR/dmg/TigerVNC.app\"\nmkdir -p \"$APPROOT/Contents/MacOS\"\nmkdir -p \"$APPROOT/Contents/Resources\"\n\ninstall -m 755 $BINDIR/vncviewer/vncviewer \"$APPROOT/Contents/MacOS/\"\ninstall -m 644 $SRCDIR/media/icons/tigervnc.icns \"$APPROOT/Contents/Resources/\"\ninstall -m 644 $BINDIR/release/Info.plist \"$APPROOT/Contents/\"\n\nfor lang in `cat \"$SRCDIR/po/LINGUAS\"`; do\n\tmkdir -p \"$APPROOT/Contents/Resources/locale/$lang/LC_MESSAGES\"\n\tinstall -m 644 $BINDIR/po/$lang.mo \\\n\t\t\"$APPROOT/Contents/Resources/locale/$lang/LC_MESSAGES/tigervnc.mo\"\ndone\n\ninstall -m 644 $SRCDIR/LICENCE.TXT $TMPDIR/dmg/\ninstall -m 644 $SRCDIR/README.rst $TMPDIR/dmg/\n\nhdiutil create -fs HFS+ -volname $PACKAGE_NAME-$VERSION \\\n\t-srcfolder \"$TMPDIR/dmg\" \\\n\t$TMPDIR/$PACKAGE_NAME-$VERSION.dmg \ncp $TMPDIR/$PACKAGE_NAME-$VERSION.dmg . \n\nexit\n"
  },
  {
    "path": "release/maketarball.in",
    "content": "#!/bin/bash\n\nset -u\nset -e\ntrap onexit INT\ntrap onexit TERM\ntrap onexit EXIT\n\nTMPDIR=\n\nonexit()\n{\n\tif [ ! \"$TMPDIR\" = \"\" ]; then\n\t\trm -rf $TMPDIR\n\tfi\n}\n\nPACKAGE_NAME=@CMAKE_PROJECT_NAME@\nVERSION=@VERSION@\nBUILD=@BUILD@\nSRCDIR=@CMAKE_SOURCE_DIR@\nBINDIR=@CMAKE_BINARY_DIR@\nOS=@CMAKE_SYSTEM_NAME@\nCPU=@CMAKE_SYSTEM_PROCESSOR@\nPREFIX=@CMAKE_INSTALL_PREFIX@\nCFLAGS=\"@CMAKE_C_FLAGS@\"\nif [[ $CFLAGS = *-m32* ]]; then\n\tCPU=i686\nfi\nPACKAGE_FILE=$PACKAGE_NAME-$OS-$CPU-$VERSION.tar.gz\n\ncd $BINDIR\n\numask 022\nTMPDIR=`mktemp -d /tmp/$PACKAGE_NAME-build.XXXXXX`\nrm -f $PACKAGE_FILE\nOUTDIR=$TMPDIR/inst/$PREFIX\n\nmkdir -p $OUTDIR/bin\nmkdir -p $OUTDIR/man/man1\n\nmake DESTDIR=$TMPDIR/inst install\n\npushd $TMPDIR/inst\ntar cfz ../$PACKAGE_FILE .\npopd\ncp $TMPDIR/$PACKAGE_FILE .\n\nexit\n"
  },
  {
    "path": "release/tigervnc.iss.in",
    "content": "[Setup]\n#ifdef WIN64\nArchitecturesInstallIn64BitMode=x64\n#endif\nAppName=TigerVNC\nAppVerName=TigerVNC @VERSION@ (@BUILD@)\nAppVersion=@VERSION@\nAppPublisher=TigerVNC team\nAppPublisherURL=https://tigervnc.org\nDefaultDirName={pf}\\TigerVNC\nDefaultGroupName=TigerVNC\nLicenseFile=@CMAKE_SOURCE_DIR@\\LICENCE.TXT\n\n[Files]\nSource: \"@CMAKE_BINARY_DIR@\\vncviewer\\vncviewer.exe\"; DestDir: \"{app}\"; Flags: ignoreversion restartreplace; \nSource: \"@CMAKE_SOURCE_DIR@\\README.rst\"; DestDir: \"{app}\"; Flags: ignoreversion\nSource: \"@CMAKE_SOURCE_DIR@\\LICENCE.TXT\"; DestDir: \"{app}\"; Flags: ignoreversion\n\n#define LINGUAS\n#define Lang\n#sub AddLanguage\n  #define Lang = FileRead(LINGUAS)\n  Source: \"@CMAKE_BINARY_DIR@\\po\\{#Lang}.mo\"; DestDir: \"{app}\\locale\\{#Lang}\\LC_MESSAGES\"; DestName: \"tigervnc.mo\"; Flags: ignoreversion\n#endsub\n#for {LINGUAS = FileOpen(\"@CMAKE_SOURCE_DIR@\\po\\LINGUAS\"); !FileEof(LINGUAS); \"\"} AddLanguage\n\n[Icons]\nName: \"{group}\\TigerVNC\"; FileName: \"{app}\\vncviewer.exe\";\nName: \"{group}\\Listening TigerVNC\"; FileName: \"{app}\\vncviewer.exe\"; Parameters: \"-listen\";\n\nName: \"{group}\\License\"; FileName: \"write.exe\"; Parameters: \"LICENCE.TXT\"; WorkingDir: \"{app}\"; Flags: \"useapppaths\"\nName: \"{group}\\Read Me\"; FileName: \"write.exe\"; Parameters: \"README.rst\"; WorkingDir: \"{app}\"; Flags: \"useapppaths\"\nName: \"{group}\\Uninstall TigerVNC\"; FileName: \"{uninstallexe}\"; WorkingDir: \"{app}\";\n"
  },
  {
    "path": "release/winvnc.iss.in",
    "content": "[Setup]\n#ifdef WIN64\nArchitecturesInstallIn64BitMode=x64\n#endif\nAppName=TigerVNC server\nAppVerName=TigerVNC server v@VERSION@ (@BUILD@)\nAppVersion=@VERSION@\nAppPublisher=TigerVNC team\nAppPublisherURL=https://tigervnc.org\nDefaultDirName={pf}\\TigerVNC server\nDefaultGroupName=TigerVNC server\nLicenseFile=@CMAKE_SOURCE_DIR@\\LICENCE.TXT\n\n[Dirs]\n; This directory is necessary to prevent the X509 file chooser from causing\n; an error dialog to appear when GetOpenFileName is called by SYSTEM account.\nName: \"{sys}\\config\\systemprofile\\Desktop\"\n\n[Files]\nSource: \"@CMAKE_BINARY_DIR@\\win\\winvnc\\winvnc4.exe\"; DestDir: \"{app}\"; Flags: ignoreversion restartreplace; \nSource: \"@CMAKE_BINARY_DIR@\\win\\wm_hooks\\wm_hooks.dll\"; DestDir: \"{app}\"; Flags: ignoreversion restartreplace; \nSource: \"@CMAKE_BINARY_DIR@\\win\\vncconfig\\vncconfig.exe\"; DestDir: \"{app}\"; Flags: ignoreversion restartreplace; \nSource: \"@CMAKE_SOURCE_DIR@\\README.rst\"; DestDir: \"{app}\"; Flags: ignoreversion\nSource: \"@CMAKE_SOURCE_DIR@\\LICENCE.TXT\"; DestDir: \"{app}\"; Flags: ignoreversion\n\n\n[Icons]\nName: \"{group}\\VNC server (User-Mode)\\Run VNC server\"; FileName: \"{app}\\winvnc4.exe\"; Parameters: \"-noconsole\";\nName: \"{group}\\VNC server (User-Mode)\\Configure VNC server\"; FileName: \"{app}\\vncconfig.exe\"; Parameters: \"-user\";\n\nName: \"{group}\\VNC server (Service-Mode)\\Configure VNC service\"; FileName: \"{app}\\vncconfig.exe\"; Parameters: \"-noconsole -service\";\nName: \"{group}\\VNC server (Service-Mode)\\Register VNC service\"; FileName: \"{app}\\winvnc4.exe\"; Parameters: \"-register\";\nName: \"{group}\\VNC server (Service-Mode)\\Unregister VNC service\"; FileName: \"{app}\\winvnc4.exe\"; Parameters: \"-unregister\";\nName: \"{group}\\VNC server (Service-Mode)\\Start VNC service\"; FileName: \"{app}\\winvnc4.exe\"; Parameters: \"-noconsole -start\";\nName: \"{group}\\VNC server (Service-Mode)\\Stop VNC service\"; FileName: \"{app}\\winvnc4.exe\"; Parameters: \"-noconsole -stop\";\nName: \"{group}\\License\"; FileName: \"write.exe\"; Parameters: \"LICENCE.TXT\"; WorkingDir: \"{app}\"; Flags: \"useapppaths\"\nName: \"{group}\\Read me\"; FileName: \"write.exe\"; Parameters: \"README.rst\"; WorkingDir: \"{app}\"; Flags: \"useapppaths\"\nName: \"{group}\\Uninstall TigerVNC server\"; FileName: \"{uninstallexe}\"; WorkingDir: \"{app}\";\n\n[Tasks]\nName: installservice; Description: \"&Register new TigerVNC server as a system service\"; GroupDescription: \"Server configuration:\"; \nName: startservice; Description: \"&Start or restart TigerVNC service\"; GroupDescription: \"Server configuration:\";\n\n[Run]\nFilename: \"{app}\\winvnc4.exe\"; Parameters: \"-register\"; Tasks: installservice\nFilename: \"net\"; Parameters: \"start winvnc4\"; Tasks: startservice\n\n[Code]\n\n{--- IShellLink ---}\n\nconst\n  CLSID_ShellLink = '{00021401-0000-0000-C000-000000000046}';\n  SLDF_RUNAS_USER = $2000;\n\ntype\n  IShellLinkW = interface(IUnknown)\n    '{000214F9-0000-0000-C000-000000000046}'\n    procedure Dummy;\n    procedure Dummy2;\n    procedure Dummy3;\n    function GetDescription(pszName: String; cchMaxName: Integer): HResult;\n    function SetDescription(pszName: String): HResult;\n    function GetWorkingDirectory(pszDir: String; cchMaxPath: Integer): HResult;\n    function SetWorkingDirectory(pszDir: String): HResult;\n    function GetArguments(pszArgs: String; cchMaxPath: Integer): HResult;\n    function SetArguments(pszArgs: String): HResult;\n    function GetHotkey(var pwHotkey: Word): HResult;\n    function SetHotkey(wHotkey: Word): HResult;\n    function GetShowCmd(out piShowCmd: Integer): HResult;\n    function SetShowCmd(iShowCmd: Integer): HResult;\n    function GetIconLocation(pszIconPath: String; cchIconPath: Integer;\n      out piIcon: Integer): HResult;\n    function SetIconLocation(pszIconPath: String; iIcon: Integer): HResult;\n    function SetRelativePath(pszPathRel: String; dwReserved: DWORD): HResult;\n    function Resolve(Wnd: HWND; fFlags: DWORD): HResult;\n    function SetPath(pszFile: String): HResult;\n  end;\n\n  IShellLinkDataList = interface(IUnknown)\n    '{45E2B4AE-B1C3-11D0-B92F-00A0C90312E1}'\n    function AddDataBlock(pDataBlock : DWORD) : HResult;\n    function CopyDataBlock(dwSig : DWORD; var ppDataBlock : DWORD) : HResult;\n    function RemoveDataBlock(dwSig : DWORD) : HResult;\n    function GetFlags(var pdwFlags : DWORD) : HResult;\n    function SetFlags(dwFlags : DWORD) : HResult;\n  end;\n\n  IPersist = interface(IUnknown)\n    '{0000010C-0000-0000-C000-000000000046}'\n    function GetClassID(var classID: TGUID): HResult;\n  end;\n\n  IPersistFile = interface(IPersist)\n    '{0000010B-0000-0000-C000-000000000046}'\n    function IsDirty: HResult;\n    function Load(pszFileName: String; dwMode: Longint): HResult;\n    function Save(pszFileName: String; fRemember: BOOL): HResult;\n    function SaveCompleted(pszFileName: String): HResult;\n    function GetCurFile(out pszFileName: String): HResult;\n  end;\n\nvar\n  OSVersion: TWindowsVersion;\n\nfunction InitializeSetup: Boolean;\nbegin\n  GetWindowsVersionEx(OSVersion);\n  SuppressibleMsgBox('TigerVNC Windows server is currently unmaintained and may not function correctly.', mbError, MB_OK, IDOK);\n  Result := True;\nend;\n\nprocedure SetRunAsUserFlag(Path: String);\nvar\n  Obj: IUnknown;\n  SL: IShellLinkW;\n  SDL: IShellLinkDataList;\n  PF: IPersistFile;\n  Flags: DWord;\nbegin\n  Obj := CreateComObject(StringToGuid(CLSID_ShellLink));\n  SL := IShellLinkW(Obj);\n  PF := IPersistFile(Obj);\n  SDL := IShellLinkDataList(Obj);\n  Path := ExpandConstant(Path);\n  OleCheck(PF.Load(Path, 0));\n  OleCheck(SDL.GetFlags(Flags));\n  OleCheck(SDL.SetFlags(Flags or SLDF_RUNAS_USER));\n  OleCheck(PF.Save(Path, True));\nend;\n\nprocedure CurStepChanged(CurStep: TSetupStep);\nvar\n  Flags: DWord;\nbegin\n  { Post-install actions on Windows Vista and higher:\n    o Modify Service-Mode start menu commands so they run as administrator.\n    o Set up the SoftwareSASGeneration system policy so as to allow services to simulate Ctrl+Alt+Del. }\n  if (CurStep = ssPostInstall) and (OSVersion.Major >= 6) then begin\n    SetRunAsUserFlag('{group}\\VNC server (Service-Mode)\\Configure VNC Service.lnk');\n    SetRunAsUserFlag('{group}\\VNC server (Service-Mode)\\Register VNC Service.lnk');\n    SetRunAsUserFlag('{group}\\VNC server (Service-Mode)\\Unregister VNC Service.lnk');\n    SetRunAsUserFlag('{group}\\VNC server (Service-Mode)\\Start VNC Service.lnk');\n    SetRunAsUserFlag('{group}\\VNC server (Service-Mode)\\Stop VNC Service.lnk');\n    if not RegQueryDWordValue(\n      HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System',\n      'SoftwareSASGeneration', Flags\n    ) then Flags := 0;\n    RegWriteDWordValue(\n      HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System',\n      'SoftwareSASGeneration', Flags or 1\n    );\n  end;\nend;  \n"
  },
  {
    "path": "tests/.gitignore",
    "content": "conv\nconvertlf\nconvperf\ndecperf\nemulatemb\nencperf\nfbperf\ngesturehandler\nhostport\npixelformat\nunicode\n"
  },
  {
    "path": "tests/CMakeLists.txt",
    "content": "if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)\n  message(FATAL_ERROR \"cmake must be invoked with the top level directory\")\nendif()\n\n# Benchmarking tools\nadd_subdirectory(perf)\n\n# Unit tests\nif(GTest_FOUND)\n  add_subdirectory(unit)\nendif()\n"
  },
  {
    "path": "tests/perf/CMakeLists.txt",
    "content": "include_directories(${CMAKE_SOURCE_DIR}/common)\n\nadd_library(test_util STATIC util.cxx)\n\nadd_executable(convperf convperf.cxx)\ntarget_link_libraries(convperf test_util rfb)\n\nadd_executable(decperf decperf.cxx)\ntarget_link_libraries(decperf test_util rdr rfb)\n\nadd_executable(encperf encperf.cxx)\ntarget_link_libraries(encperf test_util core rdr rfb)\n\nif (BUILD_VIEWER)\n  add_executable(fbperf\n    fbperf.cxx\n    ${CMAKE_SOURCE_DIR}/vncviewer/PlatformPixelBuffer.cxx\n    ${CMAKE_SOURCE_DIR}/vncviewer/Surface.cxx)\n  if(WIN32)\n    target_sources(fbperf PRIVATE ${CMAKE_SOURCE_DIR}/vncviewer/Surface_Win32.cxx)\n  elseif(APPLE)\n    target_sources(fbperf PRIVATE\n      ${CMAKE_SOURCE_DIR}/vncviewer/Surface_OSX.cxx\n      ${CMAKE_SOURCE_DIR}/vncviewer/keysym2ucs.c\n      ${CMAKE_SOURCE_DIR}/vncviewer/cocoa.mm)\n  else()\n    target_sources(fbperf PRIVATE ${CMAKE_SOURCE_DIR}/vncviewer/Surface_X11.cxx)\n  endif()\n  target_include_directories(fbperf SYSTEM PUBLIC ${FLTK_INCLUDE_DIR})\n  target_include_directories(fbperf SYSTEM PUBLIC ${Intl_INCLUDE_DIR})\n  target_link_libraries(fbperf test_util core rfb ${FLTK_LIBRARIES} ${Intl_LIBRARIES})\n  if(WIN32)\n    target_link_libraries(fbperf msimg32)\n  endif()\n  if(APPLE)\n    target_link_libraries(fbperf \"-framework Cocoa\")\n    target_link_libraries(fbperf \"-framework Carbon\")\n    target_link_libraries(fbperf \"-framework IOKit\")\n  endif()\nendif()\n"
  },
  {
    "path": "tests/perf/convperf.cxx",
    "content": "/* Copyright 2013-2014 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <rfb/PixelFormat.h>\n\n#include \"util.h\"\n\nstatic const int tile = 64;\nstatic const int fbsize = 4096;\n\nstatic uint8_t *fb1, *fb2;\n\ntypedef void (*testfn) (rfb::PixelFormat&, rfb::PixelFormat&, uint8_t*, uint8_t*);\n\nstruct TestEntry {\n  const char *label;\n  testfn fn;\n};\n\nstatic void testMemcpy(rfb::PixelFormat &dstpf,\n                       rfb::PixelFormat& /*srcpf*/,\n                       uint8_t *dst, uint8_t *src)\n{\n  int h;\n  h = tile;\n  while (h--) {\n    memcpy(dst, src, tile * dstpf.bpp/8);\n    dst += fbsize * dstpf.bpp/8;\n    src += fbsize * dstpf.bpp/8;\n  }\n}\n\nstatic void testBuffer(rfb::PixelFormat &dstpf,\n                       rfb::PixelFormat &srcpf,\n                       uint8_t *dst, uint8_t *src)\n{\n  dstpf.bufferFromBuffer(dst, srcpf, src, tile, tile, fbsize, fbsize);\n}\n\nstatic void testToRGB(rfb::PixelFormat& /*dstpf*/,\n                      rfb::PixelFormat &srcpf,\n                      uint8_t *dst, uint8_t *src)\n{\n  srcpf.rgbFromBuffer(dst, src, tile, fbsize, tile);\n}\n\nstatic void testFromRGB(rfb::PixelFormat &dstpf,\n                        rfb::PixelFormat& /*srcpf*/,\n                        uint8_t *dst, uint8_t *src)\n{\n  dstpf.bufferFromRGB(dst, src, tile, fbsize, tile);\n}\n\nstatic void doTest(testfn fn, rfb::PixelFormat &dstpf, rfb::PixelFormat &srcpf)\n{\n  startCpuCounter();\n\n  for (int i = 0;i < 10000;i++) {\n    int x, y;\n    uint8_t *dst, *src;\n    x = rand() % (fbsize - tile);\n    y = rand() % (fbsize - tile);\n    dst = fb1 + (x + y * fbsize) * dstpf.bpp/8;\n    src = fb2 + (x + y * fbsize) * srcpf.bpp/8;\n    fn(dstpf, srcpf, dst, src);\n  }\n\n  endCpuCounter();\n\n  float data, time;\n\n  data = (double)tile * tile * 10000;\n  time = getCpuCounter();\n\n  printf(\"%g\", data / (1000.0*1000.0) / time);\n}\n\nstruct TestEntry tests[] = {\n  {\"memcpy\", testMemcpy},\n  {\"bufferFromBuffer\", testBuffer},\n  {\"rgbFromBuffer\", testToRGB},\n  {\"bufferFromRGB\", testFromRGB},\n};\n\nstatic void doTests(rfb::PixelFormat &dstpf, rfb::PixelFormat &srcpf)\n{\n  size_t i;\n  char dstb[256], srcb[256];\n\n  dstpf.print(dstb, sizeof(dstb));\n  srcpf.print(srcb, sizeof(srcb));\n\n  printf(\"%s,%s\", srcb, dstb);\n\n  for (i = 0;i < sizeof(tests)/sizeof(tests[0]);i++) {\n    printf(\",\");\n    doTest(tests[i].fn, dstpf, srcpf);\n  }\n\n  printf(\"\\n\");\n}\n\nint main(int /*argc*/, char** /*argv*/)\n{\n  size_t bufsize;\n\n  time_t t;\n  char datebuffer[256];\n\n  size_t i;\n\n  bufsize = fbsize * fbsize * 4;\n\n  fb1 = new uint8_t[bufsize];\n  fb2 = new uint8_t[bufsize];\n\n  for (i = 0;i < bufsize;i++) {\n    fb1[i] = rand();\n    fb2[i] = rand();\n  }\n\n  time(&t);\n  strftime(datebuffer, sizeof(datebuffer), \"%Y-%m-%d %H:%M UTC\", gmtime(&t));\n\n  printf(\"# Pixel Conversion Performance Test %s\\n\", datebuffer);\n  printf(\"#\\n\");\n  printf(\"# Frame buffer: %dx%d pixels\\n\", fbsize, fbsize);\n  printf(\"# Tile size: %dx%d pixels\\n\", tile, tile);\n  printf(\"#\\n\");\n  printf(\"# Note: Results are Mpixels/sec\\n\");\n  printf(\"#\\n\");\n\n  printf(\"Source format,Destination Format\");\n  for (i = 0;i < sizeof(tests)/sizeof(tests[0]);i++)\n    printf(\",%s\", tests[i].label);\n  printf(\"\\n\");\n\n  rfb::PixelFormat dstpf, srcpf;\n\n  /* rgb888 targets */\n\n  printf(\"\\n\");\n\n  dstpf.parse(\"rgb888\");\n\n  srcpf.parse(\"rgb888\");\n  doTests(dstpf, srcpf);\n\n  srcpf.parse(\"bgr888\");\n  doTests(dstpf, srcpf);\n\n  srcpf.parse(\"rgb565\");\n  doTests(dstpf, srcpf);\n\n  srcpf.parse(\"rgb232\");\n  doTests(dstpf, srcpf);\n\n  /* rgb565 targets */\n\n  printf(\"\\n\");\n\n  dstpf.parse(\"rgb565\");\n\n  srcpf.parse(\"rgb888\");\n  doTests(dstpf, srcpf);\n\n  srcpf.parse(\"bgr565\");\n  doTests(dstpf, srcpf);\n\n  srcpf.parse(\"rgb232\");\n  doTests(dstpf, srcpf);\n\n  /* rgb232 targets */\n\n  printf(\"\\n\");\n\n  dstpf.parse(\"rgb232\");\n\n  srcpf.parse(\"rgb888\");\n  doTests(dstpf, srcpf);\n\n  srcpf.parse(\"rgb565\");\n  doTests(dstpf, srcpf);\n\n  srcpf.parse(\"bgr232\");\n  doTests(dstpf, srcpf);\n\n  /* rgb565 with endian conversion (both ways) */\n\n  printf(\"\\n\");\n\n  dstpf = rfb::PixelFormat(32, 24, false, true, 255, 255, 255, 0, 8, 16);\n  srcpf = rfb::PixelFormat(32, 24, true, true, 255, 255, 255, 0, 8, 16);\n\n  doTests(srcpf, dstpf);\n\n  doTests(dstpf, srcpf);\n\n  dstpf = rfb::PixelFormat(16, 16, false, true, 31, 63, 31, 0, 5, 11);\n  srcpf = rfb::PixelFormat(16, 16, true, true, 31, 63, 31, 0, 5, 11);\n\n  doTests(srcpf, dstpf);\n\n  doTests(dstpf, srcpf);\n\n  return 0;\n}\n\n"
  },
  {
    "path": "tests/perf/decperf.cxx",
    "content": "/* Copyright 2015 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n/*\n * This program reads files produced by TightVNC's/TurboVNC's\n * compare-encodings. It is basically a dump of the RFB protocol\n * from the server side from the ServerInit message and forward.\n * It is assumed that the client is using a bgr888 (LE) pixel\n * format.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include <sys/time.h>\n\n#include <rdr/FileInStream.h>\n#include <rdr/OutStream.h>\n\n#include <rfb/CConnection.h>\n#include <rfb/CMsgReader.h>\n#include <rfb/CMsgWriter.h>\n#include <rfb/PixelBuffer.h>\n#include <rfb/PixelFormat.h>\n\n#include \"util.h\"\n\n// FIXME: Files are always in this format\nstatic const rfb::PixelFormat filePF(32, 24, false, true, 255, 255, 255, 0, 8, 16);\n\nclass DummyOutStream : public rdr::OutStream {\npublic:\n  DummyOutStream();\n\n  size_t length() override;\n  void flush() override;\n\nprivate:\n  void overrun(size_t needed) override;\n\n  int offset;\n  uint8_t buf[131072];\n};\n\nclass CConn : public rfb::CConnection {\npublic:\n  CConn(const char *filename);\n  ~CConn();\n\n  void initDone() override;\n  void framebufferUpdateStart() override;\n  void framebufferUpdateEnd() override;\n  void setColourMapEntries(int, int, uint16_t*) override;\n  void bell() override;\n  void serverCutText(const char*) override;\n  virtual void getUserPasswd(bool secure, std::string *user, std::string *password) override;\n  virtual bool showMsgBox(rfb::MsgBoxFlags flags, const char *title, const char *text) override;\n\npublic:\n  double cpuTime;\n\nprotected:\n  rdr::FileInStream *in;\n  DummyOutStream *out;\n\n};\n\nDummyOutStream::DummyOutStream()\n{\n  offset = 0;\n  ptr = buf;\n  end = buf + sizeof(buf);\n}\n\nsize_t DummyOutStream::length()\n{\n  flush();\n  return offset;\n}\n\nvoid DummyOutStream::flush()\n{\n  offset += ptr - buf;\n  ptr = buf;\n}\n\nvoid DummyOutStream::overrun(size_t needed)\n{\n  flush();\n  if (avail() < needed)\n    throw std::out_of_range(\"Insufficient dummy output buffer\");\n}\n\nCConn::CConn(const char *filename)\n{\n  cpuTime = 0.0;\n\n  in = new rdr::FileInStream(filename);\n  out = new DummyOutStream;\n  setStreams(in, out);\n\n  // Need to skip the initial handshake\n  setState(RFBSTATE_INITIALISATION);\n  // That also means that the reader and writer weren't setup\n  setReader(new rfb::CMsgReader(this, in));\n  setWriter(new rfb::CMsgWriter(&server, out));\n}\n\nCConn::~CConn()\n{\n  delete in;\n  delete out;\n}\n\nvoid CConn::initDone()\n{\n  setFramebuffer(new rfb::ManagedPixelBuffer(filePF,\n                                             server.width(),\n                                             server.height()));\n}\n\nvoid CConn::framebufferUpdateStart()\n{\n  CConnection::framebufferUpdateStart();\n\n  startCpuCounter();\n}\n\nvoid CConn::framebufferUpdateEnd()\n{\n  CConnection::framebufferUpdateEnd();\n\n  endCpuCounter();\n\n  cpuTime += getCpuCounter();\n}\n\nvoid CConn::setColourMapEntries(int, int, uint16_t*)\n{\n}\n\nvoid CConn::bell()\n{\n}\n\nvoid CConn::serverCutText(const char*)\n{\n}\n\nvoid CConn::getUserPasswd(bool, std::string *, std::string *)\n{\n}\n\nbool CConn::showMsgBox(rfb::MsgBoxFlags, const char *, const char *)\n{\n    return true;\n}\n\nstruct stats\n{\n  double decodeTime;\n  double realTime;\n};\n\nstatic struct stats runTest(const char *fn)\n{\n  CConn *cc;\n  struct timeval start, stop;\n  struct stats s;\n\n  gettimeofday(&start, nullptr);\n\n  try {\n    cc = new CConn(fn);\n  } catch (std::exception& e) {\n    fprintf(stderr, \"Failed to open rfb file: %s\\n\", e.what());\n    exit(1);\n  }\n\n  try {\n    while (true)\n      cc->processMsg();\n  } catch (rdr::end_of_stream& e) {\n  } catch (std::exception& e) {\n    fprintf(stderr, \"Failed to run rfb file: %s\\n\", e.what());\n    exit(1);\n  }\n\n  gettimeofday(&stop, nullptr);\n\n  s.decodeTime = cc->cpuTime;\n  s.realTime = (double)stop.tv_sec - start.tv_sec;\n  s.realTime += ((double)stop.tv_usec - start.tv_usec)/1000000.0;\n\n  delete cc;\n\n  return s;\n}\n\nstatic void sort(double *array, int count)\n{\n  bool sorted;\n  int i;\n  do {\n    sorted = true;\n    for (i = 1;i < count;i++) {\n      if (array[i-1] > array[i]) {\n        double d;\n        d = array[i];\n        array[i] = array[i-1];\n        array[i-1] = d;\n        sorted = false;\n      }\n    }\n  } while (!sorted);\n}\n\nstatic const int runCount = 9;\n\nint main(int argc, char **argv)\n{\n  int i;\n  struct stats runs[runCount];\n  double values[runCount], dev[runCount];\n  double median, meddev;\n\n  if (argc != 2) {\n    printf(\"Syntax: %s <rfb file>\\n\", argv[0]);\n    return 1;\n  }\n\n  // Warmup\n  runTest(argv[1]);\n\n  // Multiple runs to get a good average\n  for (i = 0;i < runCount;i++)\n    runs[i] = runTest(argv[1]);\n\n  // Calculate median and median deviation for CPU usage\n  for (i = 0;i < runCount;i++)\n    values[i] = runs[i].decodeTime;\n\n  sort(values, runCount);\n  median = values[runCount/2];\n\n  for (i = 0;i < runCount;i++)\n    dev[i] = fabs((values[i] - median) / median) * 100;\n\n  sort(dev, runCount);\n  meddev = dev[runCount/2];\n\n  printf(\"CPU time: %g s (+/- %g %%)\\n\", median, meddev);\n\n  // And for CPU core usage\n  for (i = 0;i < runCount;i++)\n    values[i] = runs[i].decodeTime / runs[i].realTime;\n\n  sort(values, runCount);\n  median = values[runCount/2];\n\n  for (i = 0;i < runCount;i++)\n    dev[i] = fabs((values[i] - median) / median) * 100;\n\n  sort(dev, runCount);\n  meddev = dev[runCount/2];\n\n  printf(\"Core usage: %g (+/- %g %%)\\n\", median, meddev);\n\n  return 0;\n}\n"
  },
  {
    "path": "tests/perf/encperf.cxx",
    "content": "/* Copyright 2015 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * Copyright (C) 2015 D. R. Commander.  All Rights Reserved.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n/*\n * This program reads files produced by TightVNC's/TurboVNC's\n * fbs-dump, which in turn takes files from rfbproxy. It is\n * basically a dump of the RFB protocol from the server side after\n * the ServerInit message. Mostly this consists of FramebufferUpdate\n * message using the HexTile encoding. Screen size and pixel format\n * are not encoded in the file and must be specified by the user.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#define __USE_MINGW_ANSI_STDIO 1\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include <sys/time.h>\n\n#include <core/Configuration.h>\n\n#include <rdr/OutStream.h>\n#include <rdr/FileInStream.h>\n\n#include <rfb/AccessRights.h>\n#include <rfb/PixelFormat.h>\n#include <rfb/CConnection.h>\n#include <rfb/CMsgReader.h>\n#include <rfb/CMsgWriter.h>\n#include <rfb/UpdateTracker.h>\n#include <rfb/EncodeManager.h>\n#include <rfb/SConnection.h>\n#include <rfb/SMsgWriter.h>\n\n#include \"util.h\"\n\nstatic core::IntParameter width(\"width\", \"Frame buffer width\", 0);\nstatic core::IntParameter height(\"height\", \"Frame buffer height\", 0);\nstatic core::IntParameter count(\"count\", \"Number of benchmark iterations\", 9);\n\nstatic core::StringParameter format(\"format\", \"Pixel format (e.g. bgr888)\", \"\");\n\nstatic core::BoolParameter translate(\"translate\",\n                                     \"Translate 8-bit and 16-bit datasets into 24-bit\",\n                                     true);\n\n// The frame buffer (and output) is always this format\nstatic const rfb::PixelFormat fbPF(32, 24, false, true, 255, 255, 255, 0, 8, 16);\n\n// Encodings to use\nstatic const int32_t encodings[] = {\n  rfb::encodingTight, rfb::encodingCopyRect, rfb::encodingRRE,\n  rfb::encodingHextile, rfb::encodingZRLE, rfb::pseudoEncodingLastRect,\n  rfb::pseudoEncodingQualityLevel0 + 8,\n  rfb::pseudoEncodingCompressLevel0 + 2};\n\nclass DummyOutStream : public rdr::OutStream {\npublic:\n  DummyOutStream();\n\n  size_t length() override;\n  void flush() override;\n\nprivate:\n  void overrun(size_t needed) override;\n\n  int offset;\n  uint8_t buf[131072];\n};\n\nclass CConn : public rfb::CConnection {\npublic:\n  CConn(const char *filename);\n  ~CConn();\n\n  void getStats(double& ratio, unsigned long long& bytes,\n                unsigned long long& rawEquivalent);\n\n  void initDone() override {};\n  void resizeFramebuffer() override;\n  void framebufferUpdateStart() override;\n  void framebufferUpdateEnd() override;\n  bool dataRect(const core::Rect&, int) override;\n  void setColourMapEntries(int, int, uint16_t*) override;\n  void bell() override;\n  void serverCutText(const char*) override;\n  virtual void getUserPasswd(bool secure, std::string *user, std::string *password) override;\n  virtual bool showMsgBox(rfb::MsgBoxFlags flags, const char *title, const char *text) override;\n\npublic:\n  double decodeTime;\n  double encodeTime;\n\nprotected:\n  rdr::FileInStream *in;\n  DummyOutStream *out;\n  rfb::SimpleUpdateTracker updates;\n  class SConn *sc;\n};\n\nclass Manager : public rfb::EncodeManager {\npublic:\n  Manager(class rfb::SConnection *conn);\n\n  void getStats(double&, unsigned long long&, unsigned long long&);\n};\n\nclass SConn : public rfb::SConnection {\npublic:\n  SConn();\n  ~SConn();\n\n  void writeUpdate(const rfb::UpdateInfo& ui, const rfb::PixelBuffer* pb);\n\n  void getStats(double&, unsigned long long&, unsigned long long&);\n\n  void setAccessRights(rfb::AccessRights ar) override;\n\n  void setDesktopSize(int fb_width, int fb_height,\n                      const rfb::ScreenSet& layout) override;\n\n  void keyEvent(uint32_t keysym, uint32_t keycode, bool down) override;\n  void pointerEvent(const core::Point& pos,\n                    uint16_t buttonMask) override;\n\nprotected:\n  DummyOutStream *out;\n  Manager *manager;\n};\n\nDummyOutStream::DummyOutStream()\n{\n  offset = 0;\n  ptr = buf;\n  end = buf + sizeof(buf);\n}\n\nsize_t DummyOutStream::length()\n{\n  flush();\n  return offset;\n}\n\nvoid DummyOutStream::flush()\n{\n  offset += ptr - buf;\n  ptr = buf;\n}\n\nvoid DummyOutStream::overrun(size_t needed)\n{\n  flush();\n  if (avail() < needed)\n    throw std::out_of_range(\"Insufficient dummy output buffer\");\n}\n\nCConn::CConn(const char *filename)\n{\n  decodeTime = 0.0;\n  encodeTime = 0.0;\n\n  in = new rdr::FileInStream(filename);\n  out = new DummyOutStream;\n  setStreams(in, out);\n\n  // Need to skip the initial handshake and ServerInit\n  setState(RFBSTATE_NORMAL);\n  // That also means that the reader and writer weren't setup\n  setReader(new rfb::CMsgReader(this, in));\n  setWriter(new rfb::CMsgWriter(&server, out));\n  // Nor the frame buffer size and format\n  rfb::PixelFormat pf;\n  pf.parse(format);\n  server.setPF(pf);\n  setDesktopSize(width, height);\n\n  sc = new SConn();\n  sc->client.setPF((bool)translate ? fbPF : pf);\n  ((rfb::SMsgHandler*)sc)->setEncodings(sizeof(encodings) / sizeof(*encodings), encodings);\n}\n\nCConn::~CConn()\n{\n  delete sc;\n  delete in;\n  delete out;\n}\n\nvoid CConn::getStats(double& ratio, unsigned long long& bytes,\n                     unsigned long long& rawEquivalent)\n{\n  sc->getStats(ratio, bytes, rawEquivalent);\n}\n\nvoid CConn::resizeFramebuffer()\n{\n  rfb::ModifiablePixelBuffer *pb;\n\n  pb = new rfb::ManagedPixelBuffer((bool)translate ? fbPF : server.pf(),\n                                   server.width(), server.height());\n  setFramebuffer(pb);\n}\n\nvoid CConn::framebufferUpdateStart()\n{\n  CConnection::framebufferUpdateStart();\n\n  updates.clear();\n  startCpuCounter();\n}\n\nvoid CConn::framebufferUpdateEnd()\n{\n  rfb::UpdateInfo ui;\n  rfb::PixelBuffer* pb = getFramebuffer();\n  core::Region clip(pb->getRect());\n\n  CConnection::framebufferUpdateEnd();\n\n  endCpuCounter();\n\n  decodeTime += getCpuCounter();\n\n  updates.getUpdateInfo(&ui, clip);\n\n  startCpuCounter();\n  sc->writeUpdate(ui, pb);\n  endCpuCounter();\n\n  encodeTime += getCpuCounter();\n}\n\nbool CConn::dataRect(const core::Rect& r, int encoding)\n{\n  if (!CConnection::dataRect(r, encoding))\n    return false;\n\n  if (encoding != rfb::encodingCopyRect) // FIXME\n    updates.add_changed(r);\n\n  return true;\n}\n\nvoid CConn::setColourMapEntries(int, int, uint16_t*)\n{\n}\n\nvoid CConn::bell()\n{\n}\n\nvoid CConn::serverCutText(const char*)\n{\n}\n\nvoid CConn::getUserPasswd(bool, std::string *, std::string *)\n{\n}\n\nbool CConn::showMsgBox(rfb::MsgBoxFlags, const char *, const char *)\n{\n    return true;\n}\n\nManager::Manager(class rfb::SConnection *conn_) :\n  EncodeManager(conn_)\n{\n}\n\nvoid Manager::getStats(double& ratio, unsigned long long& encodedBytes,\n                       unsigned long long& rawEquivalent)\n{\n  StatsVector::iterator iter;\n  unsigned long long bytes, equivalent;\n\n  bytes = equivalent = 0;\n  for (iter = stats.begin(); iter != stats.end(); ++iter) {\n    StatsVector::value_type::iterator iter2;\n    for (iter2 = iter->begin(); iter2 != iter->end(); ++iter2) {\n      bytes += iter2->bytes;\n      equivalent += iter2->equivalent;\n    }\n  }\n\n  ratio = (double)equivalent / bytes;\n  encodedBytes = bytes;\n  rawEquivalent = equivalent;\n}\n\nSConn::SConn()\n: SConnection(rfb::AccessDefault)\n{\n  out = new DummyOutStream;\n  setStreams(nullptr, out);\n\n  setWriter(new rfb::SMsgWriter(&client, out));\n\n  manager = new Manager(this);\n}\n\nSConn::~SConn()\n{\n  delete manager;\n  delete out;\n}\n\nvoid SConn::writeUpdate(const rfb::UpdateInfo& ui, const rfb::PixelBuffer* pb)\n{\n  manager->writeUpdate(ui, pb, nullptr);\n}\n\nvoid SConn::getStats(double& ratio, unsigned long long& bytes,\n                     unsigned long long& rawEquivalent)\n{\n  manager->getStats(ratio, bytes, rawEquivalent);\n}\n\nvoid SConn::setAccessRights(rfb::AccessRights)\n{\n}\n\nvoid SConn::setDesktopSize(int, int, const rfb::ScreenSet&)\n{\n}\n\nvoid SConn::keyEvent(uint32_t, uint32_t, bool)\n{\n}\n\nvoid SConn::pointerEvent(const core::Point&, uint16_t)\n{\n}\n\nstruct stats\n{\n  double decodeTime;\n  double encodeTime;\n  double realTime;\n\n  double ratio;\n  unsigned long long bytes;\n  unsigned long long rawEquivalent;\n};\n\nstatic struct stats runTest(const char *fn)\n{\n  CConn *cc;\n  struct stats s;\n  struct timeval start, stop;\n\n  gettimeofday(&start, nullptr);\n\n  try {\n    cc = new CConn(fn);\n  } catch (std::exception& e) {\n    fprintf(stderr, \"Failed to open rfb file: %s\\n\", e.what());\n    exit(1);\n  }\n\n  try {\n    while (true)\n      cc->processMsg();\n  } catch (rdr::end_of_stream& e) {\n  } catch (std::exception& e) {\n    fprintf(stderr, \"Failed to run rfb file: %s\\n\", e.what());\n    exit(1);\n  }\n\n  gettimeofday(&stop, nullptr);\n\n  s.decodeTime = cc->decodeTime;\n  s.encodeTime = cc->encodeTime;\n  s.realTime = (double)stop.tv_sec - start.tv_sec;\n  s.realTime += ((double)stop.tv_usec - start.tv_usec)/1000000.0;\n  cc->getStats(s.ratio, s.bytes, s.rawEquivalent);\n\n  delete cc;\n\n  return s;\n}\n\nstatic void sort(double *array, int len)\n{\n  bool sorted;\n  int i;\n  do {\n    sorted = true;\n    for (i = 1; i < len; i++) {\n      if (array[i-1] > array[i]) {\n        double d;\n        d = array[i];\n        array[i] = array[i - 1];\n        array[i - 1] = d;\n        sorted = false;\n      }\n    }\n  } while (!sorted);\n}\n\nstatic void usage(const char *argv0)\n{\n  fprintf(stderr, \"Syntax: %s [options] <rfb file>\\n\", argv0);\n  fprintf(stderr, \"Options:\\n\");\n  core::Configuration::listParams(79, 14);\n  exit(1);\n}\n\nint main(int argc, char **argv)\n{\n  int i;\n\n  const char *fn;\n\n  fn = nullptr;\n  for (i = 1; i < argc;) {\n    int ret;\n\n    ret = core::Configuration::handleParamArg(argc, argv, i);\n    if (ret > 0) {\n      i += ret;\n      continue;\n    }\n\n    if (strcmp(argv[i], \"-h\") == 0 ||\n        strcmp(argv[i], \"--help\") == 0) {\n      usage(argv[0]);\n    }\n\n    if (strcmp(argv[i], \"-v\") == 0 ||\n        strcmp(argv[i], \"--version\") == 0) {\n      fprintf(stderr, \"encperf (TigerVNC) %s\\n\", PACKAGE_VERSION);\n      exit(0);\n    }\n\n    if (argv[i][0] == '-') {\n      fprintf(stderr, \"%s: Unrecognized option '%s'\\n\",\n              argv[0], argv[i]);\n      fprintf(stderr, \"See '%s --help' for more information.\\n\",\n              argv[0]);\n      exit(1);\n    }\n\n    if (fn != nullptr) {\n      fprintf(stderr, \"%s: Extra argument '%s'\\n\", argv[0], argv[i]);\n      fprintf(stderr, \"See '%s --help' for more information.\\n\",\n              argv[0]);\n      exit(1);\n    }\n\n    fn = argv[i];\n    i++;\n  }\n\n  int runCount = count;\n  struct stats *runs = new struct stats[runCount];\n  double *values = new double[runCount];\n  double *dev = new double[runCount];\n  double median, meddev;\n\n  if (fn == nullptr) {\n    fprintf(stderr, \"No file specified!\\n\\n\");\n    usage(argv[0]);\n  }\n\n  if (strcmp(format, \"\") == 0) {\n    fprintf(stderr, \"Pixel format not specified!\\n\\n\");\n    usage(argv[0]);\n  }\n\n  if (width == 0 || height == 0) {\n    fprintf(stderr, \"Frame buffer size not specified!\\n\\n\");\n    usage(argv[0]);\n  }\n\n  // Warmup\n  runTest(fn);\n\n  // Multiple runs to get a good average\n  for (i = 0; i < runCount; i++)\n    runs[i] = runTest(fn);\n\n  // Calculate median and median deviation for CPU usage decoding\n  for (i = 0;i < runCount;i++)\n    values[i] = runs[i].decodeTime;\n\n  sort(values, runCount);\n  median = values[runCount/2];\n\n  for (i = 0;i < runCount;i++)\n    dev[i] = fabs((values[i] - median) / median) * 100;\n\n  sort(dev, runCount);\n  meddev = dev[runCount/2];\n\n  printf(\"CPU time (decoding): %g s (+/- %g %%)\\n\", median, meddev);\n\n  // And for CPU usage encoding\n  for (i = 0;i < runCount;i++)\n    values[i] = runs[i].encodeTime;\n\n  sort(values, runCount);\n  median = values[runCount/2];\n\n  for (i = 0;i < runCount;i++)\n    dev[i] = fabs((values[i] - median) / median) * 100;\n\n  sort(dev, runCount);\n  meddev = dev[runCount/2];\n\n  printf(\"CPU time (encoding): %g s (+/- %g %%)\\n\", median, meddev);\n\n  // And for CPU core usage encoding\n  for (i = 0;i < runCount;i++)\n    values[i] = (runs[i].decodeTime + runs[i].encodeTime) / runs[i].realTime;\n\n  sort(values, runCount);\n  median = values[runCount/2];\n\n  for (i = 0;i < runCount;i++)\n    dev[i] = fabs((values[i] - median) / median) * 100;\n\n  sort(dev, runCount);\n  meddev = dev[runCount/2];\n\n  printf(\"Core usage (total): %g (+/- %g %%)\\n\", median, meddev);\n\n  printf(\"Encoded bytes: %llu\\n\", runs[0].bytes);\n  printf(\"Raw equivalent bytes: %llu\\n\", runs[0].rawEquivalent);\n  printf(\"Ratio: %g\\n\", runs[0].ratio);\n\n  return 0;\n}\n"
  },
  {
    "path": "tests/perf/fbperf.cxx",
    "content": "/* Copyright 2016 Pierre Ossman <ossman@cendio.se> for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <math.h>\n#include <sys/time.h>\n\n#include <FL/Fl.H>\n#include <FL/Fl_Window.H>\n#include <FL/fl_draw.H>\n#include <FL/x.H>\n\n#include <core/string.h>\n#include <core/time.h>\n\n#include \"../vncviewer/PlatformPixelBuffer.h\"\n\n#include \"util.h\"\n\nclass TestWindow: public Fl_Window {\npublic:\n  TestWindow();\n  ~TestWindow();\n\n  virtual void start(int width, int height);\n  virtual void stop();\n\n  void draw() override;\n\nprotected:\n  void flush() override;\n\n  void update();\n  virtual void changefb();\n\n  static void timer(void* data);\n\npublic:\n  unsigned long long pixels, frames;\n  double time;\n\nprotected:\n  PlatformPixelBuffer* fb;\n};\n\nclass PartialTestWindow: public TestWindow {\nprotected:\n  void changefb() override;\n};\n\nclass OverlayTestWindow: public PartialTestWindow {\npublic:\n  OverlayTestWindow();\n\n  void start(int width, int height) override;\n  void stop() override;\n\n  void draw() override;\n\nprotected:\n  Surface* overlay;\n  Surface* offscreen;\n};\n\nTestWindow::TestWindow() :\n  Fl_Window(0, 0, \"Framebuffer Performance Test\"),\n  fb(nullptr)\n{\n}\n\nTestWindow::~TestWindow()\n{\n  stop();\n}\n\nvoid TestWindow::start(int width, int height)\n{\n  uint32_t pixel;\n\n  stop();\n\n  resize(x(), y(), width, height);\n\n  pixels = 0;\n  frames = 0;\n  time = 0;\n\n  fb = new PlatformPixelBuffer(w(), h());\n\n  pixel = 0;\n  fb->fillRect(fb->getRect(), &pixel);\n\n  show();\n}\n\nvoid TestWindow::stop()\n{\n  hide();\n\n  delete fb;\n  fb = nullptr;\n\n  Fl::remove_idle(timer, this);\n}\n\nvoid TestWindow::draw()\n{\n  int X, Y, W, H;\n\n  // We cannot update the damage region from inside the draw function,\n  // so delegate this to an idle function\n  Fl::add_idle(timer, this);\n\n  // Check what actually needs updating\n  fl_clip_box(0, 0, w(), h(), X, Y, W, H);\n  if ((W == 0) || (H == 0))\n    return;\n\n  fb->draw(X, Y, X, Y, W, H);\n\n  pixels += W*H;\n  frames++;\n}\n\nvoid TestWindow::flush()\n{\n  startTimeCounter();\n  Fl_Window::flush();\n#if !defined(WIN32) && !defined(__APPLE__)\n  // Make sure we measure any work we queue up\n  XSync(fl_display, False);\n#endif\n  endTimeCounter();\n\n  time += getTimeCounter();\n}\n\nvoid TestWindow::update()\n{\n  core::Rect r;\n\n  startTimeCounter();\n\n  changefb();\n\n  r = fb->getDamage();\n  damage(FL_DAMAGE_USER1, r.tl.x, r.tl.y, r.width(), r.height());\n\n#if !defined(WIN32) && !defined(__APPLE__)\n  // Make sure we measure any work we queue up\n  XSync(fl_display, False);\n#endif\n\n  endTimeCounter();\n\n  time += getTimeCounter();\n}\n\nvoid TestWindow::changefb()\n{\n  uint32_t pixel;\n\n  pixel = rand();\n  fb->fillRect(fb->getRect(), &pixel);\n}\n\nvoid TestWindow::timer(void* data)\n{\n  TestWindow* self;\n\n  Fl::remove_idle(timer, data);\n\n  self = (TestWindow*)data;\n  self->update();\n}\n\nvoid PartialTestWindow::changefb()\n{\n  core::Rect r;\n  uint32_t pixel;\n\n  r = fb->getRect();\n  r.tl.x += w() / 4;\n  r.tl.y += h() / 4;\n  r.br.x -= w() / 4;\n  r.br.y -= h() / 4;\n\n  pixel = rand();\n  fb->fillRect(r, &pixel);\n}\n\nOverlayTestWindow::OverlayTestWindow() :\n  overlay(nullptr), offscreen(nullptr)\n{\n}\n\nvoid OverlayTestWindow::start(int width, int height)\n{\n  PartialTestWindow::start(width, height);\n\n  overlay = new Surface(400, 200);\n  overlay->clear(0xff, 0x80, 0x00, 0xcc);\n\n  // X11 needs an off screen buffer for compositing to avoid flicker,\n  // and alpha blending doesn't work for windows on Win32\n#if !defined(__APPLE__)\n  offscreen = new Surface(w(), h());\n#else\n  offscreen = nullptr;\n#endif\n}\n\nvoid OverlayTestWindow::stop()\n{\n  PartialTestWindow::stop();\n\n  delete offscreen;\n  offscreen = nullptr;\n  delete overlay;\n  overlay = nullptr;\n}\n\nvoid OverlayTestWindow::draw()\n{\n  int ox, oy, ow, oh;\n  int X, Y, W, H;\n\n  // We cannot update the damage region from inside the draw function,\n  // so delegate this to an idle function\n  Fl::add_idle(timer, this);\n\n  // Check what actually needs updating\n  fl_clip_box(0, 0, w(), h(), X, Y, W, H);\n  if ((W == 0) || (H == 0))\n    return;\n\n  // We might get a redraw before we are fully ready\n  if (!overlay)\n    return;\n\n  // Simplify the clip region to a simple rectangle in order to\n  // properly draw all the layers even if they only partially overlap\n  fl_push_no_clip();\n  fl_push_clip(X, Y, W, H);\n\n  if (offscreen)\n    fb->draw(offscreen, X, Y, X, Y, W, H);\n  else\n    fb->draw(X, Y, X, Y, W, H);\n\n  pixels += W*H;\n  frames++;\n\n  ox = (w() - overlay->width()) / 2;\n  oy = h() / 4 - overlay->height() / 2;\n  ow = overlay->width();\n  oh = overlay->height();\n  fl_clip_box(ox, oy, ow, oh, X, Y, W, H);\n  if ((W != 0) && (H != 0)) {\n    if (offscreen)\n      overlay->blend(offscreen, X - ox, Y - oy, X, Y, W, H);\n    else\n      overlay->blend(X - ox, Y - oy, X, Y, W, H);\n  }\n\n  fl_pop_clip();\n  fl_pop_clip();\n\n  if (offscreen) {\n    fl_clip_box(0, 0, w(), h(), X, Y, W, H);\n    offscreen->draw(X, Y, X, Y, W, H);\n  }\n}\n\nstatic void dosubtest(TestWindow* win, int width, int height,\n                      unsigned long long* pixels,\n\t\t      unsigned long long* frames,\n\t\t      double* time)\n{\n  struct timeval start;\n\n  win->start(width, height);\n\n  gettimeofday(&start, nullptr);\n  while (core::msSince(&start) < 3000)\n    Fl::wait();\n\n  win->stop();\n\n  *pixels = win->pixels;\n  *frames = win->frames;\n  *time = win->time;\n}\n\nstatic bool is_constant(double a, double b)\n{\n    return (fabs(a - b) / a) < 0.1;\n}\n\nstatic void dotest(TestWindow* win)\n{\n  unsigned long long pixels[3];\n  unsigned long long frames[3];\n  double time[3];\n\n  double delay, rate;\n\n  // Run the test several times at different resolutions...\n  dosubtest(win, 800, 600, &pixels[0], &frames[0], &time[0]);\n  dosubtest(win, 1024, 768, &pixels[1], &frames[1], &time[1]);\n  dosubtest(win, 1280, 960, &pixels[2], &frames[2], &time[2]);\n\n  // ...in order to compute how much of the rendering time is static,\n  // and how much depends on the number of pixels\n  // (i.e. solve: time = delay * frames + rate * pixels)\n  delay = (((time[0] - (double)pixels[0] / pixels[1] * time[1]) /\n            (frames[0] - (double)pixels[0] / pixels[1] * frames[1])) +\n           ((time[1] - (double)pixels[1] / pixels[2] * time[2]) /\n            (frames[1] - (double)pixels[1] / pixels[2] * frames[2]))) / 2.0;\n  rate = (((time[0] - (double)frames[0] / frames[1] * time[1]) /\n           (pixels[0] - (double)frames[0] / frames[1] * pixels[1])) +\n          ((time[1] - (double)frames[1] / frames[2] * time[2]) /\n           (pixels[1] - (double)frames[1] / frames[2] * pixels[2]))) / 2.0;\n\n  // However, we have some corner cases:\n\n  // We are restricted by some delay, e.g. refresh rate\n  if (is_constant(frames[0]/time[0], frames[2]/time[2])) {\n    fprintf(stderr, \"Warning: Fixed delay dominating updates.\\n\\n\");\n    delay = time[2]/frames[2];\n    rate = 0.0;\n  }\n\n  // There isn't any fixed delay, we are only restricted by pixel\n  // throughput\n  if (fabs(delay) < 0.001) {\n    delay = 0.0;\n    rate = time[2]/pixels[2];\n  }\n\n  // We can hit cache limits that causes performance to drop\n  // with increasing update size, screwing up our calculations\n  if ((pixels[2] / time[2]) < (pixels[0] / time[0] * 0.9)) {\n    fprintf(stderr, \"Warning: Unexpected behaviour. Measurement unreliable.\\n\\n\");\n\n    // We can't determine the proportions between these, so divide the\n    // time spent evenly\n    delay = time[2] / 2.0 / frames[2];\n    rate = time[2] / 2.0 / pixels[2];\n  }\n\n  fprintf(stderr, \"Rendering delay: %g ms/frame\\n\", delay * 1000.0);\n  fprintf(stderr, \"Rendering rate: %s\\n\",\n          (rate == 0.0) ? \"N/A pixels/s\" :\n                          core::siPrefix(1.0 / rate, \"pixels/s\").c_str());\n  fprintf(stderr, \"Maximum FPS: %g fps @ 1920x1080\\n\",\n          1.0 / (delay + rate * 1920 * 1080));\n}\n\nint main(int /*argc*/, char** /*argv*/)\n{\n  TestWindow* win;\n\n  fprintf(stderr, \"Full window update:\\n\\n\");\n  win = new TestWindow();\n  dotest(win);\n  delete win;\n  fprintf(stderr, \"\\n\");\n\n  fprintf(stderr, \"Partial window update:\\n\\n\");\n  win = new PartialTestWindow();\n  dotest(win);\n  delete win;\n  fprintf(stderr, \"\\n\");\n\n  fprintf(stderr, \"Partial window update with overlay:\\n\\n\");\n  win = new OverlayTestWindow();\n  dotest(win);\n  delete win;\n  fprintf(stderr, \"\\n\");\n\n  return 0;\n}\n"
  },
  {
    "path": "tests/perf/results/multicore/README",
    "content": "This directory contains the evaluation of the multi-core implementation\nin the decoder. The baseline is the performance before the addition of\nthe DecodeManager class.\n\nTests were performed on the following systems:\n\n - eLux RP Atom N270 1.6 GHz\n - Lubuntu 13.10 i.MX6 Quad 1.2 GHz\n - Fedora 22 i7-3770 3.4 GHz\n - Windows Vista Core 2 Duo E7400 2.8 GHz\n - Windows 10 i3-4170 3.7 GHz\n - OS X 10.6 Core 2 Duo 2.53 GHz\n - OS X 10.11 i5 2.3 GHz\n\nThe systems were tested with:\n\n a) The old, baseline code\n b) The new code with all CPUs enabled\n c) The new code with only one CPU enabled\n\nThe test itself consists of running decperf on the test files from the\nTurboVNC project. Rate of decoding is then compared to the baseline.\nNote that the CPU time is divided by core usage in the multi CPU cases\nin order to derive total decoding time. This method is sensitive to\nother load on the system.\n\nOn average, there is no regression in performance for single CPU\nsystems. This however relies on the addition of the single CPU shortcut\nin DecodeManager. Without that the performance sees a 10% lower rate.\n\nDual CPU systems see between 20% and 50% increase, and the quad core\nsystems between 75% and 125% on average. OS X is an outlier though in\nthat it gets a mere 32% increase on average. It is unknown why at this\npoint and tracing doesn't reveal anything obvious. It may be because it\nis not a true quad core system, but rather uses HyperThreading.\n\nSo in summary, the new code can do a noticeable improvement on decoding\ntime. However it does so at a cost of efficiency. Four times the CPUs\nonly gives you about twice the performance. More improvements may be\npossible.\n"
  },
  {
    "path": "tests/perf/results/notrans/README",
    "content": "This directory contains the test results in preparation for the removal\nof the PixelTransformer class.\n\nTests were performed on Linux with these CPUs:\n\n - Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz\n - ARM i.MX6 DualLite @ 1 GHz\n\nThe tests show that the new bufferFromBuffer() has similar performance\nas PixelTransformer in most cases. It gets beaten in two cases:\n\n - Input format is 16 BPP and PixelTransformer is in the\n   non-economical mode (the default mode).\n\n - Input format is 8 BPP, mode irrelevant.\n\nPixelTransformer is about twice as fast in both these cases (more if\nconverting between two low colour formats).\n\nAlthough this is significant, it is in cases that are already difficult\nto deal with performance wise, and exceedingly rare with modern\nhardware. As such it is difficult to motivate the extra complexity that\nPixelTransformer requires.\n\nIf it turns out that these cases are significant, than we can move\nPixelTransformer's massive lookup tables into a shared cache in\nPixelFormat. Implementation complexity would be similar, but at least\nwe would have a friendly API.\n"
  },
  {
    "path": "tests/perf/results/notrans/armhf.csv",
    "content": "# Pixel Conversion Test 2014-07-09 14:23 UTC\n#\n# Frame buffer: 4096x4096 pixels\n# Tile size: 64x64 pixels\n#\n# Note: Results are Mpixels/sec\n#\nSource format,Destination Format,memcpy,PixelTransformer,bufferFromBuffer,rgbFromBuffer,bufferFromRGB\n\ndepth 24 (32bpp) little-endian rgb888,depth 24 (32bpp) little-endian rgb888,67.5908,67.3684,66.8189,54.3236,59.1908\ndepth 24 (32bpp) little-endian bgr888,depth 24 (32bpp) little-endian rgb888,67.5908,33.2468,45.2097,54.3236,58.8506\ndepth 16 (16bpp) little-endian rgb565,depth 24 (32bpp) little-endian rgb888,62.0606,24.6896,16.8076,22.5924,59.5349\ndepth 7 (8bpp) rgb232,depth 24 (32bpp) little-endian rgb888,61.6867,63.2099,19.5887,23.5132,59.7956\n\ndepth 24 (32bpp) little-endian rgb888,depth 16 (16bpp) little-endian rgb565,96.8321,31.5562,40.3945,54.3236,25.0673\ndepth 16 (16bpp) little-endian bgr565,depth 16 (16bpp) little-endian rgb565,104.757,31.7766,13.3725,22.5303,25.1443\ndepth 7 (8bpp) rgb232,depth 16 (16bpp) little-endian rgb565,95.9251,61.594,15.1535,23.5132,25.098\n\ndepth 24 (32bpp) little-endian rgb888,depth 7 (8bpp) rgb232,133.42,34.5654,32.6115,54.3236,33.0056\ndepth 16 (16bpp) little-endian rgb565,depth 7 (8bpp) rgb232,133.42,42.1833,15.7842,22.5303,32.7942\ndepth 7 (8bpp) bgr232,depth 7 (8bpp) rgb232,137.45,75.7116,16.8699,23.5132,33.0056\n\ndepth 24 (32bpp) little-endian bgr888,depth 24 (32bpp) big-endian bgr888,67.5908,33.2738,45.2597,54.3957,58.9353\ndepth 24 (32bpp) big-endian bgr888,depth 24 (32bpp) little-endian bgr888,67.7025,NaN,45.3097,54.1799,59.0202\ndepth 16 (16bpp) little-endian bgr565,depth 16 (16bpp) big-endian bgr565,105.567,31.7766,13.8425,21.49,24.9756\ndepth 16 (16bpp) big-endian bgr565,depth 16 (16bpp) little-endian bgr565,105.84,NaN,12.3746,20.9086,25.1443\n"
  },
  {
    "path": "tests/perf/results/notrans/i386.csv",
    "content": "# Pixel Conversion Test 2014-07-09 14:14 UTC\n#\n# Frame buffer: 4096x4096 pixels\n# Tile size: 64x64 pixels\n#\n# Note: Results are Mpixels/sec\n#\nSource format,Destination Format,memcpy,PixelTransformer,bufferFromBuffer,rgbFromBuffer,bufferFromRGB\n\ndepth 24 (32bpp) little-endian rgb888,depth 24 (32bpp) little-endian rgb888,568.889,561.096,602.353,338.512,525.128\ndepth 24 (32bpp) little-endian bgr888,depth 24 (32bpp) little-endian rgb888,561.096,215.579,280.548,338.512,525.128\ndepth 16 (16bpp) little-endian rgb565,depth 24 (32bpp) little-endian rgb888,602.353,405.545,185.339,146.81,531.948\ndepth 7 (8bpp) rgb232,depth 24 (32bpp) little-endian rgb888,640,531.948,192.3,170.667,546.133\n\ndepth 24 (32bpp) little-endian rgb888,depth 16 (16bpp) little-endian rgb565,853.333,217.872,235.402,344.202,256\ndepth 16 (16bpp) little-endian bgr565,depth 16 (16bpp) little-endian rgb565,871.489,455.111,89.4323,146.81,256\ndepth 7 (8bpp) rgb232,depth 16 (16bpp) little-endian rgb565,952.558,568.889,94.8148,167.184,251.288\n\ndepth 24 (32bpp) little-endian rgb888,depth 7 (8bpp) rgb232,1107.03,235.402,231.412,341.333,278.639\ndepth 16 (16bpp) little-endian rgb565,depth 7 (8bpp) rgb232,1137.78,481.882,95.2558,144.735,276.757\ndepth 7 (8bpp) bgr232,depth 7 (8bpp) rgb232,1204.71,553.514,101.136,169.256,280.548\n\ndepth 24 (32bpp) little-endian bgr888,depth 24 (32bpp) big-endian bgr888,568.889,212.228,276.757,338.512,525.128\ndepth 24 (32bpp) big-endian bgr888,depth 24 (32bpp) little-endian bgr888,576.901,NaN,278.639,338.512,525.128\ndepth 16 (16bpp) little-endian bgr565,depth 16 (16bpp) big-endian bgr565,890.435,455.111,89.4323,146.81,243.81\ndepth 16 (16bpp) big-endian bgr565,depth 16 (16bpp) little-endian bgr565,871.489,NaN,85.3333,146.286,254.41\n"
  },
  {
    "path": "tests/perf/results/notrans/x86_64.csv",
    "content": "# Pixel Conversion Test 2014-07-09 14:14 UTC\n#\n# Frame buffer: 4096x4096 pixels\n# Tile size: 64x64 pixels\n#\n# Note: Results are Mpixels/sec\n#\nSource format,Destination Format,memcpy,PixelTransformer,bufferFromBuffer,rgbFromBuffer,bufferFromRGB\n\ndepth 24 (32bpp) little-endian rgb888,depth 24 (32bpp) little-endian rgb888,576.901,576.901,546.133,338.512,602.353\ndepth 24 (32bpp) little-endian bgr888,depth 24 (32bpp) little-endian rgb888,585.143,251.288,288.451,335.738,602.353\ndepth 16 (16bpp) little-endian rgb565,depth 24 (32bpp) little-endian rgb888,585.143,405.545,205.829,162.54,620.606\ndepth 7 (8bpp) rgb232,depth 24 (32bpp) little-endian rgb888,493.494,505.679,267.712,177.316,620.606\n\ndepth 24 (32bpp) little-endian rgb888,depth 16 (16bpp) little-endian rgb565,999.024,231.412,257.61,344.202,265.974\ndepth 16 (16bpp) little-endian bgr565,depth 16 (16bpp) little-endian rgb565,975.238,455.111,101.638,165.161,267.712\ndepth 7 (8bpp) rgb232,depth 16 (16bpp) little-endian rgb565,1050.26,576.901,105.296,181.239,269.474\n\ndepth 24 (32bpp) little-endian rgb888,depth 7 (8bpp) rgb232,1638.4,259.24,271.258,347.119,298.978\ndepth 16 (16bpp) little-endian rgb565,depth 7 (8bpp) rgb232,1575.38,505.679,105.026,165.161,294.676\ndepth 7 (8bpp) bgr232,depth 7 (8bpp) rgb232,1706.67,602.353,107.225,183.677,298.978\n\ndepth 24 (32bpp) little-endian bgr888,depth 24 (32bpp) big-endian bgr888,593.623,251.288,286.434,338.512,620.606\ndepth 24 (32bpp) big-endian bgr888,depth 24 (32bpp) little-endian bgr888,593.623,NaN,282.483,344.202,611.343\ndepth 16 (16bpp) little-endian bgr565,depth 16 (16bpp) big-endian bgr565,1050.26,450.11,97.7566,166.504,259.24\ndepth 16 (16bpp) big-endian bgr565,depth 16 (16bpp) little-endian bgr565,999.024,NaN,96.6038,155.152,267.712\n"
  },
  {
    "path": "tests/perf/util.cxx",
    "content": "/* Copyright 2013-2014 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n#ifdef WIN32\n#include <windows.h>\n#else\n#include <sys/resource.h>\n#include <sys/time.h>\n#endif\n\n#include \"util.h\"\n\n#ifdef WIN32\ntypedef struct {\n  FILETIME kernelTime;\n  FILETIME userTime;\n} syscounter_t;\n#else\ntypedef struct rusage syscounter_t;\n#endif\n\nstatic syscounter_t _globalCounter[2];\nstatic cpucounter_t globalCounter = _globalCounter;\n\nvoid startCpuCounter(void)\n{\n  startCpuCounter(globalCounter);\n}\n\nvoid endCpuCounter(void)\n{\n  endCpuCounter(globalCounter);\n}\n\ndouble getCpuCounter(void)\n{\n  return getCpuCounter(globalCounter);\n}\n\ncpucounter_t newCpuCounter(void)\n{\n  syscounter_t *c;\n\n  c = (syscounter_t*)malloc(sizeof(syscounter_t) * 2);\n  if (c == nullptr)\n    return nullptr;\n\n  memset(c, 0, sizeof(syscounter_t) * 2);\n\n  return c;\n}\n\nvoid freeCpuCounter(cpucounter_t c)\n{\n  free(c);\n}\n\nstatic void measureCpu(syscounter_t *counter)\n{\n#ifdef WIN32\n  FILETIME dummy1, dummy2;\n\n  GetProcessTimes(GetCurrentProcess(), &dummy1, &dummy2,\n                  &counter->kernelTime, &counter->userTime);\n#else\n  getrusage(RUSAGE_SELF, counter);\n#endif\n}\n\nvoid startCpuCounter(cpucounter_t c)\n{\n  syscounter_t *s = (syscounter_t*)c;\n  measureCpu(&s[0]);\n}\n\nvoid endCpuCounter(cpucounter_t c)\n{\n  syscounter_t *s = (syscounter_t*)c;\n  measureCpu(&s[1]);\n}\n\ndouble getCpuCounter(cpucounter_t c)\n{\n  syscounter_t *s = (syscounter_t*)c;\n  double sysSeconds, userSeconds;\n\n#ifdef WIN32\n  uint64_t counters[2];\n\n  counters[0] = (uint64_t)s[0].kernelTime.dwHighDateTime << 32 |\n                s[0].kernelTime.dwLowDateTime;\n  counters[1] = (uint64_t)s[1].kernelTime.dwHighDateTime << 32 |\n                s[1].kernelTime.dwLowDateTime;\n\n  sysSeconds = (double)(counters[1] - counters[0]) / 10000000.0;\n\n  counters[0] = (uint64_t)s[0].userTime.dwHighDateTime << 32 |\n                s[0].userTime.dwLowDateTime;\n  counters[1] = (uint64_t)s[1].userTime.dwHighDateTime << 32 |\n                s[1].userTime.dwLowDateTime;\n\n  userSeconds = (double)(counters[1] - counters[0]) / 10000000.0;\n#else\n  sysSeconds = (double)(s[1].ru_stime.tv_sec -\n                        s[0].ru_stime.tv_sec);\n  sysSeconds += (double)(s[1].ru_stime.tv_usec -\n                         s[0].ru_stime.tv_usec) / 1000000.0;\n\n  userSeconds = (double)(s[1].ru_utime.tv_sec -\n                         s[0].ru_utime.tv_sec);\n  userSeconds += (double)(s[1].ru_utime.tv_usec -\n                          s[0].ru_utime.tv_usec) / 1000000.0;\n#endif\n\n  return sysSeconds + userSeconds;\n}\n\n#ifdef WIN32\nstatic LARGE_INTEGER timeStart, timeEnd;\n#else\nstatic struct timeval timeStart, timeEnd;\n#endif\n\nvoid startTimeCounter(void)\n{\n#ifdef WIN32\n  QueryPerformanceCounter(&timeStart);\n#else\n  gettimeofday(&timeStart, nullptr);\n#endif\n}\n\nvoid endTimeCounter(void)\n{\n#ifdef WIN32\n  QueryPerformanceCounter(&timeEnd);\n#else\n  gettimeofday(&timeEnd, nullptr);\n#endif\n}\n\ndouble getTimeCounter(void)\n{\n  double time;\n\n#ifdef WIN32\n  LARGE_INTEGER freq;\n\n  QueryPerformanceFrequency(&freq);\n\n  time = timeEnd.QuadPart - timeStart.QuadPart;\n  time = time / freq.QuadPart;\n#else\n  time = (double)timeEnd.tv_sec - timeStart.tv_sec;\n  time += (double)(timeEnd.tv_usec - timeStart.tv_usec) / 1000000.0;\n#endif\n\n  return time;\n}\n"
  },
  {
    "path": "tests/perf/util.h",
    "content": "/* Copyright 2013-2014 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __TESTS_UTIL_H__\n#define __TESTS_UTIL_H__\n\ntypedef void* cpucounter_t;\n\nvoid startCpuCounter(void);\nvoid endCpuCounter(void);\n\ndouble getCpuCounter(void);\n\ncpucounter_t newCpuCounter(void);\nvoid freeCpuCounter(cpucounter_t c);\n\nvoid startCpuCounter(cpucounter_t c);\nvoid endCpuCounter(cpucounter_t c);\n\ndouble getCpuCounter(cpucounter_t c);\n\nvoid startTimeCounter(void);\nvoid endTimeCounter(void);\n\ndouble getTimeCounter(void);\n\n#endif\n"
  },
  {
    "path": "tests/unit/CMakeLists.txt",
    "content": "include(GoogleTest)\n\n# Google Test requires a new C++ standard\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=gnu++17\")\n\nenable_testing()\n\ninclude_directories(${CMAKE_SOURCE_DIR}/common)\ninclude_directories(${CMAKE_SOURCE_DIR}/vncviewer)\n\nadd_executable(configargs configargs.cxx)\ntarget_link_libraries(configargs rfb GTest::gtest_main)\ngtest_discover_tests(configargs)\n\nadd_executable(conv conv.cxx)\ntarget_link_libraries(conv rfb GTest::gtest_main)\ngtest_discover_tests(conv)\n\nadd_executable(convertlf convertlf.cxx)\ntarget_link_libraries(convertlf core GTest::gtest_main)\ngtest_discover_tests(convertlf)\n\nadd_executable(gesturehandler gesturehandler.cxx ../../vncviewer/GestureHandler.cxx)\ntarget_link_libraries(gesturehandler core GTest::gtest_main)\ngtest_discover_tests(gesturehandler)\n\nadd_executable(hostport hostport.cxx)\ntarget_link_libraries(hostport network GTest::gtest_main)\ngtest_discover_tests(hostport)\n\nadd_executable(parameters parameters.cxx)\ntarget_link_libraries(parameters core GTest::gtest_main)\ngtest_discover_tests(parameters)\n\nadd_executable(pixelformat pixelformat.cxx)\ntarget_link_libraries(pixelformat rfb GTest::gtest_main)\ngtest_discover_tests(pixelformat)\n\nadd_executable(shortcuthandler shortcuthandler.cxx ../../vncviewer/ShortcutHandler.cxx)\ntarget_link_libraries(shortcuthandler core ${Intl_LIBRARIES} GTest::gtest_main)\ngtest_discover_tests(shortcuthandler)\n\nadd_executable(unicode unicode.cxx)\ntarget_link_libraries(unicode core GTest::gtest_main)\ngtest_discover_tests(unicode)\n\nadd_executable(emulatemb emulatemb.cxx ../../vncviewer/EmulateMB.cxx)\ntarget_include_directories(emulatemb SYSTEM PUBLIC ${Intl_INCLUDE_DIR})\ntarget_link_libraries(emulatemb core ${Intl_LIBRARIES} GTest::gtest_main)\ngtest_discover_tests(emulatemb)\n"
  },
  {
    "path": "tests/unit/configargs.cxx",
    "content": "/* Copyright 2025 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <gtest/gtest.h>\n\n#include <core/Configuration.h>\n\nstatic core::BoolParameter boolparam(\"boolparam\", \"\", false);\nstatic core::IntParameter intparam(\"intparam\", \"\", 0);\nstatic core::StringParameter strparam(\"strparam\", \"\", \"\");\n\nTEST(ConfigArgs, args)\n{\n  int ret;\n  std::vector<const char*> argv;\n\n  boolparam.setParam(true);\n  intparam.setParam(1);\n  strparam.setParam(\"test\");\n\n  // Just program name\n  argv = {\"prog\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 0);\n  EXPECT_EQ(ret, 0);\n  EXPECT_EQ(boolparam, true);\n  EXPECT_EQ(intparam, 1);\n  EXPECT_STREQ(strparam, \"test\");\n\n  // A bunch of standard arguments\n  argv = {\"prog\", \"arg1\", \"arg2\", \"arg3\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 2);\n  EXPECT_EQ(ret, 0);\n  EXPECT_EQ(boolparam, true);\n  EXPECT_EQ(intparam, 1);\n  EXPECT_STREQ(strparam, \"test\");\n\n  // A parameter without any dash\n  argv = {\"prog\", \"strparam\", \"intparam\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 0);\n  EXPECT_EQ(boolparam, true);\n  EXPECT_EQ(intparam, 1);\n  EXPECT_STREQ(strparam, \"test\");\n}\n\nTEST(ConfigArgs, noDash)\n{\n  int ret;\n  std::vector<const char*> argv;\n\n  boolparam.setParam(true);\n  intparam.setParam(1);\n  strparam.setParam(\"test\");\n\n  // int argument\n  argv = {\"prog\", \"intparam=12\", \"34\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(intparam, 12);\n\n  // string argument\n  argv = {\"prog\", \"strparam=foo\", \"bar\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_STREQ(strparam, \"foo\");\n\n  // empty string argument\n  argv = {\"prog\", \"strparam=\", \"bar\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_STREQ(strparam, \"\");\n\n  // Bad parameter\n  argv = {\"prog\", \"fooparam=123\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 0);\n}\n\nTEST(ConfigArgs, singleDash)\n{\n  int ret;\n  std::vector<const char*> argv;\n\n  boolparam.setParam(true);\n  intparam.setParam(1);\n  strparam.setParam(\"test\");\n\n  // int argument\n  argv = {\"prog\", \"-intparam\", \"12\", \"34\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 2);\n  EXPECT_EQ(intparam, 12);\n\n  // int argument with equals\n  argv = {\"prog\", \"-intparam=12\", \"34\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(intparam, 12);\n\n  // string argument\n  argv = {\"prog\", \"-strparam\", \"foo\", \"bar\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 2);\n  EXPECT_STREQ(strparam, \"foo\");\n\n  // string argument with equals\n  argv = {\"prog\", \"-strparam=foo\", \"bar\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_STREQ(strparam, \"foo\");\n\n  // empty string argument with equals\n  argv = {\"prog\", \"-strparam=\", \"bar\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_STREQ(strparam, \"\");\n\n  // Missing argument\n  intparam.setParam(1);\n  argv = {\"prog\", \"-intparam\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 0);\n  EXPECT_EQ(intparam, 1);\n\n  // Bad parameter\n  argv = {\"prog\", \"-fooparam\", \"123\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 0);\n\n  // Bad parameter with equals\n  argv = {\"prog\", \"-fooparam=123\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 0);\n}\n\nTEST(ConfigArgs, doubleDash)\n{\n  int ret;\n  std::vector<const char*> argv;\n\n  boolparam.setParam(true);\n  intparam.setParam(1);\n  strparam.setParam(\"test\");\n\n  // int argument\n  argv = {\"prog\", \"--intparam\", \"12\", \"34\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 2);\n  EXPECT_EQ(intparam, 12);\n\n  // int argument with equals\n  argv = {\"prog\", \"--intparam=12\", \"34\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(intparam, 12);\n\n  // string argument\n  argv = {\"prog\", \"--strparam\", \"foo\", \"bar\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 2);\n  EXPECT_STREQ(strparam, \"foo\");\n\n  // string argument with equals\n  argv = {\"prog\", \"--strparam=foo\", \"bar\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_STREQ(strparam, \"foo\");\n\n  // empty string argument with equals\n  argv = {\"prog\", \"--strparam=\", \"bar\" };\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_STREQ(strparam, \"\");\n\n  // Missing argument\n  intparam.setParam(1);\n  argv = {\"prog\", \"--intparam\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 0);\n  EXPECT_EQ(intparam, 1);\n\n  // Bad parameter\n  argv = {\"prog\", \"--fooparam\", \"123\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 0);\n\n  // Bad parameter with equals\n  argv = {\"prog\", \"--fooparam=123\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 0);\n}\n\nTEST(ConfigArgs, bool)\n{\n  int ret;\n  std::vector<const char*> argv;\n\n  // solo bool (single)\n  boolparam.setParam(false);\n  argv = {\"prog\", \"-boolparam\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(boolparam, true);\n\n  // solo bool (double)\n  boolparam.setParam(false);\n  argv = {\"prog\", \"--boolparam\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(boolparam, true);\n\n  // bool argument (single)\n  boolparam.setParam(true);\n  argv = {\"prog\", \"-boolparam\", \"off\", \"on\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 2);\n  EXPECT_EQ(boolparam, false);\n\n  // bool argument (double)\n  boolparam.setParam(true);\n  argv = {\"prog\", \"--boolparam\", \"off\", \"on\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 2);\n  EXPECT_EQ(boolparam, false);\n\n  // bool argument equals (single)\n  boolparam.setParam(true);\n  argv = {\"prog\", \"-boolparam=off\", \"on\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(boolparam, false);\n\n  // bool argument equals (double)\n  boolparam.setParam(true);\n  argv = {\"prog\", \"--boolparam=off\", \"on\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(boolparam, false);\n\n  // empty bool argument equals (single)\n  boolparam.setParam(true);\n  argv = {\"prog\", \"-boolparam=\", \"on\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(boolparam, true);\n\n  // empty bool argument equals (double)\n  boolparam.setParam(true);\n  argv = {\"prog\", \"--boolparam=\", \"on\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(boolparam, true);\n\n  // bool bad argument (single)\n  boolparam.setParam(false);\n  argv = {\"prog\", \"-boolparam\", \"foo\", \"off\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(boolparam, true);\n\n  // bool bad argument (double)\n  boolparam.setParam(false);\n  argv = {\"prog\", \"--boolparam\", \"foo\", \"off\"};\n  ret = core::Configuration::handleParamArg(argv.size(),\n                                            (char**)argv.data(), 1);\n  EXPECT_EQ(ret, 1);\n  EXPECT_EQ(boolparam, true);\n}\n\nint main(int argc, char** argv)\n{\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "tests/unit/conv.cxx",
    "content": "/* Copyright 2013-2025 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string.h>\n\n#include <list>\n\n#include <gtest/gtest.h>\n\n#include <rfb/PixelFormat.h>\n\nstatic const uint8_t pixelRed = 0xf1;\nstatic const uint8_t pixelGreen = 0xc3;\nstatic const uint8_t pixelBlue = 0x97;\n\nstatic const int fbWidth = 40;\nstatic const int fbHeight = 30;\nstatic const int fbArea = fbWidth * fbHeight;\n// Maximum bpp, plus some room for unaligned fudging\nstatic const int fbMalloc = (fbArea * 4) + 4;\n\ntypedef bool (*testfn) (const rfb::PixelFormat&, const rfb::PixelFormat&);\n\nstruct TestEntry {\n  const char *label;\n  testfn fn;\n};\n\n#define min(a,b) (((a) < (b)) ? (a) : (b))\n\nnamespace rfb {\n\nvoid makePixel(const rfb::PixelFormat &pf,\n               uint8_t *buffer)\n{\n  rfb::Pixel p;\n\n  p = 0;\n  p |= (pixelRed >> (8 - pf.redBits)) << pf.redShift;\n  p |= (pixelGreen >> (8 - pf.greenBits)) << pf.greenShift;\n  p |= (pixelBlue >> (8 - pf.blueBits)) << pf.blueShift;\n\n  // FIXME: Should we reimplement this as well?\n  pf.bufferFromPixel(buffer, p);\n}\n\nvoid verifyPixel(const rfb::PixelFormat &dstpf,\n                 const rfb::PixelFormat &srcpf,\n                 const uint8_t *buffer)\n{\n  rfb::Pixel p;\n  int r, g, b;\n  int re, ge, be;\n\n  // FIXME: Should we reimplement this as well?\n  p = dstpf.pixelFromBuffer(buffer);\n\n  r = (p >> dstpf.redShift) & dstpf.redMax;\n  g = (p >> dstpf.greenShift) & dstpf.greenMax;\n  b = (p >> dstpf.blueShift) & dstpf.blueMax;\n\n  r = (r * 255 + dstpf.redMax/2) / dstpf.redMax;\n  g = (g * 255 + dstpf.greenMax/2) / dstpf.greenMax;\n  b = (b * 255 + dstpf.blueMax/2) / dstpf.blueMax;\n\n  // The allowed error depends on:\n  //\n  //  a) The number of bits the format can hold\n  //  b) The number of bits the source format could hold\n\n  re = (1 << (8 - min(dstpf.redBits, srcpf.redBits))) - 1;\n  ge = (1 << (8 - min(dstpf.greenBits, srcpf.greenBits))) - 1;\n  be = (1 << (8 - min(dstpf.blueBits, srcpf.blueBits))) - 1;\n\n  EXPECT_NEAR(r, pixelRed, re);\n  EXPECT_NEAR(g, pixelGreen, ge);\n  EXPECT_NEAR(b, pixelBlue, be);\n}\n\n}\n\ntypedef std::pair<rfb::PixelFormat, rfb::PixelFormat> TestPair;\ntypedef testing::TestWithParam<TestPair> Conv;\n\nnamespace rfb {\n\nstatic std::ostream& operator<<(std::ostream& os, const PixelFormat& pf)\n{\n  char b[256];\n  pf.print(b, sizeof(b));\n  return os << b;\n}\n\n}\n\nusing rfb::makePixel;\nusing rfb::verifyPixel;\n\nTEST_P(Conv, pixelFromPixel)\n{\n  rfb::Pixel p;\n  uint8_t buffer[4];\n\n  const rfb::PixelFormat &srcpf = GetParam().first;\n  const rfb::PixelFormat &dstpf = GetParam().second;\n\n  makePixel(srcpf, buffer);\n\n  p = srcpf.pixelFromBuffer(buffer);\n  p = dstpf.pixelFromPixel(srcpf, p);\n  memset(buffer, 0, sizeof(buffer));\n  dstpf.bufferFromPixel(buffer, p);\n\n  verifyPixel(dstpf, srcpf, buffer);\n}\n\nTEST_P(Conv, bufferFromBuffer)\n{\n  int i, x, y, unaligned;\n  uint8_t bufIn[fbMalloc], bufOut[fbMalloc];\n\n  const rfb::PixelFormat &srcpf = GetParam().first;\n  const rfb::PixelFormat &dstpf = GetParam().second;\n\n  // Once aligned, and once unaligned\n  for (unaligned = 0;unaligned < 2;unaligned++) {\n    for (i = 0;i < fbArea;i++)\n      makePixel(srcpf, bufIn + unaligned + i*srcpf.bpp/8);\n\n    memset(bufOut, 0, sizeof(bufOut));\n    dstpf.bufferFromBuffer(bufOut + unaligned, srcpf,\n                           bufIn + unaligned, fbArea);\n\n    for (i = 0;i < fbArea;i++) {\n      verifyPixel(dstpf, srcpf, bufOut + unaligned + i*dstpf.bpp/8);\n      if (testing::Test::HasFailure())\n        return;\n    }\n\n    memset(bufIn, 0, sizeof(bufIn));\n    for (y = 0;y < fbHeight;y++) {\n      for (x = 0;x < fbWidth/2;x++)\n        makePixel(srcpf, bufIn + unaligned + (x + y*fbWidth)*srcpf.bpp/8);\n    }\n\n    memset(bufOut, 0, sizeof(bufOut));\n    dstpf.bufferFromBuffer(bufOut + unaligned, srcpf, bufIn + unaligned,\n                           fbWidth/2, fbHeight, fbWidth, fbWidth);\n\n    for (y = 0;y < fbHeight;y++) {\n      for (x = 0;x < fbWidth;x++) {\n        const uint8_t* pixel;\n        pixel = bufOut + unaligned + (x + y*fbWidth)*dstpf.bpp/8;\n        if (x < fbWidth/2) {\n          verifyPixel(dstpf, srcpf, pixel);\n        } else {\n          const uint8_t zero[4] = { 0, 0, 0, 0 };\n          EXPECT_EQ(memcmp(pixel, zero, dstpf.bpp/8), 0);\n        }\n        if (testing::Test::HasFailure())\n          return;\n      }\n    }\n  }\n}\n\nTEST_P(Conv, bufferToFromRGB)\n{\n  int i, x, y, unaligned;\n  uint8_t bufIn[fbMalloc], bufRGB[fbMalloc], bufOut[fbMalloc];\n\n  const rfb::PixelFormat &srcpf = GetParam().first;\n  const rfb::PixelFormat &dstpf = GetParam().second;\n\n  // Once aligned, and once unaligned\n  for (unaligned = 0;unaligned < 2;unaligned++) {\n    for (i = 0;i < fbArea;i++)\n      makePixel(srcpf, bufIn + unaligned + i*srcpf.bpp/8);\n\n    memset(bufRGB, 0, sizeof(bufRGB));\n    srcpf.rgbFromBuffer(bufRGB + unaligned, bufIn + unaligned, fbArea);\n\n    memset(bufOut, 0, sizeof(bufOut));\n    dstpf.bufferFromRGB(bufOut + unaligned, bufRGB + unaligned, fbArea);\n\n    for (i = 0;i < fbArea;i++) {\n      verifyPixel(dstpf, srcpf, bufOut + unaligned + i*dstpf.bpp/8);\n      if (testing::Test::HasFailure())\n        return;\n    }\n\n    memset(bufIn, 0, sizeof(bufIn));\n    for (y = 0;y < fbHeight;y++) {\n      for (x = 0;x < fbWidth/2;x++)\n        makePixel(srcpf, bufIn + unaligned + (x + y*fbWidth)*srcpf.bpp/8);\n    }\n\n    memset(bufRGB, 0, sizeof(bufRGB));\n    srcpf.rgbFromBuffer(bufRGB + unaligned, bufIn + unaligned,\n                        fbWidth/2, fbWidth, fbHeight);\n\n    memset(bufOut, 0, sizeof(bufOut));\n    dstpf.bufferFromRGB(bufOut + unaligned, bufRGB + unaligned,\n                        fbWidth/2, fbWidth, fbHeight);\n\n    for (y = 0;y < fbHeight;y++) {\n      for (x = 0;x < fbWidth;x++) {\n        const uint8_t* pixel;\n        pixel = bufOut + unaligned + (x + y*fbWidth)*dstpf.bpp/8;\n        if (x < fbWidth/2) {\n          verifyPixel(dstpf, srcpf, pixel);\n        } else {\n          const uint8_t zero[4] = { 0, 0, 0, 0 };\n          EXPECT_EQ(memcmp(pixel, zero, dstpf.bpp/8), 0);\n        }\n        if (testing::Test::HasFailure())\n          return;\n      }\n    }\n  }\n}\n\nTEST_P(Conv, pixelToFromRGB)\n{\n  rfb::Pixel p;\n  uint16_t r16, g16, b16;\n  uint8_t r8, g8, b8;\n  uint8_t buffer[4];\n\n  const rfb::PixelFormat &srcpf = GetParam().first;\n  const rfb::PixelFormat &dstpf = GetParam().second;\n\n  makePixel(srcpf, buffer);\n\n  p = srcpf.pixelFromBuffer(buffer);\n  srcpf.rgbFromPixel(p, &r16, &g16, &b16);\n  p = dstpf.pixelFromRGB(r16, g16, b16);\n  memset(buffer, 0, sizeof(buffer));\n  dstpf.bufferFromPixel(buffer, p);\n\n  verifyPixel(dstpf, srcpf, buffer);\n\n  makePixel(srcpf, buffer);\n\n  p = srcpf.pixelFromBuffer(buffer);\n  srcpf.rgbFromPixel(p, &r8, &g8, &b8);\n  p = dstpf.pixelFromRGB(r8, g8, b8);\n  memset(buffer, 0, sizeof(buffer));\n  dstpf.bufferFromPixel(buffer, p);\n\n  verifyPixel(dstpf, srcpf, buffer);\n}\n\nstatic std::list<TestPair> paramGenerator()\n{\n  std::list<TestPair> params;\n  rfb::PixelFormat dstpf, srcpf;\n\n  /* rgb888 targets */\n\n  dstpf.parse(\"rgb888\");\n\n  srcpf.parse(\"rgb888\");\n  params.push_back(std::make_pair(srcpf, dstpf));\n\n  srcpf.parse(\"bgr888\");\n  params.push_back(std::make_pair(srcpf, dstpf));\n\n  srcpf.parse(\"rgb565\");\n  params.push_back(std::make_pair(srcpf, dstpf));\n\n  srcpf.parse(\"rgb232\");\n  params.push_back(std::make_pair(srcpf, dstpf));\n\n  /* rgb565 targets */\n\n  dstpf.parse(\"rgb565\");\n\n  srcpf.parse(\"rgb888\");\n  params.push_back(std::make_pair(srcpf, dstpf));\n\n  srcpf.parse(\"bgr565\");\n  params.push_back(std::make_pair(srcpf, dstpf));\n\n  srcpf.parse(\"rgb232\");\n  params.push_back(std::make_pair(srcpf, dstpf));\n\n  /* rgb232 targets */\n\n  dstpf.parse(\"rgb232\");\n\n  srcpf.parse(\"rgb888\");\n  params.push_back(std::make_pair(srcpf, dstpf));\n\n  srcpf.parse(\"rgb565\");\n  params.push_back(std::make_pair(srcpf, dstpf));\n\n  srcpf.parse(\"bgr232\");\n  params.push_back(std::make_pair(srcpf, dstpf));\n\n  /* endian conversion (both ways) */\n\n  dstpf = rfb::PixelFormat(32, 24, false, true, 255, 255, 255, 0, 8, 16);\n  srcpf = rfb::PixelFormat(32, 24, true, true, 255, 255, 255, 0, 8, 16);\n\n  params.push_back(std::make_pair(srcpf, dstpf));\n  params.push_back(std::make_pair(dstpf, srcpf));\n\n  dstpf = rfb::PixelFormat(16, 16, false, true, 31, 63, 31, 0, 5, 11);\n  srcpf = rfb::PixelFormat(16, 16, true, true, 31, 63, 31, 0, 5, 11);\n\n  params.push_back(std::make_pair(srcpf, dstpf));\n  params.push_back(std::make_pair(dstpf, srcpf));\n\n  // Pesky case that is very asymetrical\n  dstpf = rfb::PixelFormat(32, 24, false, true, 255, 255, 255, 0, 8, 16);\n  srcpf = rfb::PixelFormat(32, 24, true, true, 255, 255, 255, 0, 24, 8);\n\n  params.push_back(std::make_pair(srcpf, dstpf));\n  params.push_back(std::make_pair(dstpf, srcpf));\n\n  return params;\n}\n\nINSTANTIATE_TEST_SUITE_P(, Conv, testing::ValuesIn(paramGenerator()));\n\nint main(int argc, char** argv)\n{\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "tests/unit/convertlf.cxx",
    "content": "/* Copyright 2019-2025 Pierre Ossman <ossman@cendio.se> for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <gtest/gtest.h>\n\n#include <core/string.h>\n\nTEST(ConvertLF, convertLF)\n{\n  EXPECT_EQ(core::convertLF(\"\"), \"\");\n  EXPECT_EQ(core::convertLF(\"no EOL\"), \"no EOL\");\n\n  EXPECT_EQ(core::convertLF(\"\\n\"), \"\\n\");\n  EXPECT_EQ(core::convertLF(\"already correct\\n\"), \"already correct\\n\");\n  EXPECT_EQ(core::convertLF(\"multiple\\nlines\\n\"), \"multiple\\nlines\\n\");\n  EXPECT_EQ(core::convertLF(\"empty lines\\n\\n\"), \"empty lines\\n\\n\");\n  EXPECT_EQ(core::convertLF(\"\\ninitial line\"), \"\\ninitial line\");\n\n  EXPECT_EQ(core::convertLF(\"\\r\\n\"), \"\\n\");\n  EXPECT_EQ(core::convertLF(\"one line\\r\\n\"), \"one line\\n\");\n  EXPECT_EQ(core::convertLF(\"multiple\\r\\nlines\\r\\n\"), \"multiple\\nlines\\n\");\n  EXPECT_EQ(core::convertLF(\"empty lines\\r\\n\\r\\n\"), \"empty lines\\n\\n\");\n  EXPECT_EQ(core::convertLF(\"\\r\\ninitial line\"), \"\\ninitial line\");\n  EXPECT_EQ(core::convertLF(\"mixed\\r\\nlines\\n\"), \"mixed\\nlines\\n\");\n\n  EXPECT_EQ(core::convertLF(\"cropped\\r\"), \"cropped\\n\");\n  EXPECT_EQ(core::convertLF(\"old\\rmac\\rformat\"), \"old\\nmac\\nformat\");\n}\n\nTEST(ConvertLF, convertCRLF)\n{\n  EXPECT_EQ(core::convertCRLF(\"\"), \"\");\n  EXPECT_EQ(core::convertCRLF(\"no EOL\"), \"no EOL\");\n\n  EXPECT_EQ(core::convertCRLF(\"\\r\\n\"), \"\\r\\n\");\n  EXPECT_EQ(core::convertCRLF(\"already correct\\r\\n\"), \"already correct\\r\\n\");\n  EXPECT_EQ(core::convertCRLF(\"multiple\\r\\nlines\\r\\n\"), \"multiple\\r\\nlines\\r\\n\");\n  EXPECT_EQ(core::convertCRLF(\"empty lines\\r\\n\\r\\n\"), \"empty lines\\r\\n\\r\\n\");\n  EXPECT_EQ(core::convertCRLF(\"\\r\\ninitial line\"), \"\\r\\ninitial line\");\n\n  EXPECT_EQ(core::convertCRLF(\"\\n\"), \"\\r\\n\");\n  EXPECT_EQ(core::convertCRLF(\"one line\\n\"), \"one line\\r\\n\");\n  EXPECT_EQ(core::convertCRLF(\"multiple\\nlines\\n\"), \"multiple\\r\\nlines\\r\\n\");\n  EXPECT_EQ(core::convertCRLF(\"empty lines\\n\\n\"), \"empty lines\\r\\n\\r\\n\");\n  EXPECT_EQ(core::convertCRLF(\"\\ninitial line\"), \"\\r\\ninitial line\");\n  EXPECT_EQ(core::convertCRLF(\"mixed\\r\\nlines\\n\"), \"mixed\\r\\nlines\\r\\n\");\n\n  EXPECT_EQ(core::convertCRLF(\"cropped\\r\"), \"cropped\\r\\n\");\n  EXPECT_EQ(core::convertCRLF(\"old\\rmac\\rformat\"), \"old\\r\\nmac\\r\\nformat\");\n}\n\nint main(int argc, char** argv)\n{\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "tests/unit/emulatemb.cxx",
    "content": "/* Copyright 2020 Alex Tanskanen <aleta@cendio.se> for Cendio AB\n * Copyright 2025 Pierre Ossman <ossman@cendio.se> for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <unistd.h>\n\n#include <vector>\n\n#include <gtest/gtest.h>\n\n#include <core/Rect.h>\n#include <core/Configuration.h>\n\n#include \"EmulateMB.h\"\n\n// The button masks for the mouse buttons\nstatic const int empty          = 0x00;\nstatic const int left           = 0x01;\nstatic const int middle         = 0x02;\nstatic const int middleAndLeft  = 0x03;\nstatic const int right          = 0x04;\nstatic const int both           = 0x05;\nstatic const int middleAndRight = 0x06;\n\ncore::BoolParameter emulateMiddleButton(\"dummy_name\", \"dummy_desc\", true);\n\nclass TestClass : public EmulateMB\n{\npublic:\n  void sendPointerEvent(const core::Point& pos, uint16_t buttonMask) override;\n\n  struct PointerEventParams {core::Point pos; uint16_t mask; };\n\n  std::vector<PointerEventParams> results;\n};\n\nvoid TestClass::sendPointerEvent(const core::Point& pos, uint16_t buttonMask)\n{\n  PointerEventParams params;\n  params.pos = pos;\n  params.mask = buttonMask;\n  results.push_back(params);\n}\n\nTEST(EmulateMB, disabledOption)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(false);\n  test.filterPointerEvent({0, 10}, left);\n\n  ASSERT_EQ(test.results.size(), 1);\n\n  EXPECT_EQ(test.results[0].pos.x, 0);\n  EXPECT_EQ(test.results[0].pos.y, 10);\n  EXPECT_EQ(test.results[0].mask, left);\n}\n\nTEST(EmulateMB, leftClick)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({0, 0}, left);\n  test.filterPointerEvent({0, 0}, empty);\n\n  ASSERT_EQ(test.results.size(), 3);\n\n  EXPECT_EQ(test.results[0].pos.x, 0);\n  EXPECT_EQ(test.results[0].pos.y, 0);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 0);\n  EXPECT_EQ(test.results[1].pos.y, 0);\n  EXPECT_EQ(test.results[1].mask, left);\n\n  EXPECT_EQ(test.results[2].pos.x, 0);\n  EXPECT_EQ(test.results[2].pos.y, 0);\n  EXPECT_EQ(test.results[2].mask, empty);\n}\n\nTEST(EmulateMB, normalLeftPress)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({10, 20}, left);\n  usleep(100000); // 0.1s\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.results.size(), 2);\n\n  EXPECT_EQ(test.results[0].pos.x, 10);\n  EXPECT_EQ(test.results[0].pos.y, 20);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 10);\n  EXPECT_EQ(test.results[1].pos.y, 20);\n  EXPECT_EQ(test.results[1].mask, left);\n}\n\nTEST(EmulateMB, normalMiddlePress)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({0, 0}, middle);\n\n  ASSERT_EQ(test.results.size(), 1);\n\n  EXPECT_EQ(test.results[0].pos.x, 0);\n  EXPECT_EQ(test.results[0].pos.y, 0);\n  EXPECT_EQ(test.results[0].mask, middle);\n}\n\nTEST(EmulateMB, normalRightPress)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({0, 0}, right);\n  usleep(100000); // 0.1s\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.results.size(), 2);\n\n  EXPECT_EQ(test.results[0].pos.x, 0);\n  EXPECT_EQ(test.results[0].pos.y, 0);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 0);\n  EXPECT_EQ(test.results[1].pos.y, 0);\n  EXPECT_EQ(test.results[1].mask, right);\n}\n\nTEST(EmulateMB, emulateMiddleMouseButton)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({20, 30}, right);\n  test.filterPointerEvent({20, 30}, both);\n\n  ASSERT_EQ(test.results.size(), 2);\n\n  EXPECT_EQ(test.results[0].pos.x, 20);\n  EXPECT_EQ(test.results[0].pos.y, 30);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 20);\n  EXPECT_EQ(test.results[1].pos.y, 30);\n  EXPECT_EQ(test.results[1].mask, middle);\n}\n\nTEST(EmulateMB, leftReleaseAfterEmulate)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({20, 30}, left);\n  test.filterPointerEvent({20, 30}, both);\n  test.filterPointerEvent({20, 30}, right); // left released\n\n  ASSERT_EQ(test.results.size(), 3);\n\n  EXPECT_EQ(test.results[0].pos.x, 20);\n  EXPECT_EQ(test.results[0].pos.y, 30);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 20);\n  EXPECT_EQ(test.results[1].pos.y, 30);\n  EXPECT_EQ(test.results[1].mask, middle);\n\n  EXPECT_EQ(test.results[2].pos.x, 20);\n  EXPECT_EQ(test.results[2].pos.y, 30);\n  EXPECT_EQ(test.results[2].mask, middle);\n}\n\nTEST(EmulateMB, rightReleaseAfterEmulate)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({20, 30}, right);\n  test.filterPointerEvent({20, 30}, both);\n  test.filterPointerEvent({20, 30}, left); // right released\n\n  ASSERT_EQ(test.results.size(), 3);\n\n  EXPECT_EQ(test.results[0].pos.x, 20);\n  EXPECT_EQ(test.results[0].pos.y, 30);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 20);\n  EXPECT_EQ(test.results[1].pos.y, 30);\n  EXPECT_EQ(test.results[1].mask, middle);\n\n  EXPECT_EQ(test.results[2].pos.x, 20);\n  EXPECT_EQ(test.results[2].pos.y, 30);\n  EXPECT_EQ(test.results[2].mask, middle);\n}\n\nTEST(EmulateMB, leftRepressAfterEmulate)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({20, 30}, left);\n  test.filterPointerEvent({20, 30}, both);\n  test.filterPointerEvent({20, 30}, right); // left released\n  test.filterPointerEvent({20, 30}, both);\n\n  ASSERT_EQ(test.results.size(), 4);\n\n  EXPECT_EQ(test.results[0].pos.x, 20);\n  EXPECT_EQ(test.results[0].pos.y, 30);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 20);\n  EXPECT_EQ(test.results[1].pos.y, 30);\n  EXPECT_EQ(test.results[1].mask, middle);\n\n  EXPECT_EQ(test.results[2].pos.x, 20);\n  EXPECT_EQ(test.results[2].pos.y, 30);\n  EXPECT_EQ(test.results[2].mask, middle);\n\n  EXPECT_EQ(test.results[3].pos.x, 20);\n  EXPECT_EQ(test.results[3].pos.y, 30);\n  EXPECT_EQ(test.results[3].mask, middleAndLeft);\n}\n\nTEST(EmulateMB, rightRepressAfterEmulate)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({20, 30}, right);\n  test.filterPointerEvent({20, 30}, both);\n  test.filterPointerEvent({20, 30}, left); // right released\n  test.filterPointerEvent({20, 30}, both);\n\n  ASSERT_EQ(test.results.size(), 4);\n\n  EXPECT_EQ(test.results[0].pos.x, 20);\n  EXPECT_EQ(test.results[0].pos.y, 30);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 20);\n  EXPECT_EQ(test.results[1].pos.y, 30);\n  EXPECT_EQ(test.results[1].mask, middle);\n\n  EXPECT_EQ(test.results[2].pos.x, 20);\n  EXPECT_EQ(test.results[2].pos.y, 30);\n  EXPECT_EQ(test.results[2].mask, middle);\n\n  EXPECT_EQ(test.results[3].pos.x, 20);\n  EXPECT_EQ(test.results[3].pos.y, 30);\n  EXPECT_EQ(test.results[3].mask, middleAndRight);\n}\n\nTEST(EmulateMB, bothPressAfterLeftTimeout)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({10, 20}, left);\n  usleep(100000); // 0.1s\n  core::Timer::checkTimeouts();\n  test.filterPointerEvent({10, 20}, both);\n\n  ASSERT_EQ(test.results.size(), 3);\n\n  EXPECT_EQ(test.results[0].pos.x, 10);\n  EXPECT_EQ(test.results[0].pos.y, 20);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 10);\n  EXPECT_EQ(test.results[1].pos.y, 20);\n  EXPECT_EQ(test.results[1].mask, left);\n\n  EXPECT_EQ(test.results[2].pos.x, 10);\n  EXPECT_EQ(test.results[2].pos.y, 20);\n  EXPECT_EQ(test.results[2].mask, both);\n}\n\nTEST(EmulateMB, bothPressAfterRightTimeout)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({10, 20}, right);\n  usleep(100000); // 0.1s\n  core::Timer::checkTimeouts();\n  test.filterPointerEvent({10, 20}, both);\n\n  ASSERT_EQ(test.results.size(), 3);\n\n  EXPECT_EQ(test.results[0].pos.x, 10);\n  EXPECT_EQ(test.results[0].pos.y, 20);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 10);\n  EXPECT_EQ(test.results[1].pos.y, 20);\n  EXPECT_EQ(test.results[1].mask, right);\n\n  EXPECT_EQ(test.results[2].pos.x, 10);\n  EXPECT_EQ(test.results[2].pos.y, 20);\n  EXPECT_EQ(test.results[2].mask, both);\n}\n\nTEST(EmulateMB, timeoutAndDrag)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({0, 0}, left);\n  usleep(100000); //0.1s\n  core::Timer::checkTimeouts();\n  test.filterPointerEvent({10, 10}, left);\n\n  ASSERT_EQ(test.results.size(), 3);\n\n  EXPECT_EQ(test.results[0].pos.x, 0);\n  EXPECT_EQ(test.results[0].pos.y, 0);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 0);\n  EXPECT_EQ(test.results[1].pos.y, 0);\n  EXPECT_EQ(test.results[1].mask, left);\n\n  EXPECT_EQ(test.results[2].pos.x, 10);\n  EXPECT_EQ(test.results[2].pos.y, 10);\n  EXPECT_EQ(test.results[2].mask, left);\n}\n\nTEST(EmulateMB, dragAndTimeout)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({10, 10}, left);\n  test.filterPointerEvent({30, 30}, left);\n  usleep(100000); //0.1s\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.results.size(), 3);\n\n  EXPECT_EQ(test.results[0].pos.x, 10);\n  EXPECT_EQ(test.results[0].pos.y, 10);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 10);\n  EXPECT_EQ(test.results[1].pos.y, 10);\n  EXPECT_EQ(test.results[1].mask, left);\n\n  EXPECT_EQ(test.results[2].pos.x, 30);\n  EXPECT_EQ(test.results[2].pos.y, 30);\n  EXPECT_EQ(test.results[2].mask, left);\n}\n\nTEST(EmulateMB, dragAndRelease)\n{\n  TestClass test;\n\n  emulateMiddleButton.setParam(true);\n  test.filterPointerEvent({10, 10}, left);\n  test.filterPointerEvent({20, 20}, empty);\n\n  ASSERT_EQ(test.results.size(), 3);\n\n  EXPECT_EQ(test.results[0].pos.x, 10);\n  EXPECT_EQ(test.results[0].pos.y, 10);\n  EXPECT_EQ(test.results[0].mask, empty);\n\n  EXPECT_EQ(test.results[1].pos.x, 10);\n  EXPECT_EQ(test.results[1].pos.y, 10);\n  EXPECT_EQ(test.results[1].mask, left);\n\n  EXPECT_EQ(test.results[2].pos.x, 20);\n  EXPECT_EQ(test.results[2].pos.y, 20);\n  EXPECT_EQ(test.results[2].mask, empty);\n}\n\nint main(int argc, char** argv)\n{\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "tests/unit/gesturehandler.cxx",
    "content": "/* Copyright 2020-2025 Pierre Ossman <ossman@cendio.se> for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <unistd.h>\n\n#include <vector>\n\n#include <gtest/gtest.h>\n\n#include \"../../vncviewer/GestureHandler.h\"\n\nclass TestClass : public GestureHandler\n{\n  protected:\n    void handleGestureEvent(const GestureEvent& event) override;\n\n  public:\n    std::vector<GestureEvent> events;\n};\n\nvoid TestClass::handleGestureEvent(const GestureEvent& event)\n{\n  events.push_back(event);\n}\n\nTEST(GestureHandler, oneTapNormal)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureOneTap);\n  EXPECT_EQ(test.events[0].eventX, 20.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n\n  EXPECT_EQ(test.events[1].type, GestureEnd);\n  EXPECT_EQ(test.events[1].gesture, GestureOneTap);\n  EXPECT_EQ(test.events[1].eventX, 20.0);\n  EXPECT_EQ(test.events[1].eventY, 30.0);\n}\n\nTEST(GestureHandler, twoTapNormal)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 50.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoTap);\n  EXPECT_EQ(test.events[0].eventX, 25.0);\n  EXPECT_EQ(test.events[0].eventY, 40.0);\n\n  EXPECT_EQ(test.events[1].type, GestureEnd);\n  EXPECT_EQ(test.events[1].gesture, GestureTwoTap);\n  EXPECT_EQ(test.events[1].eventX, 25.0);\n  EXPECT_EQ(test.events[1].eventY, 40.0);\n}\n\nTEST(GestureHandler, twoTapSlowBegin)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n\n  usleep(500000);\n  core::Timer::checkTimeouts();\n\n  test.handleTouchBegin(2, 30.0, 50.0);\n  test.handleTouchEnd(1);\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, twoTapSlowEnd)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 50.0);\n  test.handleTouchEnd(1);\n\n  usleep(500000);\n  core::Timer::checkTimeouts();\n\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, twoTapTimeout)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 50.0);\n\n  usleep(1500000);\n  core::Timer::checkTimeouts();\n\n  test.handleTouchEnd(1);\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, threeTapNormal)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 50.0);\n  test.handleTouchBegin(3, 40.0, 40.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchEnd(3);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureThreeTap);\n  EXPECT_EQ(test.events[0].eventX, 30.0);\n  EXPECT_EQ(test.events[0].eventY, 40.0);\n\n  EXPECT_EQ(test.events[1].type, GestureEnd);\n  EXPECT_EQ(test.events[1].gesture, GestureThreeTap);\n  EXPECT_EQ(test.events[1].eventX, 30.0);\n  EXPECT_EQ(test.events[1].eventY, 40.0);\n}\n\nTEST(GestureHandler, threeTapSlowBegin)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 50.0);\n\n  usleep(500000);\n  core::Timer::checkTimeouts();\n\n  test.handleTouchBegin(3, 40.0, 40.0);\n  test.handleTouchEnd(1);\n  test.handleTouchEnd(2);\n  test.handleTouchEnd(3);\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, threeTapSlowEnd)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 50.0);\n  test.handleTouchBegin(3, 40.0, 40.0);\n  test.handleTouchEnd(1);\n  test.handleTouchEnd(2);\n\n  usleep(500000);\n  core::Timer::checkTimeouts();\n\n  test.handleTouchEnd(3);\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, threeTapDrag)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 50.0);\n  test.handleTouchBegin(3, 40.0, 40.0);\n\n  test.handleTouchUpdate(1, 120.0, 130.0);\n  test.handleTouchUpdate(2, 130.0, 150.0);\n  test.handleTouchUpdate(3, 140.0, 140.0);\n\n  test.handleTouchEnd(1);\n  test.handleTouchEnd(2);\n  test.handleTouchEnd(3);\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, threeTapTimeout)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 50.0);\n  test.handleTouchBegin(3, 40.0, 40.0);\n\n  usleep(1500000);\n  core::Timer::checkTimeouts();\n\n  test.handleTouchEnd(1);\n  test.handleTouchEnd(2);\n  test.handleTouchEnd(3);\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, dragHoriz)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 40.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 80.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n  EXPECT_EQ(test.events[0].eventX, 20.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureDrag);\n  EXPECT_EQ(test.events[1].eventX, 80.0);\n  EXPECT_EQ(test.events[1].eventY, 30.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n  EXPECT_EQ(test.events[0].eventX, 80.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n}\n\nTEST(GestureHandler, dragVert)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 20.0, 50.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 20.0, 90.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n  EXPECT_EQ(test.events[0].eventX, 20.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureDrag);\n  EXPECT_EQ(test.events[1].eventX, 20.0);\n  EXPECT_EQ(test.events[1].eventY, 90.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n  EXPECT_EQ(test.events[0].eventX, 20.0);\n  EXPECT_EQ(test.events[0].eventY, 90.0);\n}\n\nTEST(GestureHandler, dragDiag)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 120.0, 130.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 90.0, 100.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 60.0, 70.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n  EXPECT_EQ(test.events[0].eventX, 120.0);\n  EXPECT_EQ(test.events[0].eventY, 130.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureDrag);\n  EXPECT_EQ(test.events[1].eventX, 60.0);\n  EXPECT_EQ(test.events[1].eventY, 70.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n  EXPECT_EQ(test.events[0].eventX, 60.0);\n  EXPECT_EQ(test.events[0].eventY, 70.0);\n}\n\nTEST(GestureHandler, longPressNormal)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  usleep(1500000);\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureLongPress);\n  EXPECT_EQ(test.events[0].eventX, 20.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureLongPress);\n  EXPECT_EQ(test.events[0].eventX, 20.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n}\n\nTEST(GestureHandler, longPressDrag)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  usleep(1500000);\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureLongPress);\n  EXPECT_EQ(test.events[0].eventX, 20.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n\n  test.events.clear();\n\n  test.handleTouchUpdate(1, 120.0, 50.0);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureUpdate);\n  EXPECT_EQ(test.events[0].gesture, GestureLongPress);\n  EXPECT_EQ(test.events[0].eventX, 120.0);\n  EXPECT_EQ(test.events[0].eventY, 50.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureLongPress);\n  EXPECT_EQ(test.events[0].eventX, 120.0);\n  EXPECT_EQ(test.events[0].eventY, 50.0);\n}\n\nTEST(GestureHandler, twoDragFastDistinctHoriz)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 40.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(2, 50.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(2, 90.0, 30.0);\n  test.handleTouchUpdate(1, 80.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[0].eventX, 25.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 0.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 0.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[1].eventX, 25.0);\n  EXPECT_EQ(test.events[1].eventY, 30.0);\n  EXPECT_EQ(test.events[1].magnitudeX, 60.0);\n  EXPECT_EQ(test.events[1].magnitudeY, 0.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[0].eventX, 25.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 60.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 0.0);\n}\n\nTEST(GestureHandler, twoDragFastDistinctVert)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 20.0, 100.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(2, 30.0, 40.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(2, 30.0, 90.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[0].eventX, 25.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 0.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 0.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[1].eventX, 25.0);\n  EXPECT_EQ(test.events[1].eventY, 30.0);\n  EXPECT_EQ(test.events[1].magnitudeX, 0.0);\n  EXPECT_EQ(test.events[1].magnitudeY, 65.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[0].eventX, 25.0);\n  EXPECT_EQ(test.events[0].eventY, 30.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 0.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 65.0);\n}\n\nTEST(GestureHandler, twoDragFastDistinctDiag)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 120.0, 130.0);\n  test.handleTouchBegin(2, 130.0, 130.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 80.0, 90.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(2, 100.0, 130.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(2, 60.0, 70.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[0].eventX, 125.0);\n  EXPECT_EQ(test.events[0].eventY, 130.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 0.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 0.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[1].eventX, 125.0);\n  EXPECT_EQ(test.events[1].eventY, 130.0);\n  EXPECT_EQ(test.events[1].magnitudeX, -55.0);\n  EXPECT_EQ(test.events[1].magnitudeY, -50.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[0].eventX, 125.0);\n  EXPECT_EQ(test.events[0].eventY, 130.0);\n  EXPECT_EQ(test.events[0].magnitudeX, -55.0);\n  EXPECT_EQ(test.events[0].magnitudeY, -50.0);\n}\n\nTEST(GestureHandler, twoDragFastAlmost)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 30.0);\n  test.handleTouchUpdate(1, 80.0, 30.0);\n  test.handleTouchUpdate(2, 70.0, 30.0);\n  test.handleTouchEnd(1);\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  usleep(500000);\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, twoDragSlowHoriz)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 50.0, 40.0);\n  test.handleTouchBegin(2, 60.0, 40.0);\n  test.handleTouchUpdate(2, 80.0, 40.0);\n  test.handleTouchUpdate(1, 110.0, 40.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  usleep(60000); // 60ms\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[0].eventX, 55.0);\n  EXPECT_EQ(test.events[0].eventY, 40.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 0.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 0.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[1].eventX, 55.0);\n  EXPECT_EQ(test.events[1].eventY, 40.0);\n  EXPECT_EQ(test.events[1].magnitudeX, 40.0);\n  EXPECT_EQ(test.events[1].magnitudeY, 0.0);\n}\n\nTEST(GestureHandler, twoDragSlowVert)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 40.0, 40.0);\n  test.handleTouchBegin(2, 40.0, 60.0);\n  test.handleTouchUpdate(2, 40.0, 80.0);\n  test.handleTouchUpdate(1, 40.0, 100.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  usleep(60000); // 60ms\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[0].eventX, 40.0);\n  EXPECT_EQ(test.events[0].eventY, 50.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 0.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 0.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[1].eventX, 40.0);\n  EXPECT_EQ(test.events[1].eventY, 50.0);\n  EXPECT_EQ(test.events[1].magnitudeX, 0.0);\n  EXPECT_EQ(test.events[1].magnitudeY, 40.0);\n}\n\nTEST(GestureHandler, twoDragSlowDiag)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 50.0, 40.0);\n  test.handleTouchBegin(2, 40.0, 60.0);\n  test.handleTouchUpdate(1, 70.0, 60.0);\n  test.handleTouchUpdate(2, 90.0, 110.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  usleep(60000); // 60ms\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[0].eventX, 45.0);\n  EXPECT_EQ(test.events[0].eventY, 50.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 0.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 0.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureTwoDrag);\n  EXPECT_EQ(test.events[1].eventX, 45.0);\n  EXPECT_EQ(test.events[1].eventY, 50.0);\n  EXPECT_EQ(test.events[1].magnitudeX, 35.0);\n  EXPECT_EQ(test.events[1].magnitudeY, 35.0);\n}\n\nTEST(GestureHandler, twoDragTooSlow)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n\n  usleep(500000);\n  core::Timer::checkTimeouts();\n\n  test.handleTouchBegin(2, 30.0, 30.0);\n  test.handleTouchUpdate(2, 50.0, 30.0);\n  test.handleTouchUpdate(1, 80.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, pinchFastDistinctIn)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 0.0, 0.0);\n  test.handleTouchBegin(2, 130.0, 130.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 50.0, 40.0);\n  test.handleTouchUpdate(2, 100.0, 130.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(2, 60.0, 70.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GesturePinch);\n  EXPECT_EQ(test.events[0].eventX, 65.0);\n  EXPECT_EQ(test.events[0].eventY, 65.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 130.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 130.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GesturePinch);\n  EXPECT_EQ(test.events[1].eventX, 65.0);\n  EXPECT_EQ(test.events[1].eventY, 65.0);\n  EXPECT_EQ(test.events[1].magnitudeX, 10.0);\n  EXPECT_EQ(test.events[1].magnitudeY, 30.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GesturePinch);\n  EXPECT_EQ(test.events[0].eventX, 65.0);\n  EXPECT_EQ(test.events[0].eventY, 65.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 10.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 30.0);\n}\n\nTEST(GestureHandler, pinchFastDistinctOut)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 100.0, 100.0);\n  test.handleTouchBegin(2, 110.0, 100.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 130.0, 70.0);\n  test.handleTouchUpdate(2, 0.0, 200.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 180.0, 20.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GesturePinch);\n  EXPECT_EQ(test.events[0].eventX, 105.0);\n  EXPECT_EQ(test.events[0].eventY, 100.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 10.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 0.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GesturePinch);\n  EXPECT_EQ(test.events[1].eventX, 105.0);\n  EXPECT_EQ(test.events[1].eventY, 100.0);\n  EXPECT_EQ(test.events[1].magnitudeX, 180.0);\n  EXPECT_EQ(test.events[1].magnitudeY, 180.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GesturePinch);\n  EXPECT_EQ(test.events[0].eventX, 105.0);\n  EXPECT_EQ(test.events[0].eventY, 100.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 180.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 180.0);\n}\n\nTEST(GestureHandler, pinchFastAlmost)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 130.0, 130.0);\n  test.handleTouchUpdate(1, 80.0, 70.0);\n  test.handleTouchEnd(1);\n  test.handleTouchEnd(2);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  usleep(500000);\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, pinchSlowIn)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 0.0, 0.0);\n  test.handleTouchBegin(2, 130.0, 130.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 50.0, 40.0);\n  test.handleTouchUpdate(2, 100.0, 130.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  usleep(60000); // 60ms\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GesturePinch);\n  EXPECT_EQ(test.events[0].eventX, 65.0);\n  EXPECT_EQ(test.events[0].eventY, 65.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 130.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 130.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GesturePinch);\n  EXPECT_EQ(test.events[1].eventX, 65.0);\n  EXPECT_EQ(test.events[1].eventY, 65.0);\n  EXPECT_EQ(test.events[1].magnitudeX, 50.0);\n  EXPECT_EQ(test.events[1].magnitudeY, 90.0);\n}\n\nTEST(GestureHandler, pinchSlowOut)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 100.0, 130.0);\n  test.handleTouchBegin(2, 110.0, 130.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(2, 200.0, 130.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  usleep(60000); // 60ms\n  core::Timer::checkTimeouts();\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GesturePinch);\n  EXPECT_EQ(test.events[0].eventX, 105.0);\n  EXPECT_EQ(test.events[0].eventY, 130.0);\n  EXPECT_EQ(test.events[0].magnitudeX, 10.0);\n  EXPECT_EQ(test.events[0].magnitudeY, 0.0);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GesturePinch);\n  EXPECT_EQ(test.events[1].eventX, 105.0);\n  EXPECT_EQ(test.events[1].eventY, 130.0);\n  EXPECT_EQ(test.events[1].magnitudeX, 100.0);\n  EXPECT_EQ(test.events[1].magnitudeY, 0.0);\n}\n\nTEST(GestureHandler, pinchTooSlow)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 0.0, 0.0);\n\n  usleep(60000); // 60ms\n  core::Timer::checkTimeouts();\n\n  test.handleTouchBegin(2, 130.0, 130.0);\n  test.handleTouchUpdate(2, 100.0, 130.0);\n  test.handleTouchUpdate(1, 50.0, 40.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, extraIgnore)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchUpdate(1, 40.0, 30.0);\n  test.handleTouchUpdate(1, 80.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureDrag);\n\n  test.events.clear();\n\n  test.handleTouchBegin(2, 10.0, 10.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 100.0, 50.0);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureUpdate);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n  EXPECT_EQ(test.events[0].eventX, 100.0);\n  EXPECT_EQ(test.events[0].eventY, 50.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n  EXPECT_EQ(test.events[0].eventX, 100.0);\n  EXPECT_EQ(test.events[0].eventY, 50.0);\n}\n\nTEST(GestureHandler, ignoreWhenAwaitingGestureEnd)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchBegin(2, 30.0, 30.0);\n  test.handleTouchUpdate(1, 40.0, 30.0);\n  test.handleTouchUpdate(2, 90.0, 30.0);\n  test.handleTouchUpdate(1, 80.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureTwoDrag);\n\n  test.events.clear();\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureTwoDrag);\n\n  test.events.clear();\n\n  test.handleTouchBegin(3, 10.0, 10.0);\n  test.handleTouchEnd(3);\n\n  ASSERT_EQ(test.events.size(), 0);\n}\n\nTEST(GestureHandler, ignoreAfterGesture)\n{\n  TestClass test;\n\n  test.handleTouchBegin(1, 20.0, 30.0);\n  test.handleTouchUpdate(1, 40.0, 30.0);\n  test.handleTouchUpdate(1, 80.0, 30.0);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n\n  EXPECT_EQ(test.events[1].type, GestureUpdate);\n  EXPECT_EQ(test.events[1].gesture, GestureDrag);\n\n  test.events.clear();\n\n  // Start ignored event\n  test.handleTouchBegin(2, 10.0, 10.0);\n\n  ASSERT_EQ(test.events.size(), 0);\n\n  test.handleTouchUpdate(1, 100.0, 50.0);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureUpdate);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n  EXPECT_EQ(test.events[0].eventX, 100.0);\n  EXPECT_EQ(test.events[0].eventY, 50.0);\n\n  test.events.clear();\n\n  test.handleTouchEnd(1);\n\n  ASSERT_EQ(test.events.size(), 1);\n\n  EXPECT_EQ(test.events[0].type, GestureEnd);\n  EXPECT_EQ(test.events[0].gesture, GestureDrag);\n  EXPECT_EQ(test.events[0].eventX, 100.0);\n  EXPECT_EQ(test.events[0].eventY, 50.0);\n\n  // End ignored event\n  test.handleTouchEnd(2);\n\n  // Check that everything is reseted after trailing ignores are released\n  test.events.clear();\n\n  test.handleTouchBegin(3, 20.0, 30.0);\n  test.handleTouchEnd(3);\n\n  ASSERT_EQ(test.events.size(), 2);\n\n  EXPECT_EQ(test.events[0].type, GestureBegin);\n  EXPECT_EQ(test.events[0].gesture, GestureOneTap);\n  EXPECT_EQ(test.events[1].type, GestureEnd);\n  EXPECT_EQ(test.events[1].gesture, GestureOneTap);\n}\n\nint main(int argc, char** argv)\n{\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "tests/unit/hostport.cxx",
    "content": "/* Copyright 2016-2025 Pierre Ossman <ossman@cendio.se> for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <gtest/gtest.h>\n\n#include <network/TcpSocket.h>\n\nstruct result {\n  std::string host;\n  int port;\n};\n\nstatic bool operator==(const result& a, const result& b)\n{\n  return a.host == b.host && a.port == b.port;\n}\n\nstatic std::ostream& operator<<(std::ostream& os, const result& r)\n{\n  return os << r.host << \":\" << r.port;\n}\n\nstatic result getHostAndPort(const char* hostAndPort)\n{\n  std::string host;\n  int port;\n  network::getHostAndPort(hostAndPort, &host, &port);\n  return {host, port};\n}\n\nTEST(HostPost, localDisplay)\n{\n  EXPECT_EQ(getHostAndPort(\":5\"), result({\"localhost\", 5905}));\n}\n\nTEST(HostPost, noDisplay)\n{\n  EXPECT_EQ(getHostAndPort(\"1.2.3.4\"), result({\"1.2.3.4\", 5900}));\n}\n\nTEST(HostPost, display)\n{\n  EXPECT_EQ(getHostAndPort(\"1.2.3.4:5\"), result({\"1.2.3.4\", 5905}));\n  EXPECT_EQ(getHostAndPort(\"1.2.3.4:99\"), result({\"1.2.3.4\", 5999}));\n  EXPECT_EQ(getHostAndPort(\"1.2.3.4:100\"), result({\"1.2.3.4\", 100}));\n  EXPECT_EQ(getHostAndPort(\"1.2.3.4:5901\"), result({\"1.2.3.4\", 5901}));\n}\n\nTEST(HostPost, port)\n{\n  EXPECT_EQ(getHostAndPort(\"1.2.3.4::5\"), result({\"1.2.3.4\", 5}));\n  EXPECT_EQ(getHostAndPort(\"1.2.3.4::99\"), result({\"1.2.3.4\", 99}));\n  EXPECT_EQ(getHostAndPort(\"1.2.3.4::5901\"), result({\"1.2.3.4\", 5901}));\n}\n\nTEST(HostPost, bracketedIpv4)\n{\n  EXPECT_EQ(getHostAndPort(\"[1.2.3.4]\"), result({\"1.2.3.4\", 5900}));\n  EXPECT_EQ(getHostAndPort(\"[1.2.3.4]:5\"), result({\"1.2.3.4\", 5905}));\n  EXPECT_EQ(getHostAndPort(\"[1.2.3.4]:100\"), result({\"1.2.3.4\", 100}));\n  EXPECT_EQ(getHostAndPort(\"[1.2.3.4]::5\"), result({\"1.2.3.4\", 5}));\n  EXPECT_EQ(getHostAndPort(\"[1.2.3.4]::100\"), result({\"1.2.3.4\", 100}));\n}\n\nTEST(HostPost, portOne)\n{\n  // Ambigiuous. For now we'll keep the old behaviour...\n  EXPECT_EQ(getHostAndPort(\"::1\"), result({\"localhost\", 1}));\n}\n\nTEST(HostPost, bareIpv6)\n{\n  EXPECT_EQ(getHostAndPort(\"2001:1234::20:1\"), result({\"2001:1234::20:1\", 5900}));\n}\n\nTEST(HostPost, bracketedIpv6)\n{\n  EXPECT_EQ(getHostAndPort(\"[::1]\"), result({\"::1\", 5900}));\n  EXPECT_EQ(getHostAndPort(\"[2001:1234::20:1]\"), result({\"2001:1234::20:1\", 5900}));\n}\n\nTEST(HostPost, ipv6WithDisplay)\n{\n  EXPECT_EQ(getHostAndPort(\"[2001:1234::20:1]:5\"), result({\"2001:1234::20:1\", 5905}));\n  EXPECT_EQ(getHostAndPort(\"[2001:1234::20:1]:99\"), result({\"2001:1234::20:1\", 5999}));\n  EXPECT_EQ(getHostAndPort(\"[2001:1234::20:1]:100\"), result({\"2001:1234::20:1\", 100}));\n  EXPECT_EQ(getHostAndPort(\"[2001:1234::20:1]:5901\"), result({\"2001:1234::20:1\", 5901}));\n}\n\nTEST(HostPort, padding)\n{\n  EXPECT_EQ(getHostAndPort(\"    1.2.3.4    \"), result({\"1.2.3.4\", 5900}));\n  EXPECT_EQ(getHostAndPort(\"    1.2.3.4:5901    \"), result({\"1.2.3.4\", 5901}));\n  EXPECT_EQ(getHostAndPort(\"    1.2.3.4    :5901    \"), result({\"1.2.3.4\", 5901}));\n  EXPECT_EQ(getHostAndPort(\"    [1.2.3.4]:5902    \"), result({\"1.2.3.4\", 5902}));\n  EXPECT_EQ(getHostAndPort(\"    :5903    \"), result({\"localhost\", 5903}));\n  EXPECT_EQ(getHostAndPort(\"    ::4    \"), result({\"localhost\", 4}));\n  EXPECT_EQ(getHostAndPort(\"    [::1]    \"), result({\"::1\", 5900}));\n  EXPECT_EQ(getHostAndPort(\"    2001:1234::20:1    \"), result({\"2001:1234::20:1\", 5900}));\n  EXPECT_EQ(getHostAndPort(\"    [2001:1234::20:1]    \"), result({\"2001:1234::20:1\", 5900}));\n  EXPECT_EQ(getHostAndPort(\"    [2001:1234::20:1]:5905    \"), result({\"2001:1234::20:1\", 5905}));\n}\n\nint main(int argc, char** argv)\n{\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "tests/unit/parameters.cxx",
    "content": "/* Copyright 2025 Pierre Ossman <ossman@cendio.se> for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdexcept>\n\n#include <gtest/gtest.h>\n\n#include <core/Configuration.h>\n\nnamespace core {\n\n// Generic comparison for our list parameters types that preserves\n// the type (doesn't use any common base class)\ntemplate<typename IterL, typename IterR,\n         std::enable_if_t<std::is_member_function_pointer<decltype(&IterL::begin)>::value, bool> = true>\nstatic bool operator==(const IterL& lhs, const IterR& rhs)\n{\n  if (std::distance(lhs.begin(), lhs.end()) !=\n      std::distance(rhs.begin(), rhs.end()))\n    return false;\n  if (!std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()))\n    return false;\n  return true;\n}\n\nstatic std::ostream& operator<<(std::ostream& os,\n                                const core::EnumListEntry& e)\n{\n  return os << '\"' << e.getValueStr() << '\"';\n}\n\n}\n\nTEST(BoolParameter, values)\n{\n  core::BoolParameter bools(\"boolparam\", \"\", false);\n\n  bools.setParam(true);\n  EXPECT_TRUE(bools);\n\n  bools.setParam(false);\n  EXPECT_FALSE(bools);\n}\n\nTEST(BoolParameter, strings)\n{\n  core::BoolParameter strings(\"boolparam\", \"\", false);\n\n  strings.setParam(\"on\");\n  EXPECT_TRUE(strings);\n\n  strings.setParam(\"off\");\n  EXPECT_FALSE(strings);\n\n  strings.setParam(\"1\");\n  EXPECT_TRUE(strings);\n\n  strings.setParam(\"0\");\n  EXPECT_FALSE(strings);\n\n  strings.setParam(\"true\");\n  EXPECT_TRUE(strings);\n\n  strings.setParam(\"false\");\n  EXPECT_FALSE(strings);\n\n  strings.setParam(\"yes\");\n  EXPECT_TRUE(strings);\n\n  strings.setParam(\"no\");\n  EXPECT_FALSE(strings);\n}\n\nTEST(BoolParameter, validation)\n{\n  core::BoolParameter valid(\"boolparam\", \"\", false);\n\n  EXPECT_TRUE(valid.setParam(\"yes\"));\n  EXPECT_TRUE(valid);\n\n  EXPECT_FALSE(valid.setParam(\"foo\"));\n  EXPECT_TRUE(valid);\n}\n\nTEST(BoolParameter, encoding)\n{\n  core::BoolParameter encoding(\"boolparam\", \"\", false);\n\n  encoding.setParam(true);\n  EXPECT_EQ(encoding.getValueStr(), \"on\");\n\n  encoding.setParam(false);\n  EXPECT_EQ(encoding.getValueStr(), \"off\");\n}\n\nTEST(BoolParameter, default)\n{\n  core::BoolParameter def(\"boolparam\", \"\", false);\n\n  EXPECT_TRUE(def.isDefault());\n\n  def.setParam(true);\n  EXPECT_FALSE(def.isDefault());\n\n  def.setParam(false);\n  EXPECT_TRUE(def.isDefault());\n}\n\nTEST(BoolParameter, immutable)\n{\n  core::BoolParameter immutable(\"boolparam\", \"\", false);\n\n  immutable.setImmutable();\n  immutable.setParam(true);\n  immutable.setParam(\"on\");\n  EXPECT_FALSE(immutable);\n}\n\nTEST(IntParameter, values)\n{\n  core::IntParameter ints(\"intparam\", \"\", 0);\n\n  ints.setParam(123);\n  EXPECT_EQ(ints, 123);\n\n  ints.setParam(-456);\n  EXPECT_EQ(ints, -456);\n}\n\nTEST(IntParameter, strings)\n{\n  core::IntParameter strings(\"intparam\", \"\", 0);\n\n  strings.setParam(\"123\");\n  EXPECT_EQ(strings, 123);\n\n  strings.setParam(\"-456\");\n  EXPECT_EQ(strings, -456);\n}\n\nTEST(IntParameter, minmax)\n{\n  core::IntParameter bounds(\"intparam\", \"\", 30, 20, 100);\n\n  EXPECT_TRUE(bounds.setParam(57));\n  EXPECT_EQ(bounds, 57);\n\n  EXPECT_FALSE(bounds.setParam(123));\n  EXPECT_EQ(bounds, 57);\n\n  EXPECT_FALSE(bounds.setParam(\"123\"));\n  EXPECT_EQ(bounds, 57);\n\n  EXPECT_FALSE(bounds.setParam(-30));\n  EXPECT_EQ(bounds, 57);\n\n  EXPECT_FALSE(bounds.setParam(\"-30\"));\n  EXPECT_EQ(bounds, 57);\n}\n\nTEST(IntParameter, minmaxdefault)\n{\n  EXPECT_THROW({\n    core::IntParameter defbounds(\"intparam\", \"\", 10, 20, 100);\n  }, std::invalid_argument);\n}\n\nTEST(IntParameter, validation)\n{\n  core::IntParameter valid(\"intparam\", \"\", 0);\n\n  EXPECT_TRUE(valid.setParam(\"123\"));\n  EXPECT_EQ(valid, 123);\n\n  EXPECT_FALSE(valid.setParam(\"foo\"));\n  EXPECT_EQ(valid, 123);\n}\n\nTEST(IntParameter, encoding)\n{\n  core::IntParameter encoding(\"intparam\", \"\", 0);\n\n  encoding.setParam(123);\n  EXPECT_EQ(encoding.getValueStr(), \"123\");\n\n  encoding.setParam(-456);\n  EXPECT_EQ(encoding.getValueStr(), \"-456\");\n}\n\nTEST(IntParameter, default)\n{\n  core::IntParameter def(\"intparam\", \"\", 30);\n\n  EXPECT_TRUE(def.isDefault());\n\n  def.setParam(123);\n  EXPECT_FALSE(def.isDefault());\n\n  def.setParam(30);\n  EXPECT_TRUE(def.isDefault());\n}\n\nTEST(IntParameter, immutable)\n{\n  core::IntParameter immutable(\"intparam\", \"\", 0);\n\n  immutable.setImmutable();\n  immutable.setParam(123);\n  immutable.setParam(\"-456\");\n  EXPECT_EQ(immutable, 0);\n}\n\nTEST(StringParameter, values)\n{\n  core::StringParameter strings(\"stringparam\", \"\", \"\");\n\n  strings.setParam(\"foo\");\n  EXPECT_STREQ(strings, \"foo\");\n\n  strings.setParam(\"bar\");\n  EXPECT_STREQ(strings, \"bar\");\n}\n\nTEST(StringParameter, null)\n{\n  // NULL value\n  core::StringParameter null(\"stringparam\", \"\", \"\");\n  EXPECT_THROW({\n    null.setParam(nullptr);\n  }, std::invalid_argument);\n\n  // NULL default value\n  EXPECT_THROW({\n    core::StringParameter defnull(\"stringparam\", \"\", nullptr);\n  }, std::invalid_argument);\n}\n\nTEST(StringParameter, encoding)\n{\n  core::StringParameter encoding(\"stringparam\", \"\", \"\");\n\n  encoding.setParam(\"foo\");\n  EXPECT_EQ(encoding.getValueStr(), \"foo\");\n\n  encoding.setParam(\"bar\");\n  EXPECT_EQ(encoding.getValueStr(), \"bar\");\n}\n\nTEST(StringParameter, default)\n{\n  core::StringParameter def(\"stringparam\", \"\", \"test\");\n\n  EXPECT_TRUE(def.isDefault());\n\n  def.setParam(\"foo\");\n  EXPECT_FALSE(def.isDefault());\n\n  def.setParam(\"test\");\n  EXPECT_TRUE(def.isDefault());\n}\n\nTEST(StringParameter, immutable)\n{\n  core::StringParameter immutable(\"stringparam\", \"\", \"\");\n\n  immutable.setImmutable();\n  immutable.setParam(\"foo\");\n  immutable.setParam(\"bar\");\n  EXPECT_STREQ(immutable, \"\");\n}\n\nTEST(EnumParameter, values)\n{\n  core::EnumParameter enums(\"enumparam\", \"\", {\"a\", \"b\", \"c\"}, \"a\");\n\n  enums.setParam(\"b\");\n  EXPECT_FALSE(enums == \"a\");\n  EXPECT_TRUE(enums == \"b\");\n  EXPECT_FALSE(enums == \"c\");\n  EXPECT_FALSE(enums == \"foo\");\n  EXPECT_FALSE(enums != \"b\");\n  EXPECT_TRUE(enums != \"c\");\n\n  enums.setParam(\"c\");\n  EXPECT_FALSE(enums == \"a\");\n  EXPECT_FALSE(enums == \"b\");\n  EXPECT_TRUE(enums == \"c\");\n  EXPECT_FALSE(enums == \"foo\");\n  EXPECT_TRUE(enums != \"b\");\n  EXPECT_FALSE(enums != \"c\");\n}\n\nTEST(EnumParameter, caseinsensitive)\n{\n  core::EnumParameter casecmp(\"enumparam\", \"\", {\"a\", \"b\", \"c\"}, \"a\");\n\n  casecmp.setParam(\"B\");\n  EXPECT_FALSE(casecmp == \"a\");\n  EXPECT_TRUE(casecmp == \"b\");\n  EXPECT_TRUE(casecmp == \"B\");\n  EXPECT_FALSE(casecmp == \"c\");\n  EXPECT_FALSE(casecmp != \"b\");\n  EXPECT_TRUE(casecmp != \"c\");\n}\n\nTEST(EnumParameter, validation)\n{\n  core::EnumParameter valid(\"enumparam\", \"\", {\"a\", \"b\", \"c\"}, \"a\");\n\n  EXPECT_TRUE(valid.setParam(\"b\"));\n  EXPECT_EQ(valid.getValueStr(), \"b\");\n  EXPECT_FALSE(valid.setParam(\"foo\"));\n  EXPECT_EQ(valid.getValueStr(), \"b\");\n\n  // Valid default value\n  EXPECT_THROW({\n    core::EnumParameter defvalid(\"enumparam\", \"\", {\"a\", \"b\", \"c\"}, \"d\");\n  }, std::invalid_argument);\n}\n\nTEST(EnumParameter, null)\n{\n  // NULL value\n  core::EnumParameter null(\"enumparam\", \"\", {\"a\", \"b\", \"c\"}, \"a\");\n  EXPECT_THROW({\n    null.setParam(nullptr);\n  }, std::invalid_argument);\n\n  // NULL default value\n  EXPECT_THROW({\n    core::EnumParameter defnull(\"enumparam\", \"\", {\"\"}, nullptr);\n  }, std::invalid_argument);\n\n  // NULL enum value\n  EXPECT_THROW({\n    core::EnumParameter nullenum(\"enumparam\", \"\", {\"a\", nullptr, \"b\"}, \"a\");\n  }, std::invalid_argument);\n}\n\nTEST(EnumParameter, encoding)\n{\n  core::EnumParameter encoding(\"enumparam\", \"\", {\"a\", \"b\", \"c\"}, \"a\");\n\n  encoding.setParam(\"b\");\n  EXPECT_EQ(encoding.getValueStr(), \"b\");\n\n  encoding.setParam(\"C\");\n  EXPECT_EQ(encoding.getValueStr(), \"c\");\n}\n\nTEST(EnumParameter, default)\n{\n  core::EnumParameter def(\"enumparam\", \"\", {\"a\", \"b\", \"c\"}, \"a\");\n\n  EXPECT_TRUE(def.isDefault());\n\n  def.setParam(\"b\");\n  EXPECT_FALSE(def.isDefault());\n\n  def.setParam(\"A\");\n  EXPECT_TRUE(def.isDefault());\n}\n\nTEST(EnumParameter, immutable)\n{\n  core::EnumParameter immutable(\"enumparam\", \"\", {\"a\", \"b\", \"c\"}, \"a\");\n\n  immutable.setImmutable();\n  immutable.setParam(\"b\");\n  immutable.setParam(\"c\");\n  EXPECT_EQ(immutable.getValueStr(), \"a\");\n}\n\nTEST(BinaryParameter, values)\n{\n  std::vector<uint8_t> data;\n\n  core::BinaryParameter binary(\"binaryparam\", \"\", nullptr, 0);\n\n  data = {1, 2, 3};\n  binary.setParam(data.data(), data.size());\n  ASSERT_EQ(binary.getData().size(), 3);\n  EXPECT_EQ(binary.getData()[0], 1);\n  EXPECT_EQ(binary.getData()[1], 2);\n  EXPECT_EQ(binary.getData()[2], 3);\n}\n\nTEST(BinaryParameter, copy)\n{\n  std::vector<uint8_t> data;\n\n  core::BinaryParameter copy(\"binaryparam\", \"\", nullptr, 0);\n\n  data = {1, 2, 3};\n  copy.setParam(data.data(), data.size());\n  ASSERT_EQ(copy.getData().size(), 3);\n  EXPECT_EQ(copy.getData()[0], 1);\n  EXPECT_EQ(copy.getData()[1], 2);\n  EXPECT_EQ(copy.getData()[2], 3);\n\n  data[0] = 4;\n  EXPECT_EQ(copy.getData()[0], 1);\n}\n\nTEST(BinaryParameter, strings)\n{\n  core::BinaryParameter strings(\"binaryparam\", \"\", nullptr, 0);\n\n  strings.setParam(\"010203\");\n  ASSERT_EQ(strings.getData().size(), 3);\n  EXPECT_EQ(strings.getData()[0], 1);\n  EXPECT_EQ(strings.getData()[1], 2);\n  EXPECT_EQ(strings.getData()[2], 3);\n\n  strings.setParam(\"deadbeef\");\n  ASSERT_EQ(strings.getData().size(), 4);\n  EXPECT_EQ(strings.getData()[0], 0xde);\n  EXPECT_EQ(strings.getData()[1], 0xad);\n  EXPECT_EQ(strings.getData()[2], 0xbe);\n  EXPECT_EQ(strings.getData()[3], 0xef);\n}\n\nTEST(BinaryParameter, validation)\n{\n  core::BinaryParameter valid(\"binaryparam\", \"\", nullptr, 0);\n\n  EXPECT_TRUE(valid.setParam(\"010203\"));\n  ASSERT_EQ(valid.getData().size(), 3);\n  EXPECT_EQ(valid.getData()[0], 1);\n  EXPECT_EQ(valid.getData()[1], 2);\n  EXPECT_EQ(valid.getData()[2], 3);\n\n  EXPECT_FALSE(valid.setParam(\"foo\"));\n  ASSERT_EQ(valid.getData().size(), 3);\n  EXPECT_EQ(valid.getData()[0], 1);\n  EXPECT_EQ(valid.getData()[1], 2);\n  EXPECT_EQ(valid.getData()[2], 3);\n}\n\nTEST(BinaryParameter, encoding)\n{\n  std::vector<uint8_t> data;\n\n  core::BinaryParameter encoding(\"binaryparam\", \"\", nullptr, 0);\n\n  data = {1, 2, 3};\n  encoding.setParam(data.data(), data.size());\n  EXPECT_EQ(encoding.getValueStr(), \"010203\");\n\n  data = {0xde, 0xad, 0xbe, 0xef};\n  encoding.setParam(data.data(), data.size());\n  EXPECT_EQ(encoding.getValueStr(), \"deadbeef\");\n}\n\nTEST(BinaryParameter, default)\n{\n  std::vector<uint8_t> data;\n\n  data = {1, 2, 3};\n  core::BinaryParameter def(\"binaryparam\", \"\", data.data(), data.size());\n\n  EXPECT_TRUE(def.isDefault());\n\n  data = {4, 5, 6};\n  def.setParam(data.data(), data.size());\n  EXPECT_FALSE(def.isDefault());\n\n  data = {1, 2, 3};\n  def.setParam(data.data(), data.size());\n  EXPECT_TRUE(def.isDefault());\n}\n\nTEST(BinaryParameter, immutable)\n{\n  std::vector<uint8_t> data;\n\n  core::BinaryParameter immutable(\"binaryparam\", \"\", nullptr, 0);\n\n  immutable.setImmutable();\n  data = {1, 2, 3};\n  immutable.setParam(data.data(), data.size());\n  immutable.setParam(\"deadbeef\");\n  EXPECT_EQ(immutable.getData().size(), 0);\n}\n\nTEST(IntListParameter, values)\n{\n  std::list<int> data;\n\n  core::IntListParameter list(\"listparam\", \"\", {});\n\n  list.setParam({1, 2, 3, 4});\n  data = {1, 2, 3, 4};\n  EXPECT_EQ(list, data);\n}\n\nTEST(IntListParameter, strings)\n{\n  std::list<int> data;\n\n  core::IntListParameter strings(\"listparam\", \"\", {});\n\n  strings.setParam(\"1,2,3,4\");\n  data = {1, 2, 3, 4};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"5 ,   6 , 7,8\");\n  data = {5, 6, 7, 8};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"9,\\n10,\\t11,\\t12\");\n  data = {9, 10, 11, 12};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"\");\n  data = {};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"   \");\n  data = {};\n  EXPECT_EQ(strings, data);\n}\n\nTEST(IntListParameter, minmax)\n{\n  std::list<int> data;\n\n  core::IntListParameter bounds(\"listparam\", \"\", {}, 20, 100);\n\n  EXPECT_TRUE(bounds.setParam({57, 73}));\n  data = {57, 73};\n  EXPECT_EQ(bounds, data);\n\n  EXPECT_FALSE(bounds.setParam({57, 123}));\n  data = {57, 73};\n  EXPECT_EQ(bounds, data);\n\n  EXPECT_FALSE(bounds.setParam(\"57,123\"));\n  data = {57, 73};\n  EXPECT_EQ(bounds, data);\n\n  EXPECT_FALSE(bounds.setParam({57, -30}));\n  data = {57, 73};\n  EXPECT_EQ(bounds, data);\n\n  EXPECT_FALSE(bounds.setParam(\"57,-30\"));\n  data = {57, 73};\n  EXPECT_EQ(bounds, data);\n}\n\nTEST(IntListParameter, minmaxdefault)\n{\n  EXPECT_THROW({\n    core::IntListParameter defbounds(\"listparam\", \"\", {10}, 20, 100);\n  }, std::invalid_argument);\n}\n\nTEST(IntListParameter, validation)\n{\n  std::list<int> data;\n\n  core::IntListParameter valid(\"listparam\", \"\", {});\n\n  EXPECT_TRUE(valid.setParam(\"1,2,3,4\"));\n  data = {1, 2, 3, 4};\n  EXPECT_EQ(valid, data);\n\n  EXPECT_FALSE(valid.setParam(\"foo\"));\n  data = {1, 2, 3, 4};\n  EXPECT_EQ(valid, data);\n\n  EXPECT_FALSE(valid.setParam(\"1,2,x,4\"));\n  data = {1, 2, 3, 4};\n  EXPECT_EQ(valid, data);\n}\n\nTEST(IntListParameter, encoding)\n{\n  std::list<int> data;\n\n  core::IntListParameter encoding(\"listparam\", \"\", {});\n\n  encoding.setParam({1, 2, 3, 4});\n  EXPECT_EQ(encoding.getValueStr(), \"1,2,3,4\");\n}\n\nTEST(IntListParameter, default)\n{\n  std::list<int> data;\n\n  core::IntListParameter def(\"listparam\", \"\", {1, 2, 3});\n\n  EXPECT_TRUE(def.isDefault());\n\n  def.setParam({4, 5, 6});\n  EXPECT_FALSE(def.isDefault());\n\n  def.setParam({1, 2, 3});\n  EXPECT_TRUE(def.isDefault());\n}\n\nTEST(IntListParameter, immutable)\n{\n  std::list<int> data;\n\n  core::IntListParameter immutable(\"listparam\", \"\", {});\n\n  immutable.setImmutable();\n  immutable.setParam({1, 2, 3, 4});\n  immutable.setParam(\"1,2,3,4\");\n  EXPECT_TRUE(immutable.begin() == immutable.end());\n}\n\nTEST(StringListParameter, values)\n{\n  std::list<std::string> data;\n\n  core::StringListParameter list(\"listparam\", \"\", {});\n\n  list.setParam({\"1\", \"2\", \"3\", \"4\"});\n  data = {\"1\", \"2\", \"3\", \"4\"};\n  EXPECT_EQ(list, data);\n}\n\nTEST(StringListParameter, strings)\n{\n  std::list<std::string> data;\n\n  core::StringListParameter strings(\"listparam\", \"\", {});\n\n  strings.setParam(\"1,2,3,4\");\n  data = {\"1\", \"2\", \"3\", \"4\"};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"5 ,   6 , 7,8\");\n  data = {\"5\", \"6\", \"7\", \"8\"};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"9,\\n10,\\t11,\\t12\");\n  data = {\"9\", \"10\", \"11\", \"12\"};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"\");\n  data = {};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"  \");\n  data = {};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"a, , b\");\n  data = {\"a\", \"\", \"b\"};\n  EXPECT_EQ(strings, data);\n}\n\nTEST(StringListParameter, null)\n{\n  // NULL default value\n  EXPECT_THROW({\n    core::StringListParameter defnull(\"enumparam\", \"\", {nullptr});\n  }, std::invalid_argument);\n}\n\nTEST(StringListParameter, encoding)\n{\n  core::StringListParameter encoding(\"listparam\", \"\", {});\n\n  encoding.setParam({\"1\", \"2\", \"3\", \"4\"});\n  EXPECT_EQ(encoding.getValueStr(), \"1,2,3,4\");\n}\n\nTEST(StringListParameter, default)\n{\n  core::StringListParameter def(\"listparam\", \"\", {\"1\", \"2\", \"3\"});\n\n  EXPECT_TRUE(def.isDefault());\n\n  def.setParam({\"4\", \"5\", \"6\"});\n  EXPECT_FALSE(def.isDefault());\n\n  def.setParam({\"1\", \"2\", \"3\"});\n  EXPECT_TRUE(def.isDefault());\n}\n\nTEST(StringListParameter, immutable)\n{\n  std::list<std::string> data;\n\n  core::StringListParameter immutable(\"listparam\", \"\", {\"a\", \"b\"});\n\n  immutable.setImmutable();\n  immutable.setParam({\"1\", \"2\", \"3\", \"4\"});\n  immutable.setParam(\"1,2,3,4\");\n  data = {\"a\", \"b\"};\n  EXPECT_EQ(immutable, data);\n}\n\nTEST(EnumListParameter, values)\n{\n  std::list<std::string> data;\n\n  core::EnumListParameter list(\"listparam\", \"\", {\"a\", \"b\", \"c\"}, {\"a\"});\n\n  list.setParam({\"a\", \"b\", \"c\"});\n  data = {\"a\", \"b\", \"c\"};\n  EXPECT_EQ(list, data);\n}\n\nTEST(EnumListParameter, caseinsensitive)\n{\n  std::list<std::string> data;\n\n  core::EnumListParameter casecmp(\"listparam\", \"\", {\"a\", \"b\", \"c\"}, {\"a\"});\n\n  casecmp.setParam({\"A\", \"B\", \"C\"});\n  data = {\"a\", \"B\", \"c\"};\n  EXPECT_EQ(casecmp, data);\n}\n\nTEST(EnumListParameter, strings)\n{\n  std::list<std::string> data;\n\n  core::EnumListParameter strings(\"listparam\", \"\", {\"a\", \"b\", \"c\"}, {\"a\"});\n\n  strings.setParam(\"a,b,c\");\n  data = {\"a\", \"b\", \"c\"};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"c ,   b , a,a\");\n  data = {\"c\", \"b\", \"a\", \"a\"};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"b,\\na,\\tc,\\tb\");\n  data = {\"b\", \"a\", \"c\", \"b\"};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"\");\n  data = {};\n  EXPECT_EQ(strings, data);\n\n  strings.setParam(\"  \");\n  data = {};\n  EXPECT_EQ(strings, data);\n}\n\nTEST(EnumListParameter, validation)\n{\n  std::list<std::string> data;\n\n  core::EnumListParameter valid(\"enumparam\", \"\", {\"a\", \"b\", \"c\"}, {\"a\"});\n\n  EXPECT_TRUE(valid.setParam({\"a\", \"b\", \"c\"}));\n  data = {\"a\", \"b\", \"c\"};\n  EXPECT_EQ(valid, data);\n\n  EXPECT_FALSE(valid.setParam({\"a\", \"foo\", \"c\"}));\n  data = {\"a\", \"b\", \"c\"};\n  EXPECT_EQ(valid, data);\n}\n\nTEST(EnumListParameter, validdefault)\n{\n  EXPECT_THROW({\n    core::EnumListParameter defvalid(\"enumparam\", \"\", {\"a\", \"b\", \"c\"}, {\"d\"});\n  }, std::invalid_argument);\n}\n\nTEST(EnumListParameter, null)\n{\n  // NULL default value\n  EXPECT_THROW({\n    core::EnumListParameter defnull(\"enumparam\", \"\", {\"\"}, {nullptr});\n  }, std::invalid_argument);\n\n  // NULL enum value\n  EXPECT_THROW({\n    core::EnumListParameter nullenum(\"enumparam\", \"\", {\"a\", nullptr, \"b\"}, {\"a\"});\n  }, std::invalid_argument);\n}\n\nTEST(EnumListParameter, encoding)\n{\n  core::EnumListParameter encoding(\"listparam\", \"\", {\"a\", \"b\", \"c\"}, {\"a\"});\n\n  encoding.setParam({\"a\", \"b\", \"C\"});\n  EXPECT_EQ(encoding.getValueStr(), \"a,b,c\");\n}\n\nTEST(EnumListParameter, default)\n{\n  core::EnumListParameter def(\"listparam\", \"\", {\"a\", \"b\", \"c\"}, {\"a\"});\n\n  EXPECT_TRUE(def.isDefault());\n\n  def.setParam({\"a\", \"b\", \"c\"});\n  EXPECT_FALSE(def.isDefault());\n\n  def.setParam(\"A\");\n  EXPECT_TRUE(def.isDefault());\n}\n\nTEST(EnumListParameter, immutable)\n{\n  std::list<std::string> data;\n\n  core::EnumListParameter immutable(\"listparam\", \"\", {\"a\", \"b\", \"c\"}, {\"a\"});\n\n  immutable.setImmutable();\n  immutable.setParam({\"a\", \"b\", \"c\"});\n  immutable.setParam(\"a,b,c\");\n  data = {\"a\"};\n  EXPECT_EQ(immutable, data);\n}\n\nint main(int argc, char** argv)\n{\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "tests/unit/pixelformat.cxx",
    "content": "/* Copyright 2019-2025 Pierre Ossman <ossman@cendio.se> for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <list>\n#include <stdexcept>\n\n#include <gtest/gtest.h>\n\n#include <rfb/PixelFormat.h>\n\nstruct Params {\n  int b;\n  int d;\n  bool e;\n  bool t;\n  int rm;\n  int gm;\n  int bm;\n  int rs;\n  int gs;\n  int bs;\n};\n\nstatic std::ostream& operator<<(std::ostream& os, const Params& p)\n{\n  return os << p.b << \", \" << p.d << \", \" <<\n         (p.e ? \"true\" : \"false\") << \" \" <<\n         (p.t ? \"true\" : \"false\") << \", \" <<\n         p.rm << \", \" << p.gm << \", \" << p.bm << \", \"\n         << p.rs << \", \" << p.gs << \", \" << p.bs;\n}\n\ntypedef testing::TestWithParam<Params> PixelFormatValid;\n\nTEST_P(PixelFormatValid, constructor)\n{\n  Params params;\n  rfb::PixelFormat* pf;\n\n  params = GetParam();\n  pf = nullptr;\n\n  EXPECT_NO_THROW({\n    pf = new rfb::PixelFormat(params.b, params.d, params.e, params.t,\n                              params.rm, params.gm, params.bm,\n                              params.rs, params.gs, params.bs);\n  });\n\n  delete pf;\n}\n\ntypedef testing::TestWithParam<Params> PixelFormatInvalid;\n\nTEST_P(PixelFormatInvalid, constructor)\n{\n  Params params;\n  rfb::PixelFormat* pf;\n\n  params = GetParam();\n  pf = nullptr;\n\n  EXPECT_THROW({\n    pf = new rfb::PixelFormat(params.b, params.d, params.e, params.t,\n                              params.rm, params.gm, params.bm,\n                              params.rs, params.gs, params.bs);\n  }, std::invalid_argument);\n\n  delete pf;\n}\n\ntypedef testing::TestWithParam<Params> PixelFormatIs888;\n\nTEST_P(PixelFormatIs888, constructor)\n{\n  Params params;\n  rfb::PixelFormat* pf;\n\n  params = GetParam();\n  pf = new rfb::PixelFormat(params.b, params.d, params.e, params.t,\n                            params.rm, params.gm, params.bm,\n                            params.rs, params.gs, params.bs);\n  EXPECT_TRUE(pf->is888());\n\n  delete pf;\n}\n\ntypedef testing::TestWithParam<Params> PixelFormatNot888;\n\nTEST_P(PixelFormatNot888, constructor)\n{\n  Params params;\n  rfb::PixelFormat* pf;\n\n  params = GetParam();\n  pf = new rfb::PixelFormat(params.b, params.d, params.e, params.t,\n                            params.rm, params.gm, params.bm,\n                            params.rs, params.gs, params.bs);\n  EXPECT_FALSE(pf->is888());\n\n  delete pf;\n}\n\nstatic std::list<Params> validFormats()\n{\n  std::list<Params> params;\n\n  /* Normal true color formats */\n\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 0, 8, 16});\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 24, 16, 8});\n\n  params.push_back(Params{16, 16, false, true, 15, 31, 15, 0, 5, 11});\n\n  params.push_back(Params{8, 8, false, true, 3, 7, 3, 0, 2, 5});\n\n  /* Excessive bpp */\n\n  params.push_back(Params{32, 16, false, true, 15, 31, 15, 0, 5, 11});\n\n  params.push_back(Params{16, 16, false, true, 15, 31, 15, 0, 5, 11});\n\n  params.push_back(Params{32, 8, false, true, 3, 7, 3, 0, 2, 5});\n\n  params.push_back(Params{16, 8, false, true, 3, 7, 3, 0, 2, 5});\n\n  /* Colour map */\n\n  params.push_back(Params{8, 8, false, false, 0, 0, 0, 0, 0, 0});\n\n  return params;\n}\n\nINSTANTIATE_TEST_SUITE_P(, PixelFormatValid, testing::ValuesIn(validFormats()));\n\nstatic std::list<Params> invalidFormats()\n{\n  std::list<Params> params;\n\n  params.push_back(Params{64, 24, false, true, 255, 255, 255, 0, 8, 16});\n\n  params.push_back(Params{18, 16, false, true, 15, 31, 15, 0, 5, 11});\n\n  params.push_back(Params{3, 3, false, true, 1, 1, 1, 0, 1, 2});\n\n  /* Invalid depth */\n\n  params.push_back(Params{16, 24, false, true, 15, 31, 15, 0, 5, 11});\n\n  params.push_back(Params{8, 24, false, true, 3, 7, 3, 0, 2, 5});\n  params.push_back(Params{8, 16, false, true, 3, 7, 3, 0, 2, 5});\n\n  params.push_back(Params{32, 24, false, false, 0, 0, 0, 0, 0, 0});\n\n  /* Invalid max values */\n\n  params.push_back(Params{32, 24, false, true, 254, 255, 255, 0, 8, 16});\n  params.push_back(Params{32, 24, false, true, 255, 253, 255, 0, 8, 16});\n  params.push_back(Params{32, 24, false, true, 255, 255, 252, 0, 8, 16});\n\n  params.push_back(Params{32, 24, false, true, 511, 127, 127, 0, 16, 20});\n  params.push_back(Params{32, 24, false, true, 127, 511, 127, 0, 4, 20});\n  params.push_back(Params{32, 24, false, true, 127, 127, 511, 0, 4, 8});\n\n  /* Insufficient depth */\n\n  params.push_back(Params{32, 16, false, true, 255, 255, 255, 0, 8, 16});\n\n  /* Invalid shift values */\n\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 25, 8, 16});\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 0, 25, 16});\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 0, 8, 25});\n\n  /* Overlapping channels */\n\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 0, 7, 16});\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 0, 8, 15});\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 0, 16, 7});\n\n  return params;\n}\n\nINSTANTIATE_TEST_SUITE_P(, PixelFormatInvalid, testing::ValuesIn(invalidFormats()));\n\nstatic std::list<Params> is888Formats()\n{\n  std::list<Params> params;\n\n  /* Positive cases */\n\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 0, 8, 16});\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 24, 16, 8});\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 24, 8, 0});\n\n  return params;\n}\n\nINSTANTIATE_TEST_SUITE_P(, PixelFormatIs888, testing::ValuesIn(is888Formats()));\n\nstatic std::list<Params> not888Formats()\n{\n  std::list<Params> params;\n\n  /* Low depth */\n\n  params.push_back(Params{32, 16, false, true, 15, 31, 15, 0, 8, 16});\n  params.push_back(Params{32, 8, false, true, 3, 7, 3, 0, 8, 16});\n\n  /* Low bpp and depth */\n\n  params.push_back(Params{16, 16, false, true, 15, 31, 15, 0, 5, 11});\n  params.push_back(Params{8, 8, false, true, 3, 7, 3, 0, 2, 5});\n\n  /* Colour map */\n\n  params.push_back(Params{8, 8, false, false, 0, 0, 0, 0, 0, 0});\n\n  /* Odd shifts */\n\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 0, 8, 18});\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 0, 11, 24});\n  params.push_back(Params{32, 24, false, true, 255, 255, 255, 4, 16, 24});\n\n  return params;\n}\n\nINSTANTIATE_TEST_SUITE_P(, PixelFormatNot888, testing::ValuesIn(not888Formats()));\n\nint main(int argc, char** argv)\n{\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "tests/unit/shortcuthandler.cxx",
    "content": "/* Copyright 2021-2025 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <gtest/gtest.h>\n\n#define XK_LATIN1\n#define XK_MISCELLANY\n#include <rfb/keysymdef.h>\n\n#include \"ShortcutHandler.h\"\n\nTEST(ShortcutHandler, noModifiers)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(0);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_a), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_Hyper_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(5, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(5), ShortcutHandler::KeyNormal);\n}\n\nTEST(ShortcutHandler, singleArmed)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyUnarm);\n}\n\nTEST(ShortcutHandler, singleDualArmed)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_R), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyUnarm);\n}\n\nTEST(ShortcutHandler, singleShortcut)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, singleRightShortcut)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_R), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, singleDualShortcut)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_R), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, singleShortcutReordered)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyShortcut);\n}\n\nTEST(ShortcutHandler, singleDualShortcutReordered)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_R), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, singleShortcutRepeated)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, singleShortcutMultipleKeys)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_b), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_c), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, singleWedgeNormal)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_b), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_a), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n}\n\nTEST(ShortcutHandler, singleWedgeModifier)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_a), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n}\n\nTEST(ShortcutHandler, singleWedgeModifierArmed)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_a), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n}\n\nTEST(ShortcutHandler, singleWedgeModifierFiring)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, singleUnwedge)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control);\n\n  handler.handleKeyPress(1, XK_Shift_L);\n  handler.handleKeyPress(2, XK_Control_L);\n  handler.handleKeyRelease(1);\n  handler.handleKeyRelease(2);\n\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, multiArmed)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyUnarm);\n}\n\nTEST(ShortcutHandler, multiRearmed)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyUnarm);\n}\n\nTEST(ShortcutHandler, multiFailedArm)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyNormal);\n}\n\nTEST(ShortcutHandler, multiDualArmed)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Alt_R), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyUnarm);\n}\n\nTEST(ShortcutHandler, multiShortcut)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, multiRightShortcut)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_R), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_R), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_R), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, multiDualShortcut)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_R), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_Alt_R), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(5, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(6, XK_Shift_R), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(7, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(7), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(6), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(5), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, multiShortcutReordered)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyShortcut);\n}\n\nTEST(ShortcutHandler, multiDualShortcutReordered)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(5, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(7, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_R), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_Alt_R), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyPress(6, XK_Shift_R), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(6), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(7), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(5), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, multiShortcutRepeated)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, multiShortcutMultipleKeys)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyPress(5, XK_b), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(5), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyPress(6, XK_c), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(6), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, multiWedgeNormal)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_b), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(5, XK_a), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(5), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n}\n\nTEST(ShortcutHandler, multiWedgeModifier)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Super_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(5, XK_a), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(5), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n}\n\nTEST(ShortcutHandler, multiWedgeArming)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(1, XK_b), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(5, XK_a), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(5), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n}\n\nTEST(ShortcutHandler, multiWedgeModifierArming)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_Super_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyNormal);\n}\n\nTEST(ShortcutHandler, multiWedgeModifierArmed)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_Super_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyNormal);\n}\n\nTEST(ShortcutHandler, multiWedgeModifierFiring)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  EXPECT_EQ(handler.handleKeyPress(1, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyPress(5, XK_Super_L), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(5), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(1), ShortcutHandler::KeyIgnore);\n}\n\nTEST(ShortcutHandler, multiUnwedge)\n{\n  ShortcutHandler handler;\n\n  handler.setModifiers(ShortcutHandler::Control |\n                       ShortcutHandler::Shift |\n                       ShortcutHandler::Alt);\n\n  handler.handleKeyPress(1, XK_Super_L);\n  handler.handleKeyPress(2, XK_Control_L);\n  handler.handleKeyPress(3, XK_Alt_L);\n  handler.handleKeyPress(4, XK_Shift_L);\n  handler.handleKeyRelease(1);\n  handler.handleKeyRelease(2);\n  handler.handleKeyRelease(3);\n  handler.handleKeyRelease(4);\n\n  EXPECT_EQ(handler.handleKeyPress(2, XK_Control_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(3, XK_Alt_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(4, XK_Shift_L), ShortcutHandler::KeyNormal);\n  EXPECT_EQ(handler.handleKeyPress(5, XK_a), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(5), ShortcutHandler::KeyShortcut);\n  EXPECT_EQ(handler.handleKeyRelease(4), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(3), ShortcutHandler::KeyIgnore);\n  EXPECT_EQ(handler.handleKeyRelease(2), ShortcutHandler::KeyIgnore);\n}\n\nint main(int argc, char** argv)\n{\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "tests/unit/unicode.cxx",
    "content": "/* Copyright 2020-2025 Pierre Ossman <ossman@cendio.se> for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string.h>\n#include <wchar.h>\n\n#include <gtest/gtest.h>\n\n#include <core/string.h>\n\nstruct _ucs4utf8 {\n    unsigned ucs4;\n    const char *utf8;\n};\n\nstruct _ucs4utf16 {\n    unsigned ucs4;\n    const wchar_t *utf16;\n};\n\nstruct _latin1utf8 {\n    const char *latin1;\n    const char *utf8;\n};\n\nstruct _utf8utf16 {\n    const char *utf8;\n    const wchar_t *utf16;\n};\nstruct _utf8ascii {\n    const char *utf8;\n    const char *ascii;\n};\n\nstruct _ucs4utf8 ucs4utf8[] = {\n    { 0x0061, \"a\" },\n    { 0x00f6, \"\\xc3\\xb6\" },\n    { 0x263a, \"\\xe2\\x98\\xba\" },\n    { 0x1f638, \"\\xf0\\x9f\\x98\\xb8\" },\n    { 0x2d006, \"\\xf0\\xad\\x80\\x86\" },\n    { 0xfffd, \"\\xe5\\xe4\" },\n    { 0xfffd, \"\\xed\\xa2\\x80\" },\n    { 0xfffd, \"\\xed\\xbb\\xbf\" },\n    { 0xd880, \"\\xef\\xbf\\xbd\" },\n    { 0xdeff, \"\\xef\\xbf\\xbd\" },\n    { 0x110200, \"\\xef\\xbf\\xbd\" },\n};\n\nstruct _ucs4utf16 ucs4utf16[] = {\n    { 0x0061, L\"a\" },\n    { 0x00f6, L\"\\xf6\" },\n    { 0x263a, L\"\\x263a\" },\n    { 0x1f638, L\"\\xd83d\\xde38\" },\n    { 0x2d006, L\"\\xd874\\xdc06\" },\n    { 0xfffd, L\"\\xdc40\\xdc12\" },\n    { 0x110200, L\"\\xfffd\" },\n    { 0xd87f, L\"\\xfffd\" },\n};\n\nstruct _latin1utf8 latin1utf8[] = {\n    { \"abc\",            \"abc\" },\n    { \"\\xe5\\xe4\\xf6\",   \"\\xc3\\xa5\\xc3\\xa4\\xc3\\xb6\" },\n    { \"???\",            \"\\xe2\\x98\\xb9\\xe2\\x98\\xba\\xe2\\x98\\xbb\" },\n    { \"?\",              \"\\xe5\\xe4\" },\n};\n\nstruct _utf8utf16 utf8utf16[] = {\n    { \"abc\",                                                L\"abc\" },\n    { \"\\xc3\\xa5\\xc3\\xa4\\xc3\\xb6\",                           L\"\\xe5\\xe4\\xf6\" },\n    { \"\\xe2\\x98\\xb9\\xe2\\x98\\xba\\xe2\\x98\\xbb\",               L\"\\x2639\\x263a\\x263b\" },\n    { \"\\xf0\\x9f\\x98\\xb8\\xf0\\x9f\\x99\\x81\\xf0\\x9f\\x99\\x82\",   L\"\\xd83d\\xde38\\xd83d\\xde41\\xd83d\\xde42\" },\n    { \"\\xf0\\xad\\x80\\x86\\xf0\\xad\\x80\\x88\",                   L\"\\xd874\\xdc06\\xd874\\xdc08\" },\n    { \"\\xef\\xbf\\xbd\\xc3\\xa5\",                               L\"\\xd840\\xe5\" },\n    { \"\\xed\\xa1\\xbf\",                                       L\"\\xfffd\" },\n};\n\nstruct _utf8ascii utf8ascii[] = {\n    { \"abc\", \"abc\" },\n    { \"ab\\xc3\\xb6\", \"ab?\" },\n    {\"\\xf0\\x9f\\x94\\xa5\", \"?\" },\n};\n\nconst char *validutf8[] = {\n    \"abc\",\n    \"\\xc3\\xa5\\xc3\\xa4\\xc3\\xb6\",\n    \"\\xf0\\xad\\x80\\x86\",\n};\n\nconst char *invalidutf8[] = {\n    \"\\xe5\\xe4\\xf6\",\n    \"\\xf8\\xa1\\xa1\\xa1\\xa1\",\n    \"\\xed\\xa2\\x80\",\n};\n\nconst wchar_t *validutf16[] = {\n    L\"abc\",\n    L\"\\xe5\\xe4\\xf6\",\n    L\"\\xd83d\\xde38\\xd83d\\xde41\\xd83d\\xde42\",\n};\n\nconst wchar_t *invalidutf16[] = {\n    L\"\\xdc40\\xdc12\",\n};\n\nconst char *validascii[] = {\n  \"abc\",\n  \"123\",\n};\n\nconst char *invalidascii[] = {\n  \"\\x80\\xa5\",\n};\n\n#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*a))\n\nTEST(Unicode, ucs4ToUTF8)\n{\n  size_t i;\n  for (i = 0;i < ARRAY_SIZE(ucs4utf8);i++) {\n    size_t len;\n    char utf8[5];\n\n    /* Expected failure? */\n    if (ucs4utf8[i].ucs4 == 0xfffd)\n      continue;\n\n    len = core::ucs4ToUTF8(ucs4utf8[i].ucs4, utf8);\n    EXPECT_STREQ(utf8, ucs4utf8[i].utf8);\n    EXPECT_EQ(len, strlen(utf8));\n  }\n}\n\nTEST(Unicode, utf8ToUCS4)\n{\n  size_t i;\n  for (i = 0;i < ARRAY_SIZE(ucs4utf8);i++) {\n    size_t len;\n    unsigned ucs4;\n\n    /* Expected failure? */\n    if (strcmp(ucs4utf8[i].utf8, \"\\xef\\xbf\\xbd\") == 0)\n      continue;\n\n    len = core::utf8ToUCS4(ucs4utf8[i].utf8, strlen(ucs4utf8[i].utf8), &ucs4);\n    EXPECT_EQ(ucs4, ucs4utf8[i].ucs4);\n    EXPECT_EQ(len, strlen(ucs4utf8[i].utf8));\n  }\n}\n\nTEST(Unicode, ucs4ToUTF16)\n{\n  size_t i;\n  for (i = 0;i < ARRAY_SIZE(ucs4utf16);i++) {\n    size_t len;\n    wchar_t utf16[3];\n\n    /* Expected failure? */\n    if (ucs4utf16[i].ucs4 == 0xfffd)\n        continue;\n\n    len = core::ucs4ToUTF16(ucs4utf16[i].ucs4, utf16);\n    EXPECT_STREQ(utf16, ucs4utf16[i].utf16);\n    EXPECT_EQ(len, wcslen(utf16));\n  }\n}\n\nTEST(Unicode, utf16ToUCS4)\n{\n  size_t i;\n  for (i = 0;i < ARRAY_SIZE(ucs4utf16);i++) {\n    size_t len;\n    unsigned ucs4;\n\n    /* Expected failure? */\n    if (wcscmp(ucs4utf16[i].utf16, L\"\\xfffd\") == 0)\n        continue;\n\n    len = core::utf16ToUCS4(ucs4utf16[i].utf16, wcslen(ucs4utf16[i].utf16), &ucs4);\n    EXPECT_EQ(ucs4, ucs4utf16[i].ucs4);\n    EXPECT_EQ(len, wcslen(ucs4utf16[i].utf16));\n  }\n}\n\nTEST(Unicode, latin1ToUTF8)\n{\n  size_t i;\n\n  for (i = 0; i < ARRAY_SIZE(latin1utf8); i++) {\n    /* Expected failure? */\n    if (strchr(latin1utf8[i].latin1, '?') != nullptr)\n      continue;\n\n    EXPECT_EQ(core::latin1ToUTF8(latin1utf8[i].latin1), latin1utf8[i].utf8);\n  }\n}\n\nTEST(Unicode, utf8ToLatin1)\n{\n  size_t i;\n  for (i = 0; i < ARRAY_SIZE(latin1utf8); i++)\n    EXPECT_EQ(core::utf8ToLatin1(latin1utf8[i].utf8), latin1utf8[i].latin1);\n}\n\nTEST(Unicode, utf8ToAscii)\n{\n  size_t i;\n  for (i = 0; i < ARRAY_SIZE(utf8ascii); i++)\n    EXPECT_EQ(core::utf8ToAscii(utf8ascii[i].utf8), (utf8ascii[i].ascii));\n}\n\nTEST(Unicode, utf16ToUTF8)\n{\n  size_t i;\n  for (i = 0; i < ARRAY_SIZE(utf8utf16); i++) {\n    /* Expected failure? */\n    if (wcscmp(utf8utf16[i].utf16, L\"\\xfffd\") == 0)\n      continue;\n\n    EXPECT_EQ(core::utf16ToUTF8(utf8utf16[i].utf16), utf8utf16[i].utf8);\n  }\n}\n\nTEST(Unicode, utf8ToUTF16)\n{\n  size_t i;\n  for (i = 0; i < ARRAY_SIZE(utf8utf16); i++) {\n    /* Expected failure? */\n    if (strstr(utf8utf16[i].utf8, \"\\xef\\xbf\\xbd\") != nullptr)\n      continue;\n\n    EXPECT_EQ(core::utf8ToUTF16(utf8utf16[i].utf8), utf8utf16[i].utf16);\n  }\n}\n\nTEST(Unicode, isValidUTF8)\n{\n  size_t i;\n  for (i = 0; i < ARRAY_SIZE(validutf8); i++)\n    EXPECT_TRUE(core::isValidUTF8(validutf8[i]));\n  for (i = 0; i < ARRAY_SIZE(invalidutf8); i++)\n    EXPECT_FALSE(core::isValidUTF8(invalidutf8[i]));\n}\n\nTEST(Unicode, isValidUTF16)\n{\n  size_t i;\n  for (i = 0; i < ARRAY_SIZE(validutf16); i++)\n    EXPECT_TRUE(core::isValidUTF16(validutf16[i]));\n  for (i = 0; i < ARRAY_SIZE(invalidutf16); i++)\n    EXPECT_FALSE(core::isValidUTF16(invalidutf16[i]));\n}\n\nTEST(Unicode, isValidAscii)\n{\n  size_t i;\n  for (i = 0; i < ARRAY_SIZE(validascii); i++)\n    EXPECT_TRUE(core::isValidAscii(validascii[i]));\n  for (i = 0; i < ARRAY_SIZE(invalidascii); i++)\n    EXPECT_FALSE(core::isValidAscii(invalidascii[i]));\n};\n\nint main(int argc, char** argv)\n{\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "unix/CMakeLists.txt",
    "content": "if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)\n  message(FATAL_ERROR \"cmake must be invoked with the top level directory\")\nendif()\n\nadd_subdirectory(tx)\nadd_subdirectory(common)\nadd_subdirectory(vncconfig)\nadd_subdirectory(vncpasswd)\nadd_subdirectory(vncserver)\nadd_subdirectory(x0vncserver)\n\nif (ENABLE_WAYLAND)\n  add_subdirectory(w0vncserver)\nendif()\n"
  },
  {
    "path": "unix/common/CMakeLists.txt",
    "content": "add_library(unixcommon STATIC\n  randr.cxx)\n\ntarget_include_directories(unixcommon PUBLIC ${CMAKE_SOURCE_DIR}/common)\ntarget_include_directories(unixcommon PUBLIC ${CMAKE_SOURCE_DIR}/unix/common)\ntarget_link_libraries(unixcommon core rfb)\n\nif(UNIX)\n  libtool_create_control_file(unixcommon)\nendif()\n\nif(NOT WIN32)\n  set_target_properties(unixcommon\n    PROPERTIES COMPILE_FLAGS -fPIC)\nendif()\n"
  },
  {
    "path": "unix/common/RandrGlue.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2015 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n/*\n  This header defines an interface for X RandR operations. It is\n  implemented by a corresponding RandrGlue.c, either with internal\n  calls (for Xvnc/vncmodule.so) or Xlib calls (x0vncserver).\n */\n\n#ifndef RANDR_GLUE_H\n#define RANDR_GLUE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nint vncGetScreenWidth(void);\nint vncGetScreenHeight(void);\n\nint vncRandRIsValidScreenSize(int width, int height);\nint vncRandRResizeScreen(int width, int height);\nvoid vncRandRUpdateSetTime(void);\n\nint vncRandRHasOutputClones(void);\n\nint vncRandRGetOutputCount(void);\nint vncRandRGetAvailableOutputs(void);\n\nchar *vncRandRGetOutputName(int outputIdx);\n\nint vncRandRIsOutputEnabled(int outputIdx);\nint vncRandRIsOutputUsable(int outputIdx);\nint vncRandRIsOutputConnected(int outputIdx);\n\nint vncRandRCheckOutputMode(int outputIdx, int width, int height);\n\nint vncRandRDisableOutput(int outputIdx);\nint vncRandRReconfigureOutput(int outputIdx, int x, int y,\n                              int width, int height);\n\nunsigned int vncRandRGetOutputId(int outputIdx);\nint vncRandRGetOutputDimensions(int outputIdx,\n                                 int *x, int *y, int *width, int *height);\n\nint vncRandRCanCreateOutputs(int extraOutputs);\nint vncRandRCreateOutputs(int extraOutputs);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/common/randr.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2017 Pierre Ossman for Cendio AB\n * Copyright 2018 Peter Astrand <astrand@cendio.se> for Cendio AB\n * Copyright 2014 Brian P. Hinz\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdlib.h>\n\n#include <unixcommon.h>\n\n#include <core/LogWriter.h>\n\n#include <rfb/screenTypes.h>\n#include <rfb/ScreenSet.h>\n\n#include <RandrGlue.h>\n\nstatic core::LogWriter vlog(\"RandR\");\n\nstatic int ResizeScreen(bool dryrun, int fb_width, int fb_height,\n                        std::set<unsigned int>* disabledOutputs)\n{\n  vlog.debug(\"Resizing screen framebuffer to %dx%d\", fb_width, fb_height);\n\n  /*\n   * Disable outputs which are larger than the target size\n   */\n  for (int i = 0;i < vncRandRGetOutputCount();i++) {\n    int x, y, width, height;\n    if (vncRandRGetOutputDimensions(i, &x, &y, &width, &height) == 0) {\n      if (x + width > fb_width || y + height > fb_height) {\n        char *name = vncRandRGetOutputName(i);\n        vlog.debug(\"Temporarily disabling output '%s'\", name);\n        free(name);\n        if (!dryrun) {\n          /* Currently ignoring errors */\n          /* FIXME: Save output rotation and restore when configuring output */\n          vncRandRDisableOutput(i);\n          disabledOutputs->insert(vncRandRGetOutputId(i));\n        }\n      }\n    }\n  }\n\n  if (!vncRandRIsValidScreenSize(fb_width, fb_height))\n    return 0;\n\n  if (dryrun)\n    return 1;\n\n  return vncRandRResizeScreen(fb_width, fb_height);\n}\n\n\n/* Return output index of preferred output, -1 on failure */\nint getPreferredScreenOutput(OutputIdMap *outputIdMap,\n                             const std::set<unsigned int>& disabledOutputs)\n{\n  int firstDisabled = -1;\n  int firstEnabled = -1;\n  int firstConnected = -1;\n  int firstUsable = -1;\n\n  for (int i = 0;i < vncRandRGetOutputCount();i++) {\n    unsigned int output = vncRandRGetOutputId(i);\n\n    /* In use? */\n    if (outputIdMap->count(output) == 1) {\n      continue;\n    }\n\n    /* Can it be used? */\n    if (!vncRandRIsOutputUsable(i)) {\n      continue;\n    }\n\n    /* Temporarily disabled? */\n    if (disabledOutputs.count(output)) {\n      if (firstDisabled == -1) firstDisabled = i;\n    }\n\n    /* Enabled? */\n    if (vncRandRIsOutputEnabled(i)) {\n      if (firstEnabled == -1) firstEnabled = i;\n    }\n\n    /* Connected? */\n    if (vncRandRIsOutputConnected(i)) {\n      if (firstConnected == -1) firstConnected = i;\n    }\n\n    if (firstUsable == -1) firstUsable = i;\n  }\n\n  if (firstEnabled != -1) {\n    return firstEnabled;\n  } else if (firstDisabled != -1) {\n    return firstDisabled;\n  } else if (firstConnected != -1) {\n    return firstConnected;\n  } else {\n    return firstUsable; /* Possibly -1 */\n  }\n}\n\n\nrfb::ScreenSet computeScreenLayout(OutputIdMap *outputIdMap)\n{\n  rfb::ScreenSet layout;\n  OutputIdMap newIdMap;\n\n  for (int i = 0;i < vncRandRGetOutputCount();i++) {\n    unsigned int outputId;\n    int x, y, width, height;\n\n    /* Disabled? */\n    if (!vncRandRIsOutputEnabled(i))\n      continue;\n\n    outputId = vncRandRGetOutputId(i);\n\n    /* Known output? */\n    if (outputIdMap->count(outputId) == 1)\n      newIdMap[outputId] = (*outputIdMap)[outputId];\n    else {\n      uint32_t id;\n      OutputIdMap::const_iterator iter;\n\n      while (true) {\n        id = rand();\n        for (iter = outputIdMap->begin();iter != outputIdMap->end();++iter) {\n          if (iter->second == id)\n            break;\n        }\n        if (iter == outputIdMap->end())\n          break;\n      }\n\n      newIdMap[outputId] = id;\n    }\n\n    if (vncRandRGetOutputDimensions(i, &x, &y, &width, &height) == 0) {\n      layout.add_screen(rfb::Screen(newIdMap[outputId], x, y, width, height, 0));\n    }\n  }\n\n  /* Only keep the entries that are currently active */\n  *outputIdMap = newIdMap;\n\n  /*\n   * Make sure we have something to display. Hopefully it's just temporary\n   * that we have no active outputs...\n   */\n  if (layout.num_screens() == 0)\n    layout.add_screen(rfb::Screen(0, 0, 0, vncGetScreenWidth(),\n                                  vncGetScreenHeight(), 0));\n\n  return layout;\n}\n\nstatic unsigned int _setScreenLayout(bool dryrun,\n                                     int fb_width, int fb_height, const rfb::ScreenSet& layout,\n                                     OutputIdMap *outputIdMap)\n{\n  int ret;\n  int availableOutputs;\n  std::set<unsigned int> disabledOutputs;\n  /* Printing errors in the dryrun pass might be confusing */\n  const bool logErrors = !dryrun || vlog.getLevel() >= vlog.LEVEL_DEBUG;\n\n  // RandR support?\n  if (vncRandRGetOutputCount() == 0)\n    return rfb::resultProhibited;\n\n  /*\n   * First check that we don't have any active clone modes. That's just\n   * too messy to deal with.\n   */\n  if (vncRandRHasOutputClones()) {\n    if (logErrors) {\n      vlog.error(\"Clone mode active. Refusing to touch screen layout.\");\n    }\n    return rfb::resultInvalid;\n  }\n\n  /* Next count how many useful outputs we have... */\n  availableOutputs = vncRandRGetAvailableOutputs();\n\n  /* Try to create more outputs if needed... (only works on Xvnc) */\n  if (layout.num_screens() > availableOutputs) {\n    vlog.debug(\"Insufficient screens. Need to create %d more.\",\n               layout.num_screens() - availableOutputs);\n\n    if (!vncRandRCanCreateOutputs(layout.num_screens() - availableOutputs)) {\n      if (logErrors)\n        vlog.error(\"Unable to create more screens, as needed by the new client layout.\");\n      return rfb::resultInvalid;\n    }\n\n    if (!dryrun) {\n      ret = vncRandRCreateOutputs(layout.num_screens() - availableOutputs);\n      if (!ret) {\n        if (logErrors)\n          vlog.error(\"Unable to create more screens, as needed by the new client layout.\");\n        return rfb::resultInvalid;\n      }\n    }\n  }\n\n  /* First we might need to resize the screen */\n  if ((fb_width != vncGetScreenWidth()) ||\n      (fb_height != vncGetScreenHeight())) {\n    ret = ResizeScreen(dryrun, fb_width, fb_height, &disabledOutputs);\n    if (!ret) {\n      if (logErrors) {\n        vlog.error(\"Failed to resize screen to %dx%d\", fb_width, fb_height);\n      }\n      return rfb::resultInvalid;\n    }\n  }\n\n  /* Next, reconfigure all known outputs */\n  for (int i = 0;i < vncRandRGetOutputCount();i++) {\n    unsigned int output;\n    char *name_;\n    std::string name;\n\n    rfb::ScreenSet::const_iterator iter;\n\n    output = vncRandRGetOutputId(i);\n    name = name_ = vncRandRGetOutputName(i);\n    free(name_);\n\n    /* Known? */\n    if (outputIdMap->count(output) == 0)\n      continue;\n\n    /* Find the corresponding screen... */\n    for (iter = layout.begin();iter != layout.end();++iter) {\n      if (iter->id == (*outputIdMap)[output])\n        break;\n    }\n\n    /* Missing? */\n    if (iter == layout.end()) {\n      outputIdMap->erase(output);\n      continue;\n    }\n\n    /* Probably not needed, but let's be safe */\n    if (!vncRandRIsOutputUsable(i)) {\n      if (logErrors)\n        vlog.error(\"Required output '%s' cannot be used\", name.c_str());\n      return rfb::resultInvalid;\n    }\n\n    /* Possible mode? */\n    if (!vncRandRCheckOutputMode(i, iter->dimensions.width(),\n                                 iter->dimensions.height())) {\n      if (logErrors)\n        vlog.error(\"Output '%s' does not support required mode %dx%d\",\n                   name.c_str(),\n                   iter->dimensions.width(), iter->dimensions.height());\n      return rfb::resultInvalid;\n    }\n\n    vlog.debug(\"Reconfiguring output '%s' to %dx%d+%d+%d\", name.c_str(),\n               iter->dimensions.width(), iter->dimensions.height(),\n               iter->dimensions.tl.x, iter->dimensions.tl.y);\n\n    if (dryrun)\n      continue;\n\n    /* Reconfigure new mode and position */\n    ret = vncRandRReconfigureOutput(i,\n                                    iter->dimensions.tl.x,\n                                    iter->dimensions.tl.y,\n                                    iter->dimensions.width(),\n                                    iter->dimensions.height());\n    if (!ret) {\n      if (logErrors)\n        vlog.error(\"Failed to reconfigure output '%s' to %dx%d+%d+%d\",\n                   name.c_str(),\n                   iter->dimensions.width(), iter->dimensions.height(),\n                   iter->dimensions.tl.x, iter->dimensions.tl.y);\n      return rfb::resultInvalid;\n    }\n  }\n\n  /* Allocate new outputs for new screens */\n  rfb::ScreenSet::const_iterator iter;\n  for (iter = layout.begin();iter != layout.end();++iter) {\n    OutputIdMap::const_iterator oi;\n    unsigned int output;\n    char *name_;\n    std::string name;\n    int i;\n\n    /* Does this screen have an output already? */\n    for (oi = outputIdMap->begin();oi != outputIdMap->end();++oi) {\n      if (oi->second == iter->id)\n        break;\n    }\n\n    if (oi != outputIdMap->end())\n      continue;\n\n    /* Find an unused output */\n    i = getPreferredScreenOutput(outputIdMap, disabledOutputs);\n\n    /* Shouldn't happen */\n    if (i == -1) {\n      if (logErrors)\n        vlog.error(\"Cannot find an available output for new screen layout\");\n      return rfb::resultInvalid;\n    }\n    output = vncRandRGetOutputId(i);\n    name = name_ = vncRandRGetOutputName(i);\n    free(name_);\n\n    /*\n     * Make sure we already have an entry for this, or\n     * computeScreenLayout() will think it is a brand new output and\n     * assign it a random id.\n     */\n    (*outputIdMap)[output] = iter->id;\n\n    /* Probably not needed, but let's be safe */\n    if (!vncRandRIsOutputUsable(i)) {\n      if (logErrors)\n        vlog.error(\"Required new output '%s' cannot be used\", name.c_str());\n      return rfb::resultInvalid;\n    }\n\n    /* Possible mode? */\n    if (!vncRandRCheckOutputMode(i, iter->dimensions.width(),\n                                 iter->dimensions.height())) {\n      if (logErrors)\n        vlog.error(\"New output '%s' does not support required mode %dx%d\",\n                   name.c_str(),\n                   iter->dimensions.width(), iter->dimensions.height());\n      return rfb::resultInvalid;\n    }\n\n    vlog.debug(\"Reconfiguring new output '%s' to %dx%d+%d+%d\", name.c_str(),\n               iter->dimensions.width(), iter->dimensions.height(),\n               iter->dimensions.tl.x, iter->dimensions.tl.y);\n\n    if (dryrun)\n      continue;\n\n    /* Reconfigure new mode and position */\n    ret = vncRandRReconfigureOutput(i,\n                                    iter->dimensions.tl.x,\n                                    iter->dimensions.tl.y,\n                                    iter->dimensions.width(),\n                                    iter->dimensions.height());\n    if (!ret) {\n      if (logErrors)\n        vlog.error(\"Failed to reconfigure new output '%s' to %dx%d+%d+%d\",\n                   name.c_str(),\n                   iter->dimensions.width(), iter->dimensions.height(),\n                   iter->dimensions.tl.x, iter->dimensions.tl.y);\n      return rfb::resultInvalid;\n    }\n  }\n\n  /* Turn off unused outputs */\n  for (int i = 0;i < vncRandRGetOutputCount();i++) {\n    unsigned int output = vncRandRGetOutputId(i);\n\n    /* Known? */\n    if (outputIdMap->count(output) == 1)\n      continue;\n\n    /* Enabled? */\n    if (!vncRandRIsOutputEnabled(i))\n      continue;\n\n    /* Disable and move on... */\n    ret = vncRandRDisableOutput(i);\n    char *name = vncRandRGetOutputName(i);\n    if (ret) {\n      vlog.debug(\"Disabled unused output '%s'\", name);\n    } else {\n      if (logErrors) {\n        vlog.error(\"Failed to disable unused output '%s'\", name);\n      }\n      free(name);\n      return rfb::resultInvalid;\n    }\n    free(name);\n  }\n\n  /*\n   * Update timestamp for when screen layout was last changed.\n   * This is normally done in the X11 request handlers, which is\n   * why we have to deal with it manually here.\n   */\n  vncRandRUpdateSetTime();\n\n  return rfb::resultSuccess;\n}\n\n\nunsigned int setScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout,\n                             OutputIdMap *outputIdMap)\n{\n    return _setScreenLayout(false, fb_width, fb_height, layout, outputIdMap);\n}\n\n\nunsigned int tryScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout,\n                             OutputIdMap *outputIdMap)\n{\n    OutputIdMap dryrunIdMap = *outputIdMap;\n    return _setScreenLayout(true, fb_width, fb_height, layout, &dryrunIdMap);\n}\n"
  },
  {
    "path": "unix/common/unixcommon.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2015 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef UNIXCOMMON_H\n#define UNIXCOMMON_H\n\n#include <stdint.h>\n\n#include <map>\n#include <set>\n\nnamespace rfb { struct ScreenSet; }\n\ntypedef std::map<unsigned int, uint32_t> OutputIdMap;\n\nrfb::ScreenSet computeScreenLayout(OutputIdMap *outputIdMap);\n\nunsigned int setScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout,\n                             OutputIdMap *outputIdMap);\n\nunsigned int tryScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout,\n                             OutputIdMap *outputIdMap);\n\n/*\n * FIXME: This is only exposed because we still have logic in XDesktop\n *        that we haven't integrated in setScreenLayout()\n */\nint getPreferredScreenOutput(OutputIdMap *outputIdMap,\n                             const std::set<unsigned int>& disabledOutputs);\n\n#endif /* UNIXCOMMON_H */\n"
  },
  {
    "path": "unix/tx/CMakeLists.txt",
    "content": "add_library(tx STATIC\n  TXWindow.cxx)\n\ntarget_include_directories(tx SYSTEM PUBLIC ${X11_INCLUDE_DIR})\n\ntarget_include_directories(tx PUBLIC ${CMAKE_SOURCE_DIR}/common)\ntarget_include_directories(tx PUBLIC ${CMAKE_SOURCE_DIR}/common/rfb)\n\ntarget_link_libraries(tx core ${X11_LIBRARIES})\n"
  },
  {
    "path": "unix/tx/TXButton.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// TXButton.h\n//\n// A TXButton is a clickable button with some text in it.  The button must be\n// big enough to contain the text - if not then it will be resized\n// appropriately.\n//\n\n#ifndef __TXBUTTON_H__\n#define __TXBUTTON_H__\n\n#include <algorithm>\n\n#include \"TXWindow.h\"\n\n// TXButtonCallback's buttonActivate() method is called when a button is\n// activated.\nclass TXButton;\nclass TXButtonCallback {\npublic:\n  virtual void buttonActivate(TXButton* button)=0;\n};\n\n\nclass TXButton : public TXWindow, public TXEventHandler {\npublic:\n\n  TXButton(Display* dpy_, const char* text_,\n           TXButtonCallback* cb_=nullptr,\n           TXWindow* parent_=nullptr, int w=1, int h=1)\n    : TXWindow(dpy_, w, h, parent_), cb(cb_), down(false),\n      disabled_(false)\n  {\n    setEventHandler(this);\n    setText(text_);\n    gc = XCreateGC(dpy, win(), 0, nullptr);\n    XSetFont(dpy, gc, defaultFont);\n    addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask);\n  }\n\n  virtual ~TXButton() {\n    XFreeGC(dpy, gc);\n  }\n\n  // setText() changes the text in the button.\n  void setText(const char* text_) {\n    text = text_;\n    int textWidth = XTextWidth(defaultFS, text.data(), text.size());\n    int textHeight = (defaultFS->ascent + defaultFS->descent);\n    int newWidth = std::max(width(), textWidth + xPad*2 + bevel*2);\n    int newHeight = std::max(height(), textHeight + yPad*2 + bevel*2);\n    if (width() < newWidth || height() < newHeight) {\n      resize(newWidth, newHeight);\n    }\n  }\n\n  // disabled() sets or queries the disabled state of the checkbox.  A disabled\n  // checkbox cannot be changed via the user interface.\n  void disabled(bool b) { disabled_ = b; paint(); }\n  bool disabled() { return disabled_; }\n\nprivate:\n\n  void paint() {\n    int tw = XTextWidth(defaultFS, text.data(), text.size());\n    int startx = (width() - tw) / 2;\n    int starty = (height() + defaultFS->ascent - defaultFS->descent) / 2;\n    if (down || disabled_) {\n      drawBevel(gc, 0, 0, width(), height(), bevel, defaultBg, darkBg,lightBg);\n      startx++; starty++;\n    } else {\n      drawBevel(gc, 0, 0, width(), height(), bevel, defaultBg, lightBg,darkBg);\n    }\n\n    XSetForeground(dpy, gc, disabled_ ? disabledFg : defaultFg);\n    XDrawString(dpy, win(), gc, startx, starty, text.data(), text.size());\n  }\n\n  void handleEvent(TXWindow* /*w*/, XEvent* ev) override {\n    switch (ev->type) {\n    case Expose:\n      paint();\n      break;\n    case ButtonPress:\n      if (!disabled_) {\n        down = true;\n        paint();\n      }\n      break;\n    case ButtonRelease:\n      if (!down) break;\n      down = false;\n      paint();\n      if (ev->xbutton.x >= 0 && ev->xbutton.x < width() &&\n          ev->xbutton.y >= 0 && ev->xbutton.y < height()) {\n        if (cb) cb->buttonActivate(this);\n      }\n      break;\n    }\n  }\n\n  GC gc;\n  std::string text;\n  TXButtonCallback* cb;\n  bool down;\n  bool disabled_;\n};\n\n#endif\n"
  },
  {
    "path": "unix/tx/TXCheckbox.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// TXCheckbox.h\n//\n// A TXCheckbox has a box which may be \"checked\" with some text next to it.\n// The checkbox window must be big enough to contain the text - if not then it\n// will be resized appropriately.\n//\n// There are two styles of checkbox: the normal style which uses a tick in a\n// square box, and the radio style which uses a dot inside a circle.  The\n// default behaviour when clicking on the checkbox is to toggle it on or off,\n// but this behaviour can be changed by the callback object.  In particular to\n// get radiobutton behaviour, the callback must ensure that only one of a set\n// of radiobuttons is selected.\n//\n\n#ifndef __TXCHECKBOX_H__\n#define __TXCHECKBOX_H__\n\n#include <algorithm>\n\n#include \"TXWindow.h\"\n\n// TXCheckboxCallback's checkboxSelect() method is called when the state of a\n// checkbox changes.\nclass TXCheckbox;\nclass TXCheckboxCallback {\npublic:\n  virtual void checkboxSelect(TXCheckbox* checkbox)=0;\n};\n\n\nclass TXCheckbox : public TXWindow, public TXEventHandler {\npublic:\n  TXCheckbox(Display* dpy_, const char* text_, TXCheckboxCallback* cb_,\n             bool radio_=false, TXWindow* parent_=nullptr,\n             int w=1, int h=1)\n    : TXWindow(dpy_, w, h, parent_), cb(cb_), text(nullptr),\n      boxSize(radio_ ? 12 : 13), boxPad(4),\n      checked_(false), disabled_(false), radio(radio_)\n  {\n    setEventHandler(this);\n    setText(text_);\n    gc = XCreateGC(dpy, win(), 0, nullptr);\n    XSetFont(dpy, gc, defaultFont);\n    addEventMask(ExposureMask| ButtonPressMask | ButtonReleaseMask);\n  }\n\n  virtual ~TXCheckbox() {\n    XFreeGC(dpy, gc);\n    if (text) free(text);\n  }\n\n  // setText() changes the text in the checkbox.\n  void setText(const char* text_) {\n    if (text) free(text);\n    text = strdup((char*)text_);\n    int textWidth = XTextWidth(defaultFS, text, strlen(text));\n    int textHeight = (defaultFS->ascent + defaultFS->descent);\n    int newWidth = std::max(width(), textWidth + xPad*2 + boxPad*2 + boxSize);\n    int newHeight = std::max(height(), textHeight + yPad*2);\n    if (width() < newWidth || height() < newHeight) {\n      resize(newWidth, newHeight);\n    }\n  }\n\n  // checked() sets or queries the state of the checkbox\n  void checked(bool b) { checked_ = b; paint(); }\n  bool checked() { return checked_; }\n\n  // disabled() sets or queries the disabled state of the checkbox.  A disabled\n  // checkbox cannot be changed via the user interface.\n  void disabled(bool b) { disabled_ = b; paint(); }\n  bool disabled() { return disabled_; }\n\nprivate:\n  void paint() {\n    if (disabled_)\n      drawBevel(gc, xPad + boxPad, (height() - boxSize) / 2, boxSize, boxSize,\n                bevel, disabledBg, darkBg, lightBg, radio);\n    else\n      drawBevel(gc, xPad + boxPad, (height() - boxSize) / 2, boxSize, boxSize,\n                bevel, enabledBg, darkBg, lightBg, radio);\n    XSetBackground(dpy, gc, disabled_ ? disabledBg : enabledBg);\n    XSetForeground(dpy, gc, disabled_ ? disabledFg : defaultFg);\n    if (checked_) {\n      Pixmap icon = radio ? dot : tick;\n      int iconSize = radio ? dotSize : tickSize;\n      XCopyPlane(dpy, icon, win(), gc, 0, 0, iconSize, iconSize,\n                 xPad + boxPad + (boxSize - iconSize) / 2,\n                 (height() - iconSize) / 2, 1);\n    }\n    XDrawString(dpy, win(), gc, xPad + boxSize + boxPad*2,\n                (height() + defaultFS->ascent - defaultFS->descent) / 2,\n                text, strlen(text));\n  }\n\n  void handleEvent(TXWindow* /*w*/, XEvent* ev) override {\n    switch (ev->type) {\n    case Expose:\n      paint();\n      break;\n    case ButtonPress:\n      break;\n    case ButtonRelease:\n      if (ev->xbutton.x >= 0 && ev->xbutton.x < width() &&\n          ev->xbutton.y >= 0 && ev->xbutton.y < height()) {\n        if (!disabled_) {\n          checked_ = !checked_;\n          if (cb) cb->checkboxSelect(this);\n          paint();\n        }\n      }\n      break;\n    }\n  }\n\n  TXCheckboxCallback* cb;\n  GC gc;\n  char* text;\n  int boxSize;\n  int boxPad;\n  bool checked_;\n  bool disabled_;\n  bool radio;\n};\n\n#endif\n"
  },
  {
    "path": "unix/tx/TXDialog.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// TXDialog.h\n//\n// A TXDialog is a pop-up dialog window.  The dialog can be made visible by\n// calling its show() method.  Dialogs can be modal or non-modal.  For a modal\n// dialog box, the show() method only returns when the dialog box has been\n// dismissed.  For a non-modal dialog box, the show() method returns\n// immediately.\n//\n\n#ifndef __TXDIALOG_H__\n#define __TXDIALOG_H__\n\n#include <core/Exception.h>\n\n#include \"TXWindow.h\"\n#include <errno.h>\n\nclass TXDialog : public TXWindow, public TXDeleteWindowCallback {\npublic:\n  TXDialog(Display* dpy_, int width, int height, const char* name,\n           bool modal_=false)\n    : TXWindow(dpy_, width, height), done(false), ok(false), modal(modal_)\n  {\n    toplevel(name, this);\n    resize(width, height);\n  }\n\n  virtual ~TXDialog() {}\n\n  // show() makes the dialog visible.  For a modal dialog box, this processes X\n  // events until the done flag has been set, after which it returns the value\n  // of the ok flag.  For a non-modal dialog box it always returns true\n  // immediately.\n  bool show() {\n    ok = false;\n    done = false;\n    initDialog();\n    raise();\n    map();\n    if (modal) {\n      while (true) {\n        TXWindow::handleXEvents(dpy);\n        if (done) {\n          return ok;\n        }\n        fd_set rfds;\n        FD_ZERO(&rfds);\n        FD_SET(ConnectionNumber(dpy), &rfds);\n        int n = select(FD_SETSIZE, &rfds, nullptr, nullptr, nullptr);\n        if (n < 0) throw core::socket_error(\"select\", errno);\n      }\n    }\n    return true;\n  }\n\n  // initDialog() can be overridden in a derived class.  Typically it is used\n  // to make sure that checkboxes have the right state, etc.\n  virtual void initDialog() {}\n\n  // resize() is overridden here to re-center the dialog\n  void resize(int w, int h) {\n    TXWindow::resize(w,h);\n    int dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));\n    int dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));\n    setUSPosition((dpyWidth - width() - 10) / 2, (dpyHeight - height() - 30) / 2);\n  }    \n\nprotected:\n  void deleteWindow(TXWindow* /*w*/) override {\n    ok = false;\n    done = true;\n    unmap();\n  }\n\n  bool done;\n  bool ok;\n  bool modal;\n};\n\n#endif\n"
  },
  {
    "path": "unix/tx/TXLabel.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// TXLabel.h\n//\n// An TXLabel allows you to put up multiline text in a window with various\n// alignments.  The label must be big enough to contain the text - if not then\n// it will be resized appropriately.\n//\n\n#ifndef __TXLABEL_H__\n#define __TXLABEL_H__\n\n#include <stdlib.h>\n\n#include <algorithm>\n\n#include \"TXWindow.h\"\n#include <core/string.h>\n\nclass TXLabel : public TXWindow, public TXEventHandler {\npublic:\n  enum HAlign { left, centre, right };\n  enum VAlign { top, middle, bottom };\n\n  TXLabel(Display* dpy_, const char* text_, TXWindow* parent_=nullptr,\n          int w=1, int h=1, HAlign ha=centre, VAlign va=middle)\n    : TXWindow(dpy_, w, h, parent_), lineSpacing(2), lines(0),\n      halign(ha), valign(va)\n  {\n    setEventHandler(this);\n    setText(text_);\n    addEventMask(ExposureMask);\n  }\n\n  // setText() changes the text in the label.\n  void setText(const char* text_) {\n    text = text_;\n    lines = 0;\n    size_t lineStart = 0;\n    int textWidth = 0;\n    size_t i = -1;\n    do {\n      i++;\n      if (i >= text.size() || text[i] == '\\n') {\n        int tw = XTextWidth(defaultFS, &text[lineStart], i-lineStart);\n        if (tw > textWidth) textWidth = tw;\n        lineStart = i+1;\n        lines++;\n      }\n    } while (i < text.size());\n    int textHeight = ((defaultFS->ascent + defaultFS->descent + lineSpacing)\n                      * lines);\n    int newWidth = std::max(width(), textWidth + xPad*2);\n    int newHeight = std::max(height(), textHeight + yPad*2);\n    if (width() < newWidth || height() < newHeight) {\n      resize(newWidth, newHeight);\n    }\n    invalidate();\n  }\n\nprivate:\n  int xOffset(int textWidth) {\n    switch (halign) {\n    case left:  return xPad;\n    case right: return width() - xPad - textWidth;\n    default:    return (width() - textWidth) / 2;\n    }\n  }\n\n  int yOffset(int lineNum) {\n    int textHeight = ((defaultFS->ascent + defaultFS->descent + lineSpacing)\n                      * lines);\n    int lineOffset = ((defaultFS->ascent + defaultFS->descent + lineSpacing)\n                      * lineNum + defaultFS->ascent);\n    switch (valign) {\n    case top:    return yPad + lineOffset;\n    case bottom: return height() - yPad - textHeight + lineOffset;\n    default:     return (height() - textHeight) / 2 + lineOffset;\n    }\n  }\n\n  void paint() {\n    size_t lineNum = 0;\n    size_t lineStart = 0;\n    size_t i = -1;\n    do {\n      i++;\n      if (i >= text.size() || text[i] == '\\n') {\n        int tw = XTextWidth(defaultFS, &text[lineStart], i-lineStart);\n        XDrawString(dpy, win(), defaultGC, xOffset(tw), yOffset(lineNum),\n                    &text[lineStart], i-lineStart);\n        lineStart = i+1;\n        lineNum++;\n      }\n    } while (i < text.size());\n  }\n\n  void handleEvent(TXWindow* /*w*/, XEvent* ev) override {\n    switch (ev->type) {\n    case Expose:\n      paint();\n      break;\n    }\n  }\n\n  int lineSpacing;\n  std::string text;\n  int lines;\n  HAlign halign;\n  VAlign valign;\n};\n\n#endif\n"
  },
  {
    "path": "unix/tx/TXWindow.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// TXWindow.cxx\n//\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <X11/Xatom.h>\n#include \"TXWindow.h\"\n#include <list>\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <vector>\n\nstd::list<TXWindow*> windows;\n\nAtom wmProtocols, wmDeleteWindow, wmTakeFocus;\nAtom xaTIMESTAMP, xaTARGETS, xaSELECTION_TIME, xaSELECTION_STRING;\nAtom xaCLIPBOARD, xaUTF8_STRING, xaINCR;\nunsigned long TXWindow::black, TXWindow::white;\nunsigned long TXWindow::defaultFg, TXWindow::defaultBg;\nunsigned long TXWindow::lightBg, TXWindow::darkBg;\nunsigned long TXWindow::disabledFg, TXWindow::disabledBg;\nunsigned long TXWindow::enabledBg;\nunsigned long TXWindow::scrollbarBg;\nColormap TXWindow::cmap = 0;\nGC TXWindow::defaultGC = nullptr;\nFont TXWindow::defaultFont = 0;\nXFontStruct* TXWindow::defaultFS = nullptr;\nTime TXWindow::cutBufferTime = 0;\nPixmap TXWindow::dot = 0, TXWindow::tick = 0;\nconst int TXWindow::dotSize = 4, TXWindow::tickSize = 8;\nchar* TXWindow::defaultWindowClass;\n\nTXGlobalEventHandler* TXWindow::globalEventHandler = nullptr;\n\nvoid TXWindow::init(Display* dpy, const char* defaultWindowClass_)\n{\n  cmap = DefaultColormap(dpy,DefaultScreen(dpy));\n  wmProtocols = XInternAtom(dpy, \"WM_PROTOCOLS\", False);\n  wmDeleteWindow = XInternAtom(dpy, \"WM_DELETE_WINDOW\", False);\n  wmTakeFocus = XInternAtom(dpy, \"WM_TAKE_FOCUS\", False);\n  xaTIMESTAMP = XInternAtom(dpy, \"TIMESTAMP\", False);\n  xaTARGETS = XInternAtom(dpy, \"TARGETS\", False);\n  xaSELECTION_TIME = XInternAtom(dpy, \"SELECTION_TIME\", False);\n  xaSELECTION_STRING = XInternAtom(dpy, \"SELECTION_STRING\", False);\n  xaCLIPBOARD = XInternAtom(dpy, \"CLIPBOARD\", False);\n  xaUTF8_STRING = XInternAtom(dpy, \"UTF8_STRING\", False);\n  xaINCR = XInternAtom(dpy, \"INCR\", False);\n  XColor cols[6];\n  cols[0].red = cols[0].green = cols[0].blue = 0x0000;\n  cols[1].red = cols[1].green = cols[1].blue = 0xbbbb;\n  cols[2].red = cols[2].green = cols[2].blue = 0xeeee;\n  cols[3].red = cols[3].green = cols[3].blue = 0x5555;\n  cols[4].red = cols[4].green = cols[4].blue = 0x8888;\n  cols[5].red = cols[5].green = cols[5].blue = 0xffff;\n  getColours(dpy, cols, 6);\n  black = defaultFg = cols[0].pixel;\n  defaultBg = disabledBg = cols[1].pixel;\n  lightBg = cols[2].pixel;\n  darkBg = disabledFg = cols[3].pixel;\n  scrollbarBg = cols[4].pixel;\n  white = enabledBg = cols[5].pixel;\n  defaultGC = XCreateGC(dpy, DefaultRootWindow(dpy), 0, nullptr);\n  defaultFS\n    = XLoadQueryFont(dpy, \"-*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*\");\n  if (!defaultFS) {\n    defaultFS = XLoadQueryFont(dpy, \"fixed\");\n    if (!defaultFS) {\n      fprintf(stderr,\"Failed to load any font\\n\");\n      exit(1);\n    }\n  }\n  defaultFont = defaultFS->fid;\n  XSetForeground(dpy, defaultGC, defaultFg);\n  XSetBackground(dpy, defaultGC, defaultBg);\n  XSetFont(dpy, defaultGC, defaultFont);\n  XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask);\n\n  static unsigned char dotBits[] = { 0x06, 0x0f, 0x0f, 0x06};\n  dot = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), (char*)dotBits,\n                              dotSize, dotSize);\n  static unsigned char tickBits[] = { 0x80, 0xc0, 0xe2, 0x76, 0x3e, 0x1c, 0x08, 0x00};\n  tick = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), (char*)tickBits,\n                               tickSize, tickSize);\n  defaultWindowClass = strdup(defaultWindowClass_);\n}\n\nvoid TXWindow::handleXEvents(Display* dpy)\n{\n  while (XPending(dpy)) {\n    XEvent ev;\n    XNextEvent(dpy, &ev);\n    if (globalEventHandler) {\n      if (globalEventHandler->handleGlobalEvent(&ev))\n        continue;\n    }\n    if (ev.type == MappingNotify) {\n      XRefreshKeyboardMapping(&ev.xmapping);\n    } else if (ev.type == PropertyNotify &&\n               ev.xproperty.window == DefaultRootWindow(dpy) &&\n               ev.xproperty.atom == XA_CUT_BUFFER0) {\n      cutBufferTime = ev.xproperty.time;\n    } else {\n      std::list<TXWindow*>::iterator i;\n      for (i = windows.begin(); i != windows.end(); i++) {\n        if ((*i)->win() == ev.xany.window)\n          (*i)->handleXEvent(&ev);\n      }\n    }\n  }\n}\n\nTXGlobalEventHandler* TXWindow::setGlobalEventHandler(TXGlobalEventHandler* h)\n{\n  TXGlobalEventHandler* old = globalEventHandler;\n  globalEventHandler = h;\n  return old;\n}\n\nvoid TXWindow::getColours(Display* dpy, XColor* cols, int nCols)\n{\n  std::vector<bool> got;\n\n  bool failed = false;\n  int i;\n  for (i = 0; i < nCols; i++) {\n    if (XAllocColor(dpy, cmap, &cols[i])) {\n      got.push_back(true);\n    } else {\n      got.push_back(false);\n      failed = true;\n    }\n  }\n\n  if (!failed) {\n    return;\n  }\n\n  // AllocColor has failed.  This is because the colormap is full.  So the\n  // only thing we can do is use the \"shared\" pixels in the colormap.  The\n  // code below is designed to work even when the colormap isn't full so is\n  // more complex than it needs to be in this case.  However it would be\n  // useful one day to be able to restrict the number of colours allocated by\n  // an application so I'm leaving it in here.\n\n  // For each pixel in the colormap, try to allocate exactly its RGB values.\n  // If this returns a different pixel then it must be a private or\n  // unallocated pixel, so we can't use it.  If it returns us the same pixel\n  // again, it's almost certainly a shared colour, so we can use it (actually\n  // it is possible that it was an unallocated pixel which we've now\n  // allocated - by going through the pixels in reverse order we make this\n  // unlikely except for the lowest unallocated pixel - this works because of\n  // the way the X server allocates new pixels).\n\n  int cmapSize = DisplayCells(dpy,DefaultScreen(dpy));\n\n  XColor* cm = new XColor[cmapSize];\n  std::vector<bool> shared;\n  std::vector<bool> usedAsNearest;\n\n  for (i = 0; i < cmapSize; i++) {\n    cm[i].pixel = i;\n    shared.push_back(false);\n    usedAsNearest.push_back(false);\n  }\n\n  XQueryColors(dpy, cmap, cm, cmapSize);\n\n  for (i = cmapSize-1; i >= 0; i--) {\n    if (XAllocColor(dpy, cmap, &cm[i])) {\n      if (cm[i].pixel == (unsigned long)i) {\n        shared[i] = true;\n      } else {\n        XFreeColors(dpy, cmap, &cm[i].pixel, 1, 0);\n      }\n    }\n  }\n\n  for (int j = 0; j < nCols; j++) {\n    unsigned long minDistance = ULONG_MAX;\n    unsigned long nearestPixel = 0;\n    if (!got[j]) {\n      for (i = 0; i < cmapSize; i++) {\n        if (shared[i]) {\n          unsigned long rd = (cm[i].red - cols[j].red)/2;\n          unsigned long gd = (cm[i].green - cols[j].green)/2;\n          unsigned long bd = (cm[i].blue - cols[j].blue)/2;\n          unsigned long distance = (rd*rd + gd*gd + bd*bd);\n\n          if (distance < minDistance) {\n            minDistance = distance;\n            nearestPixel = i;\n          }\n        }\n      }\n\n      cols[j].pixel = nearestPixel;\n      usedAsNearest[nearestPixel] = true;\n    }\n  }\n\n  for (i = 0; i < cmapSize; i++) {\n    if (shared[i] && !usedAsNearest[i]) {\n      unsigned long p = i;\n      XFreeColors(dpy, cmap, &p, 1, 0);\n    }\n  }\n}\n\nWindow TXWindow::windowWithName(Display* dpy, Window top, const char* name)\n{\n  char* windowName;\n  if (XFetchName(dpy, top, &windowName)) {\n    if (strcmp(windowName, name) == 0) {\n      XFree(windowName);\n      return top;\n    }\n    XFree(windowName);\n  }\n\n  Window* children;\n  Window dummy;\n  unsigned int nchildren;\n  if (!XQueryTree(dpy, top, &dummy, &dummy, &children,&nchildren) || !children)\n    return 0;\n\n  for (int i = 0; i < (int)nchildren; i++) {\n    Window w = windowWithName(dpy, children[i], name);\n    if (w) {\n      XFree((char*)children);\n      return w;\n    }\n  }\n  XFree((char*)children);\n  return 0;\n}\n\n\nTXWindow::TXWindow(Display* dpy_, int w, int h, TXWindow* parent_,\n                   int borderWidth)\n  : dpy(dpy_), xPad(3), yPad(3), bevel(2), parent(parent_), width_(w),\n    height_(h), eventHandler(nullptr), dwc(nullptr), eventMask(0),\n    toplevel_(false)\n{\n  sizeHints.flags = 0;\n  XSetWindowAttributes attr;\n  attr.background_pixel = defaultBg;\n  attr.border_pixel = 0;\n  Window par = parent ? parent->win() : DefaultRootWindow(dpy);\n  win_ = XCreateWindow(dpy, par, 0, 0, width_, height_, borderWidth,\n                      CopyFromParent, CopyFromParent,\n                      (Visual*)CopyFromParent,\n                      CWBackPixel | CWBorderPixel, &attr);\n  if (parent) map();\n\n  windows.push_back(this);\n}\n\nTXWindow::~TXWindow()\n{\n  windows.remove(this);\n  XDestroyWindow(dpy, win());\n}\n\nvoid TXWindow::toplevel(const char* name, TXDeleteWindowCallback* dwc_,\n                        int argc, char** argv, const char* windowClass,\n                        bool iconic)\n{\n  toplevel_ = true;\n  XWMHints wmHints;\n  wmHints.flags = InputHint|StateHint;\n  wmHints.input = True;\n  wmHints.initial_state = iconic ? IconicState : NormalState;\n  XClassHint classHint;\n  if (!windowClass) windowClass = defaultWindowClass;\n  classHint.res_name = (char*)name;\n  classHint.res_class = (char*)windowClass;\n  XSetWMProperties(dpy, win(), nullptr, nullptr, argv, argc,\n                   &sizeHints, &wmHints, &classHint);\n  XStoreName(dpy, win(), name);\n  XSetIconName(dpy, win(), name);\n  Atom protocols[10];\n  int nProtocols = 0;\n  protocols[nProtocols++] = wmTakeFocus;\n  dwc = dwc_;\n  if (dwc)\n    protocols[nProtocols++] = wmDeleteWindow;\n  XSetWMProtocols(dpy, win(), protocols, nProtocols);\n  addEventMask(StructureNotifyMask);\n}\n\nvoid TXWindow::setName(const char* name)\n{\n  XClassHint classHint;\n  memset(&classHint, 0, sizeof(classHint));\n  XGetClassHint(dpy, win(), &classHint);\n  XFree(classHint.res_name);\n  classHint.res_name = (char*)name;\n  XSetClassHint(dpy, win(), &classHint);\n  XFree(classHint.res_class);\n  XStoreName(dpy, win(), name);\n  XSetIconName(dpy, win(), name);    \n}\n\nvoid TXWindow::setMaxSize(int w, int h)\n{\n  sizeHints.flags |= PMaxSize;\n  sizeHints.max_width = w;\n  sizeHints.max_height = h;\n  XSetWMNormalHints(dpy, win(), &sizeHints);\n}\n\nvoid TXWindow::setUSPosition(int x, int y)\n{\n  sizeHints.flags |= USPosition;\n  sizeHints.x = x;\n  sizeHints.y = y;\n  XSetWMNormalHints(dpy, win(), &sizeHints);\n  move(x, y);\n}\n\nvoid TXWindow::setGeometry(const char* geom, int x, int y, int w, int h)\n{\n  char defGeom[256];\n  sprintf(defGeom,\"%dx%d+%d+%d\",w,h,x,y);\n  XWMGeometry(dpy, DefaultScreen(dpy), strEmptyToNull((char*)geom), defGeom,\n              0, &sizeHints, &x, &y, &w, &h, &sizeHints.win_gravity);\n  sizeHints.flags |= PWinGravity;\n  setUSPosition(x, y);\n  resize(w, h);\n}\n\nTXEventHandler* TXWindow::setEventHandler(TXEventHandler* h)\n{\n  TXEventHandler* old = eventHandler;\n  eventHandler = h;\n  return old;\n}\n\nvoid TXWindow::addEventMask(long mask)\n{\n  eventMask |= mask;\n  XSelectInput(dpy, win(), eventMask);\n}\n\nvoid TXWindow::removeEventMask(long mask)\n{\n  eventMask &= ~mask;\n  XSelectInput(dpy, win(), eventMask);\n}\n\nvoid TXWindow::unmap()\n{\n  XUnmapWindow(dpy, win());\n  if (toplevel_) {\n    XUnmapEvent ue;\n    ue.type = UnmapNotify;\n    ue.display = dpy;\n    ue.event = DefaultRootWindow(dpy);\n    ue.window = win();\n    ue.from_configure = False;\n    XSendEvent(dpy, DefaultRootWindow(dpy), False,\n               (SubstructureRedirectMask|SubstructureNotifyMask),\n               (XEvent*)&ue);\n  }\n}\n\nvoid TXWindow::resize(int w, int h)\n{\n  //if (w == width_ && h == height_) return;\n  XResizeWindow(dpy, win(), w, h);\n  width_ = w;\n  height_ = h;\n  resizeNotify();\n}\n\nvoid TXWindow::setBorderWidth(int bw)\n{\n  XWindowChanges c;\n  c.border_width = bw;\n  XConfigureWindow(dpy, win(), CWBorderWidth, &c);\n}\n\nvoid TXWindow::ownSelection(Atom selection, Time time)\n{\n  XSetSelectionOwner(dpy, selection, win(), time);\n  if (XGetSelectionOwner(dpy, selection) == win()) {\n    selectionOwner_[selection] = true;\n    selectionOwnTime[selection] = time;\n  }\n}\n\nvoid TXWindow::handleXEvent(XEvent* ev)\n{\n  switch (ev->type) {\n\n  case ClientMessage:\n    if (ev->xclient.message_type == wmProtocols) {\n      if ((Atom)ev->xclient.data.l[0] == wmDeleteWindow) {\n        if (dwc) dwc->deleteWindow(this);\n      } else if ((Atom)ev->xclient.data.l[0] == wmTakeFocus) {\n        takeFocus(ev->xclient.data.l[1]);\n      }\n    }\n    break;\n\n  case ConfigureNotify:\n    if (ev->xconfigure.width != width_ || ev->xconfigure.height != height_) {\n      width_ = ev->xconfigure.width;\n      height_ = ev->xconfigure.height;\n      resizeNotify();\n    }\n    break;\n\n  case SelectionNotify:\n    if (ev->xselection.property != None) {\n      Atom type;\n      int format;\n      unsigned long nitems, after;\n      unsigned char *data;\n      XGetWindowProperty(dpy, win(), ev->xselection.property, 0, 16384, True,\n                         AnyPropertyType, &type, &format,\n                         &nitems, &after, &data);\n      if (type != None) {\n        selectionNotify(&ev->xselection, type, format, nitems, data);\n        XFree(data);\n        break;\n      }\n    }\n    selectionNotify(&ev->xselection, 0, 0, 0, nullptr);\n    break;\n\n  case SelectionRequest:\n    {\n      XSelectionEvent se;\n      se.type = SelectionNotify;\n      se.display = ev->xselectionrequest.display;\n      se.requestor = ev->xselectionrequest.requestor;\n      se.selection = ev->xselectionrequest.selection;\n      se.time = ev->xselectionrequest.time;\n      se.target = ev->xselectionrequest.target;\n      if (ev->xselectionrequest.property == None)\n        ev->xselectionrequest.property = ev->xselectionrequest.target;\n      if (!selectionOwner_[se.selection]) {\n        se.property = None;\n      } else {\n        se.property = ev->xselectionrequest.property;\n        if (se.target == xaTARGETS) {\n          Atom targets[3];\n          targets[0] = xaTIMESTAMP;\n          targets[1] = XA_STRING;\n          targets[2] = xaUTF8_STRING;\n          XChangeProperty(dpy, se.requestor, se.property, XA_ATOM, 32,\n                          PropModeReplace, (unsigned char*)targets, 3);\n        } else if (se.target == xaTIMESTAMP) {\n          Time t = selectionOwnTime[se.selection];\n          XChangeProperty(dpy, se.requestor, se.property, XA_INTEGER, 32,\n                          PropModeReplace, (unsigned char*)&t, 1);\n        } else if (se.target == XA_STRING || se.target == xaUTF8_STRING) {\n          if (!selectionRequest(se.requestor, se.selection, se.target, se.property))\n            se.property = None;\n        } else {\n          se.property = None;\n        }\n      }\n      XSendEvent(dpy, se.requestor, False, 0, (XEvent*)&se);\n      break;\n    }\n\n  case SelectionClear:\n    selectionOwner_[ev->xselectionclear.selection] = false;\n    break;\n  }\n\n  if (eventHandler) eventHandler->handleEvent(this, ev);\n}\n\nvoid TXWindow::drawBevel(GC gc, int x, int y, int w, int h, int b,\n                         unsigned long middle, unsigned long tl,\n                         unsigned long br, bool round)\n{\n  if (round) {\n    XGCValues gcv;\n    gcv.line_width = b;\n    XChangeGC(dpy, gc, GCLineWidth, &gcv);\n    XSetForeground(dpy, gc, middle);\n    XFillArc(dpy, win(), gc,  x, y, w-b/2, h-b/2, 0, 360*64);\n    XSetForeground(dpy, gc, tl);\n    XDrawArc(dpy, win(), gc,  x, y, w-b/2, h-b/2, 45*64, 180*64);\n    XSetForeground(dpy, gc, br);\n    XDrawArc(dpy, win(), gc,  x, y, w-b/2, h-b/2, 225*64, 180*64);\n  } else {\n    XSetForeground(dpy, gc, middle);\n    if (w-2*b > 0 && h-2*b > 0)\n      XFillRectangle(dpy, win(), gc, x+b, y+b, w-2*b, h-2*b);\n    XSetForeground(dpy, gc, tl);\n    XFillRectangle(dpy, win(), gc, x, y, w, b);\n    XFillRectangle(dpy, win(), gc, x, y, b, h);\n    XSetForeground(dpy, gc, br);\n    for (int i = 0; i < b; i++) {\n      if (w-i > 0) XFillRectangle(dpy, win(), gc, x+i, y+h-1-i, w-i, 1); \n      if (h-1-i > 0) XFillRectangle(dpy, win(), gc, x+w-1-i, y+i+1, 1, h-1-i);\n    }\n  }\n}\n"
  },
  {
    "path": "unix/tx/TXWindow.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// TXWindow.h\n//\n// A TXWindow is the base class for all tx windows (widgets).  In addition it\n// contains a number of static methods and members which are used throughout\n// tx.\n//\n// Before calling any other tx methods, TXWindow::init() must be called with\n// the X display to use.\n\n#ifndef __TXWINDOW_H__\n#define __TXWINDOW_H__\n\n#include <X11/X.h>\n#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n#include <map>\n\n\n// TXDeleteWindowCallback's deleteWindow() method is called when a top-level\n// window is \"deleted\" (closed) by the user using the window manager.\nclass TXWindow;\nclass TXDeleteWindowCallback {\npublic:\n  virtual void deleteWindow(TXWindow* w) = 0;\n};\n\n// TXEventHandler is an interface implemented by classes wanting to handle X\n// events on a window.  Most derived classes of window are their own event\n// handlers.\nclass TXEventHandler {\npublic:\n  virtual void handleEvent(TXWindow* w, XEvent* ev) = 0;\n};\n\n// TXGlobalEventHandler is similar to TXEventHandler but will be called early and\n// for every X event. The handler should return true to indicate that the\n// event was swallowed and shouldn't be processed further.\nclass TXGlobalEventHandler {\npublic:\n  virtual bool handleGlobalEvent(XEvent* ev) = 0;\n};\n\nclass TXWindow {\npublic:\n\n  // Constructor - creates a window of the given size, with the default\n  // background (currently grey).  It is mapped by default if it has a parent.\n  // If no parent is specified its parent is the root window and it will remain\n  // unmapped.\n  TXWindow(Display* dpy_, int width=1, int height=1,\n           TXWindow* parent_=nullptr,\n           int borderWidth=0);\n  virtual ~TXWindow();\n\n  // toplevel() declares that this is a top-level window.  Various\n  // window-manager-related properties are set on the window.  The given\n  // TXDeleteWindowCallback is notified when the window is \"deleted\" (cloesd)\n  // by the user.\n  void toplevel(const char* name, TXDeleteWindowCallback* dwc=nullptr,\n                int argc=0, char** argv=nullptr,\n                const char* windowClass=nullptr,\n                bool iconic=false);\n\n  // setMaxSize() tells the window manager the maximum size to allow a\n  // top-level window.  It has no effect on a non-top-level window.\n  void setMaxSize(int w, int h);\n\n  // setUSPosition() tells the window manager the position which the \"user\" has\n  // asked for a top-level window.  Most window managers ignore requests by a\n  // program for position, so you have to tell it that the \"user\" asked for the\n  // position.  This has no effect on a non-top-level window.\n  void setUSPosition(int x, int y);\n\n  void setGeometry(const char* geom, int x, int y, int w, int h);\n\n  void setName(const char* name);\n\n  // setTransientFor() tells the window manager that this window is \"owned\" by\n  // the given window.  The window manager can use this information as it sees\n  // fit.\n  void setTransientFor(Window w) { XSetTransientForHint(dpy, win(), w); }\n\n  // setEventHandler() sets the TXEventHandler to handle X events for this\n  // window.  It returns the previous event handler, so that handlers can chain\n  // themselves.\n  TXEventHandler* setEventHandler(TXEventHandler* h);\n\n  // Accessor methods\n  Window win() { return win_; }\n  int width() { return width_; }\n  int height() { return height_; }\n\n  // selectionOwner() returns true if this window owns the given selection.\n  bool selectionOwner(Atom selection) { return selectionOwner_[selection]; }\n\n  // Wrappers around common Xlib calls\n  void addEventMask(long mask);\n  void removeEventMask(long mask);\n  void map()                   { XMapWindow(dpy, win()); }\n  void unmap();\n  void setBg(unsigned long bg) { XSetWindowBackground(dpy, win(), bg); }\n  void move(int x, int y)      { XMoveWindow(dpy, win(), x, y); }\n  void resize(int w, int h);\n  void raise()                 { XRaiseWindow(dpy, win()); }\n  void setBorderWidth(int bw);\n  void invalidate(int x=0, int y=0, int w=0, int h=0) { XClearArea(dpy, win(), x, y, w, h, True); }\n\n  // ownSelection requests that the window owns the given selection from the\n  // given time (the time should be taken from an X event).\n  void ownSelection(Atom selection, Time time);\n\n\n  // drawBevel draws a rectangular or circular bevel filling the given\n  // rectangle, using the given colours for the middle, the top/left and the\n  // bottom/right.\n  void drawBevel(GC gc, int x, int y, int w, int h, int b,\n                 unsigned long middle, unsigned long tl, unsigned long br,\n                 bool round=false);\n\n  // Methods to be overridden in a derived class\n\n  // resizeNotify() is called whenever the window's dimensions may have\n  // changed.\n  virtual void resizeNotify() {}\n\n  // takeFocus() is called when the window has received keyboard focus from the\n  // window manager.\n  virtual void takeFocus(Time /*time*/) {}\n\n  // selectionNotify() is called when the selection owner has replied to a\n  // request for information about a selection from the selection owner.\n  virtual void selectionNotify(XSelectionEvent* /*ev*/, Atom /*type*/,\n                               int /*format*/, int /*nitems*/,\n                               void* /*data*/) {}\n\n  // selectionRequest() is called when this window is the selection owner and\n  // another X client has requested the selection.  It should set the given\n  // property on the given window to the value of the given selection,\n  // returning true if successful, false otherwise.\n  virtual bool selectionRequest(Window /*requestor*/,\n                                Atom /*selection*/,\n                                Atom /*target*/,\n                                Atom /*property*/) { return false;}\n\n  // Static methods\n\n  // init() must be called before any other tx methods.\n  static void init(Display* dpy, const char* defaultWindowClass);\n\n  // getColours() sets the pixel values in the cols array to the best available\n  // for the given rgb values, even in the case of a full colormap.\n  static void getColours(Display* dpy, XColor* cols, int nCols);\n\n  // handleXEvents() should be called whenever there are events to handle on\n  // the connection to the X display.  It process all available events, then\n  // returns when there are no more events to process.\n  static void handleXEvents(Display* dpy);\n\n  // setGlobalEventHandler() sets the TXGlobalEventHandler to intercept all\n  // X events. It returns the previous events handler, so that handlers can\n  // chain themselves.\n  static TXGlobalEventHandler* setGlobalEventHandler(TXGlobalEventHandler* h);\n\n  // windowWithName() locates a window with a given name on a display.\n  static Window windowWithName(Display* dpy, Window top, const char* name);\n\n  // strEmptyToNull() returns the string it's given but turns an empty string\n  // into null, which can be useful for passing rfb parameters to Xlib calls.\n  static char* strEmptyToNull(char* s) { return s && s[0] ? s : nullptr; }\n\n  // The following are default values for various things.\n  static unsigned long black, white;\n  static unsigned long defaultFg, defaultBg, lightBg, darkBg;\n  static unsigned long disabledFg, disabledBg, enabledBg;\n  static unsigned long scrollbarBg;\n  static GC defaultGC;\n  static Colormap cmap;\n  static Font defaultFont;\n  static XFontStruct* defaultFS;\n  static Time cutBufferTime;\n  static Pixmap dot, tick;\n  static const int dotSize, tickSize;\n  static char* defaultWindowClass;\n\n  Display* const dpy;\n\n  int xPad, yPad, bevel;\n\nprivate:\n\n  // handleXEvent() is called from handleXEvents() when an event for this\n  // window arrives.  It does general event processing before calling on to the\n  // event handler.\n  void handleXEvent(XEvent* ev);\n\n  TXWindow* parent;\n  Window win_;\n  int width_, height_;\n  TXEventHandler* eventHandler;\n  TXDeleteWindowCallback* dwc;\n  long eventMask;\n  XSizeHints sizeHints;\n  std::map<Atom,Time> selectionOwnTime;\n  std::map<Atom,bool> selectionOwner_;\n  bool toplevel_;\n\n  static TXGlobalEventHandler* globalEventHandler;\n};\n\nextern Atom wmProtocols, wmDeleteWindow, wmTakeFocus;\nextern Atom xaTIMESTAMP, xaTARGETS, xaSELECTION_TIME, xaSELECTION_STRING;\nextern Atom xaCLIPBOARD, xaUTF8_STRING, xaINCR;\n\n#endif\n"
  },
  {
    "path": "unix/w0vncserver/CMakeLists.txt",
    "content": "if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)\n  message(FATAL_ERROR \"cmake must be invoked with the top level directory\")\nendif()\n\nadd_executable(w0vncserver\n  portals/portalConstants.h\n  portals/PortalProxy.cxx\n  portals/Clipboard.cxx\n  portals/RemoteDesktop.cxx\n  portals/PortalDesktop.cxx\n  pipewire/PipeWirePixelBuffer.cxx\n  pipewire/PipeWireSource.cxx\n  pipewire/PipeWireStream.cxx\n  wayland/GWaylandSource.cxx\n  wayland/objects/Output.cxx\n  wayland/objects/Object.cxx\n  wayland/objects/DataControl.cxx\n  wayland/objects/Display.cxx\n  wayland/objects/Keyboard.cxx\n  wayland/objects/Pointer.cxx\n  wayland/objects/Seat.cxx\n  wayland/objects/Shm.cxx\n  wayland/objects/ShmPool.cxx\n  wayland/objects/VirtualPointer.cxx\n  wayland/objects/VirtualKeyboard.cxx\n  wayland/objects/ImageCaptureSource.cxx\n  wayland/objects/ImageCopyCaptureManager.cxx\n  wayland/objects/ImageCopyCaptureSession.cxx\n  wayland/objects/ImageCopyCaptureCursorSession.cxx\n  wayland/objects/ScreencopyManager.cxx\n  wayland/WaylandDesktop.cxx\n  wayland/WaylandPixelBuffer.cxx\n  qnum_to_xorgevdev.c\n  xkb_to_qnum.c\n  w0vncserver.cxx\n  parameters.cxx\n  GSocketSource.cxx\n  RFBTimerSource.cxx\n)\n\nadd_executable(w0vncserver-forget\n  w0vncserver-forget.cxx\n)\n\n# Generate protocol headers\nset(GEN_WAYLAND_SRCS \"\")\nset(WAYLAND_PROTOCOLS\n  ext-foreign-toplevel-list-v1\n  ext-image-capture-source-v1\n  ext-image-copy-capture-v1\n  wlr-screencopy-unstable-v1\n  wlr-virtual-pointer-unstable-v1\n  virtual-keyboard-unstable-v1\n  ext-data-control-v1\n)\n\nforeach(P ${WAYLAND_PROTOCOLS})\n  set(XML ${CMAKE_CURRENT_SOURCE_DIR}/wayland/protocols/${P}.xml)\n  set(H ${CMAKE_CURRENT_BINARY_DIR}/${P}.h)\n  set(C ${CMAKE_CURRENT_BINARY_DIR}/${P}.c)\n\n  add_custom_command(\n    OUTPUT ${C}\n    BYPRODUCTS ${H}\n    COMMAND ${WAYLAND_SCANNER_EXECUTABLE} private-code ${XML} ${C}\n    COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header ${XML} ${H}\n    DEPENDS ${XML}\n    COMMENT \"Generating ${C} and ${H}\"\n  )\n\n  set_source_files_properties(${H} ${C} PROPERTIES GENERATED TRUE)\n\n  list(APPEND GEN_WAYLAND_SRCS ${C})\nendforeach()\n\n# Add generated sources and headers\ntarget_sources(w0vncserver PRIVATE ${GEN_WAYLAND_SRCS})\ntarget_include_directories(w0vncserver PRIVATE ${CMAKE_CURRENT_BINARY_DIR})\n\ntarget_include_directories(w0vncserver SYSTEM PUBLIC ${GLIB_INCLUDE_DIRS})\ntarget_include_directories(w0vncserver SYSTEM PUBLIC ${GIO_INCLUDE_DIRS})\ntarget_include_directories(w0vncserver SYSTEM PUBLIC ${GOBJECT_INCLUDE_DIRS})\ntarget_include_directories(w0vncserver SYSTEM PUBLIC ${PIXMAN_INCLUDE_DIRS})\ntarget_include_directories(w0vncserver SYSTEM PUBLIC ${PIPEWIRE_INCLUDE_DIRS})\ntarget_include_directories(w0vncserver SYSTEM PUBLIC ${UUID_INCLUDE_DIRS})\ntarget_include_directories(w0vncserver SYSTEM PUBLIC ${WAYLANDCLIENT_INCLUDE_DIRS})\ntarget_include_directories(w0vncserver SYSTEM PUBLIC ${XKBCOMMON_INCLUDE_DIRS})\n\ntarget_link_libraries(w0vncserver core rfb network rdr)\ntarget_link_libraries(w0vncserver ${GLIB_LIBRARIES})\ntarget_link_libraries(w0vncserver ${GIO_LIBRARIES})\ntarget_link_libraries(w0vncserver ${GOBJECT_LIBRARIES})\ntarget_link_libraries(w0vncserver ${PIXMAN_LIBRARIES})\ntarget_link_libraries(w0vncserver ${PIPEWIRE_LIBRARIES})\ntarget_link_libraries(w0vncserver ${UUID_LIBRARIES})\ntarget_link_libraries(w0vncserver ${XKBCOMMON_LIBRARIES})\ntarget_link_libraries(w0vncserver ${WAYLANDCLIENT_LIBRARIES})\n\ntarget_link_libraries(w0vncserver-forget core)\n\ninstall(TARGETS w0vncserver w0vncserver-forget DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})\ninstall(FILES w0vncserver.man DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man1 RENAME w0vncserver.1)\ninstall(FILES w0vncserver-forget.man DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man1 RENAME w0vncserver-forget.1)\n"
  },
  {
    "path": "unix/w0vncserver/GSocketSource.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <exception>\n#include <map>\n\n#include <glib.h>\n\n#include <network/TcpSocket.h>\n#include <core/LogWriter.h>\n#include <rfb/VNCServerST.h>\n#include <rdr/FdInStream.h>\n#include <rdr/FdOutStream.h>\n\n#include \"w0vncserver.h\"\n#include \"GSocketSource.h\"\n\nstatic core::LogWriter vlog(\"GSocketMonitor\");\n\nstatic std::map<GSource*, GSocketSource*> sources;\n\nstruct SocketState {\n  void* tag;\n  bool prevHadBufferedData;\n};\n\nstruct ListenerReadyEvent {\n  GSocketSource* instance;\n  network::SocketListener* listener;\n  GIOCondition condition;\n};\n\nGSourceFuncs GSocketSource::sourceFuncs {\n  .prepare = [](GSource* source, int* timeout) {\n    assert(sources.count(source) != 0);\n    return sources[source]->prepare(timeout);\n  },\n  .check = nullptr,\n  .dispatch = [](GSource* source, GSourceFunc, void*) {\n    assert(sources.count(source) != 0);\n    return sources[source]->dispatch();\n  },\n  .finalize = nullptr,\n  .closure_callback = nullptr,\n  .closure_marshal = nullptr\n};\n\nGSocketSource::GSocketSource(rfb::VNCServer* server_,\n                             std::list<network::SocketListener*> *listeners_)\n  : source(nullptr), server(server_), listeners(listeners_)\n{\n  source = g_source_new(&sourceFuncs, sizeof(GSource));\n  previousCondition = G_IO_IN;\n\n  sources[source] = this;\n}\n\nGSocketSource::~GSocketSource()\n{\n  std::list<network::Socket*> sockets;\n\n  for (GIOChannel* channel : channels)\n    g_io_channel_unref(channel);\n\n  for (ListenerReadyEvent* event : listenerEvents)\n    delete event;\n\n  server->getSockets(&sockets);\n  for (network::Socket* sock : sockets) {\n    server->removeSocket(sock);\n    delete sock;\n  }\n\n  sources.erase(source);\n  // GLib will take care of the monitored FDs on our source\n  g_source_unref(source);\n  g_source_destroy(source);\n}\n\nvoid GSocketSource::attach(GMainContext* context)\n{\n  assert(source);\n\n  g_source_attach((GSource*)source, context);\n}\n\nvoid GSocketSource::listen()\n{\n  assert(listeners->size());\n\n  for (network::SocketListener* listener : *listeners) {\n    ListenerReadyEvent* event;\n    GIOChannel* channel;\n    int fd;\n\n    fd = listener->getFd();\n\n    channel = g_io_channel_unix_new(fd);\n    channels.push_back(channel);\n\n    event = new ListenerReadyEvent();\n    event->instance = this;\n    event->listener = listener;\n\n    listenerEvents.push_back(event);\n\n    g_io_add_watch(\n      channel,\n      static_cast<GIOCondition>((G_IO_IN | G_IO_ERR | G_IO_HUP)),\n      [](GIOChannel*, GIOCondition condition, void* data) {\n        ListenerReadyEvent* event_;\n\n        event_ = static_cast<ListenerReadyEvent*>(data);\n        event_->condition = condition;\n        return event_->instance->handleListenerReady(event_);\n      },\n      event);\n  }\n}\n\nint GSocketSource::prepare(int* timeout)\n{\n  std::list<network::Socket*> sockets;\n\n  server->getSockets(&sockets);\n\n  *timeout = -1;\n\n  for (network::Socket* sock : sockets) {\n    int fd;\n    SocketState* state;\n\n    fd = sock->getFd();\n    state = &fdMap[fd];\n    assert(state->tag);\n\n    if (sock->isShutdownRead()) {\n      vlog.debug(\"Client gone, sock %d\", fd);\n      g_source_remove_unix_fd(source, state->tag);\n      server->removeSocket(sock);\n      delete sock;\n      fdMap.erase(fd);\n      continue;\n    }\n\n    if (state->prevHadBufferedData != sock->outStream().hasBufferedData()) {\n      // FIXME: Calling g_source_modify_unix_fd() will cause the main\n      // loop to wake up immediately if it is currently blocked.\n      // Calling it while we are in prepare() will skip polling FDs\n      // and just dispatch() instead, essentially causing a busy wait.\n      // To circumvent this, we only modify which events we want to\n      // listen for if they differ from the last event loop iteration.\n      GIOCondition newEvents = static_cast<GIOCondition>(G_IO_IN | G_IO_HUP | G_IO_ERR);\n      if (sock->outStream().hasBufferedData())\n        newEvents = static_cast<GIOCondition>(newEvents | G_IO_OUT);\n      g_source_modify_unix_fd(source, state->tag, newEvents);\n      state->prevHadBufferedData = sock->outStream().hasBufferedData();\n    }\n  }\n\n  return FALSE;\n}\n\nint GSocketSource::dispatch()\n{\n  std::list<network::Socket*> sockets;\n\n  server->getSockets(&sockets);\n\n  for (network::Socket* sock : sockets) {\n    GIOCondition events;\n    int fd;\n    SocketState state;\n\n    fd = sock->getFd();\n    state = fdMap[fd];\n    assert(state.tag);\n\n    events = g_source_query_unix_fd(source, state.tag);\n\n    if (events & G_IO_HUP || events & G_IO_ERR) {\n      vlog.debug(\"Client gone, sock %d\", fd);\n      g_source_remove_unix_fd(source, state.tag);\n      server->removeSocket(sock);\n      delete sock;\n      fdMap.erase(fd);\n      continue;\n    }\n\n    if (events & G_IO_IN)\n      server->processSocketReadEvent(sock);\n    if (events & G_IO_OUT)\n      server->processSocketWriteEvent(sock);\n  }\n\n  return G_SOURCE_CONTINUE;\n}\n\nint GSocketSource::handleListenerReady(ListenerReadyEvent* event)\n{\n  network::Socket* sock;\n  network::SocketListener* listener;\n  GIOCondition condition;\n  SocketState state;\n  int fd;\n  void* tag;\n\n  listener = event->listener;\n  condition = event->condition;\n\n  if (condition & G_IO_ERR || condition & G_IO_HUP) {\n    vlog.status(\"Client connection error\");\n    return G_SOURCE_CONTINUE;\n  }\n\n  sock = listener->accept();\n  if (!sock) {\n    vlog.status(\"Client connection rejected\");\n    return G_SOURCE_CONTINUE;\n  }\n\n  if (!server->addSocket(sock)) {\n    delete sock;\n    return G_SOURCE_CONTINUE;\n  }\n\n  fd = sock->getFd();\n  tag = g_source_add_unix_fd(source, fd,\n                             static_cast<GIOCondition>((G_IO_IN | G_IO_HUP | G_IO_ERR)));\n  state.tag = tag;\n  state.prevHadBufferedData = false;\n\n  fdMap[fd] = state;\n\n  return G_SOURCE_CONTINUE;\n}\n"
  },
  {
    "path": "unix/w0vncserver/GSocketSource.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __G_SOCKET_SOURCE__H\n#define __G_SOCKET_SOURCE__H\n\n#include <list>\n#include <map>\n\n#include <glib.h>\n\nnamespace rfb { class VNCServer; }\nnamespace network { class SocketListener; }\nstruct SocketState;\nstruct ListenerReadyEvent;\n\nclass GSocketSource {\npublic:\n  GSocketSource(rfb::VNCServer* server,\n                 std::list<network::SocketListener*> *listeners);\n  ~GSocketSource();\n\n  void attach(GMainContext* context);\n  void listen();\n\nprivate:\n  int prepare(int* timeout);\n  int dispatch();\n  int handleListenerReady(ListenerReadyEvent* event);\n\nprivate:\n  GSource* source;\n  GIOCondition previousCondition;\n  rfb::VNCServer* server;\n  std::map<int, SocketState> fdMap;\n  std::list<network::SocketListener*>* listeners;\n  std::list<GIOChannel*> channels;\n  static GSourceFuncs sourceFuncs;\n  std::list<ListenerReadyEvent*> listenerEvents;\n};\n\n#endif // __G_SOCKET_SOURCE__H\n"
  },
  {
    "path": "unix/w0vncserver/RFBTimerSource.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <map>\n\n#include <glib.h>\n\n#include <core/Timer.h>\n\n#include \"w0vncserver.h\"\n#include \"RFBTimerSource.h\"\n\nstatic std::map<GSource*, RFBTimerSource*> sources;\n\nGSourceFuncs RFBTimerSource::sourceFuncs {\n  .prepare = [](GSource* source, int* timeout) {\n    assert(sources.count(source) != 0);\n    return sources[source]->prepare(timeout);\n  },\n  .check = [](GSource* source) {\n    assert(sources.count(source) != 0);\n    return sources[source]->check();\n  },\n  .dispatch = [](GSource* source, GSourceFunc, void*) {\n    assert(sources.count(source) != 0);\n    return sources[source]->dispatch();\n  },\n  .finalize = nullptr,\n  .closure_callback = nullptr,\n  .closure_marshal = nullptr\n};\n\nRFBTimerSource::RFBTimerSource()\n{\n  source = g_source_new(&sourceFuncs, sizeof(GSource));\n  sources[source] = this;\n}\n\nRFBTimerSource::~RFBTimerSource()\n{\n  sources.erase(source);\n  g_source_unref(source);\n  g_source_destroy(source);\n}\n\nvoid RFBTimerSource::attach(GMainContext* context)\n{\n  assert(source);\n\n  g_source_attach(source, context);\n}\n\nint RFBTimerSource::prepare(int* timeout)\n{\n  int nextTimeout;\n\n  *timeout = -1;\n\n  nextTimeout = core::Timer::getNextTimeout();\n\n  if (nextTimeout >= 0)\n    *timeout = nextTimeout;\n\n  return FALSE;\n}\n\nint RFBTimerSource::check()\n{\n  int nextTimeout;\n\n  nextTimeout = core::Timer::getNextTimeout();\n\n  if (nextTimeout < 0)\n    return FALSE;\n\n  return TRUE;\n}\n\nint RFBTimerSource::dispatch()\n{\n  core::Timer::checkTimeouts();\n\n  return G_SOURCE_CONTINUE;\n}\n"
  },
  {
    "path": "unix/w0vncserver/RFBTimerSource.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_TIMER_SOURCE_H__\n#define __RFB_TIMER_SOURCE_H__\n\n#include <glib.h>\n\nclass RFBTimerSource {\npublic:\n  RFBTimerSource();\n  ~RFBTimerSource();\n\n  void attach(GMainContext* context);\n\nprivate:\n  int prepare(int* timeout);\n  int check();\n  int dispatch();\nprivate:\n  GSource* source;\n  static GSourceFuncs sourceFuncs;\n};\n#endif //__RFB_TIMER_SOURCE_H__\n"
  },
  {
    "path": "unix/w0vncserver/parameters.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#include <pwd.h>\n#include <unistd.h>\n\n#include \"parameters.h\"\n\nstatic const char* defaultDesktopName();\n\ncore::IntParameter\n  rfbport(\"rfbport\",\n          \"TCP port to listen for RFB protocol\", 5900, -1, 65535);\ncore::StringParameter\n  rfbunixpath(\"rfbunixpath\",\n              \"Unix socket to listen for RFB protocol\", \"\");\ncore::IntParameter\n  rfbunixmode(\"rfbunixmode\",\n              \"Unix socket access mode\", 0600, 0000, 0777);\ncore::BoolParameter\n  localhostOnly(\"localhost\",\n                \"Only allow connections from localhost\", false);\ncore::StringParameter\n  desktopName(\"desktop\", \"Name of VNC desktop\", defaultDesktopName());\ncore::StringParameter\n  interface(\"interface\",\n            \"Listen on the specified network address\", \"all\");\n\ncore::BoolParameter\n  rawKeyboard(\"RawKeyboard\",\n              \"Send keyboard events straight through and avoid mapping \"\n              \"them to the current keyboard layout\", false);\ncore::BoolParameter\n  setPrimary(\"SetPrimary\",\n             \"Set the primary as well as the selection clipboard\",\n             true);\ncore::BoolParameter\n  sendPrimary(\"SendPrimary\",\n              \"Send the primary as well as the selection clipboard\",\n              true);\n\n\nstatic const char* defaultDesktopName()\n{\n  long host_max = sysconf(_SC_HOST_NAME_MAX);\n  if (host_max < 0)\n    return \"\";\n\n  std::vector<char> hostname(host_max + 1);\n  if (gethostname(hostname.data(), hostname.size()) == -1)\n    return \"\";\n\n  struct passwd* pwent = getpwuid(getuid());\n  if (pwent == nullptr)\n    return \"\";\n\n  int len = snprintf(nullptr, 0, \"%s@%s\", pwent->pw_name, hostname.data());\n  if (len < 0)\n    return \"\";\n\n  char* name = new char[len + 1];\n\n  snprintf(name, len + 1, \"%s@%s\", pwent->pw_name, hostname.data());\n\n  return name;\n}\n"
  },
  {
    "path": "unix/w0vncserver/parameters.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __W0VNCSERVER_PARAMETERS_H__\n#define __W0VNCSERVER_PARAMETERS_H__\n\n#include <core/Configuration.h>\n\nextern core::IntParameter rfbport;\nextern core::StringParameter rfbunixpath;\nextern core::IntParameter rfbunixmode;\nextern core::BoolParameter localhostOnly;\nextern core::StringParameter desktopName;\nextern core::StringParameter interface;\nextern core::BoolParameter rawKeyboard;\nextern core::BoolParameter setPrimary;\nextern core::BoolParameter sendPrimary;\n\n#endif // __W0VNCSERVER_PARAMETERS_H__\n"
  },
  {
    "path": "unix/w0vncserver/pipewire/PipeWirePixelBuffer.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <stdint.h>\n\n#include <glib.h>\n#include <glib-object.h>\n\n#include <pipewire/pipewire.h>\n#include <spa/param/video/raw.h>\n#include <spa/utils/defs.h>\n#include <spa/buffer/buffer.h>\n\n#include <pixman.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n#include <rfb/VNCServer.h>\n#include <rfb/PixelFormat.h>\n\n#include \"PipeWireStream.h\"\n#include \"PipeWirePixelBuffer.h\"\n\nstruct PipeWireCursor {\n  uint32_t w;\n  uint32_t h;\n  int32_t x;\n  int32_t y;\n  int32_t hotspotX;\n  int32_t hotspotY;\n};\n\nstatic core::LogWriter vlog(\"PipewirePixelBuffer\");\n\nPipeWirePixelBuffer::PipeWirePixelBuffer(int32_t pipewireFd,\n                                         uint32_t pipewireId,\n                                         rfb::VNCServer* server_)\n  : PipeWireStream(pipewireFd, pipewireId), server(server_),\n    lastSequence(0)\n{\n  cursor = new PipeWireCursor();\n}\n\nPipeWirePixelBuffer::~PipeWirePixelBuffer()\n{\n  delete cursor;\n}\n\nvoid PipeWirePixelBuffer::processBuffer(pw_buffer* buffer)\n{\n  spa_buffer* spaBuffer;\n\n  spaBuffer = buffer->buffer;\n\n  processDamage(spaBuffer);\n  processCursor(spaBuffer);\n  processFrame(spaBuffer);\n}\n\nvoid PipeWirePixelBuffer::setParameters(int width, int height,\n                                        rfb::PixelFormat pf)\n{\n  setSize(width, height);\n  setPF(pf);\n  pipewirePixelFormat = pf;\n  server->setPixelBuffer(this);\n}\n\nvoid PipeWirePixelBuffer::stopped()\n{\n  server->closeClients(\"Session stopped unexpectedly\");\n\n  PipeWireStream::stopped();\n}\n\nvoid PipeWirePixelBuffer::processFrame(spa_buffer* buffer)\n{\n  int srcStride;\n  int dstStride;\n  uint8_t* srcBuffer;\n  spa_chunk* chunk;\n  pixman_bool_t ret;\n  core::Region region;\n  std::vector<core::Rect> rects;\n  spa_meta_header* header;\n  bool frameDropped;\n\n  chunk = buffer->datas[0].chunk;\n\n  if (chunk->size == 0 || chunk->flags  & SPA_CHUNK_FLAG_CORRUPTED)\n    return;\n\n  // Check size\n  if (chunk->size != (uint32_t) (width() * height() * (pipewirePixelFormat.bpp / 8))) {\n    vlog.error(\"Invalid chunk size: %d\", chunk->size);\n    return;\n  }\n\n  header = (spa_meta_header*)spa_buffer_find_meta_data(buffer,\n                                                       SPA_META_Header,\n                                                       sizeof(*header));\n\n  // Detect dropped frames. We can't rely on the damage events we've\n  // gotten and have to mark the entire frame as damaged\n  // https://bugs.kde.org/show_bug.cgi?id=510561\n  frameDropped = (header->seq != lastSequence + 1);\n  lastSequence = header->seq;\n\n  region = frameDropped ? getRect() : accumulatedDamage;\n\n  // Clamp damage outside of framebuffer\n  region = region.intersect(getRect());\n\n  srcBuffer = (uint8_t*)buffer->datas[0].data;\n  srcStride = chunk->stride / (pipewirePixelFormat.bpp / 8);\n\n  region.get_rects(&rects);\n  for (core::Rect &rect : rects) {\n    uint8_t* dstBuffer;\n\n    dstBuffer = getBufferRW(getRect(), &dstStride);\n    ret = pixman_blt((uint32_t*)srcBuffer, (uint32_t*)dstBuffer,\n                     srcStride, dstStride, pipewirePixelFormat.bpp,\n                     getPF().bpp, rect.tl.x, rect.tl.y, rect.tl.x,\n                     rect.tl.y, rect.width(), rect.height());\n    commitBufferRW(rect);\n\n    if (!ret) {\n      uint8_t* damagedBuffer;\n\n      damagedBuffer = &srcBuffer[(pipewirePixelFormat.bpp / 8) *\n                                (rect.tl.y * srcStride + rect.tl.x)];\n      imageRect(pipewirePixelFormat, rect, damagedBuffer, srcStride);\n    }\n  }\n\n  server->add_changed(region);\n  accumulatedDamage.clear();\n}\n\nvoid PipeWirePixelBuffer::processCursor(spa_buffer* buffer)\n{\n  spa_meta_cursor* cursorData;\n  spa_meta_bitmap* cursorBitmap;\n  uint8_t* cursorBuffer;\n\n  if (!hasCursorData(buffer))\n    return;\n\n  cursorData = (spa_meta_cursor*)spa_buffer_find_meta_data(buffer,\n                                                           SPA_META_Cursor,\n                                                           sizeof(*cursorData));\n  assert(cursorData);\n\n  cursor->x = cursorData->position.x;\n  cursor->y = cursorData->position.y;\n  cursor->hotspotX = cursorData->hotspot.x;\n  cursor->hotspotY = cursorData->hotspot.y;\n\n  server->setCursorPos({cursor->x, cursor->y}, true);\n\n  // No new cursor bitmap\n  if (!cursorData->bitmap_offset)\n    return;\n\n  cursorBitmap = SPA_MEMBER(cursorData, cursorData->bitmap_offset,\n                            struct spa_meta_bitmap);\n  if (!supportedCursorPixelformat(cursorBitmap->format))\n    return;\n\n  cursorBuffer = SPA_MEMBER(cursorBitmap, cursorBitmap->offset, uint8_t);\n\n  cursor->w = cursorBitmap->size.width;\n  cursor->h = cursorBitmap->size.height;\n\n  setCursor(cursor->w, cursor->h, cursor->hotspotX,\n            cursor->hotspotY, cursorBuffer);\n}\n\nvoid PipeWirePixelBuffer::processDamage(spa_buffer* buffer)\n{\n  spa_meta* damage;\n  spa_meta_region* metaRegion;\n\n  damage = spa_buffer_find_meta(buffer, SPA_META_VideoDamage);\n\n  if (!damage)\n    return;\n\n  spa_meta_for_each(metaRegion, damage) {\n    if (!spa_meta_region_is_valid(metaRegion))\n      continue;\n\n    core::Point tl{metaRegion->region.position.x,\n                   metaRegion->region.position.y};\n    core::Point br{static_cast<int>(tl.x + metaRegion->region.size.width),\n                   static_cast<int>(tl.y + metaRegion->region.size.height)};\n    accumulatedDamage.assign_union({{tl, br}});\n  }\n}\n\nbool PipeWirePixelBuffer::hasCursorData(spa_buffer* buffer)\n{\n  spa_meta_cursor* mcs;\n\n  mcs = (spa_meta_cursor*)spa_buffer_find_meta_data(buffer,\n                                                    SPA_META_Cursor,\n                                                    sizeof(*mcs));\n\n  if (mcs && spa_meta_cursor_is_valid(mcs)) {\n      // We got new cursor position / new cursor bitmap\n      return true;\n    }\n\n  return false;\n}\n\nvoid PipeWirePixelBuffer::setCursor(int width, int height, int hotX,\n                                    int hotY,\n                                    const unsigned char* rgbaData)\n{\n  // Copied from XserverDesktop.cc\n  uint8_t* cursorData;\n\n  uint8_t *out;\n  const unsigned char *in;\n\n  cursorData = new uint8_t[width * height * 4];\n\n  // Un-premultiply alpha\n  in = rgbaData;\n  out = cursorData;\n  for (int y = 0; y < height; y++) {\n    for (int x = 0; x < width; x++) {\n      uint8_t alpha;\n\n      alpha = in[3];\n      if (alpha == 0)\n        alpha = 1; // Avoid division by zero\n\n      *out++ = (unsigned)*in++ * 255/alpha;\n      *out++ = (unsigned)*in++ * 255/alpha;\n      *out++ = (unsigned)*in++ * 255/alpha;\n      *out++ = *in++;\n    }\n  }\n\n  try {\n    server->setCursor(width, height, {hotX, hotY}, cursorData);\n  } catch (std::exception& e) {\n    vlog.error(\"PipewirePixelBuffer::setCursor: %s\",e.what());\n  }\n\n  delete [] cursorData;\n}\n\nbool PipeWirePixelBuffer::supportedCursorPixelformat(int format_)\n{\n  return format_ == SPA_VIDEO_FORMAT_RGBx ||\n         format_ == SPA_VIDEO_FORMAT_RGBA;\n}\n"
  },
  {
    "path": "unix/w0vncserver/pipewire/PipeWirePixelBuffer.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __PIPEWIRE_PIXEL_BUFFER_H__\n#define __PIPEWIRE_PIXEL_BUFFER_H__\n\n#include <rfb/PixelBuffer.h>\n#include <core/Region.h>\n#include <spa/buffer/buffer.h>\n\n#include \"PipeWireStream.h\"\n\nnamespace rfb { class VNCServer; class PixelFormat;}\n\nstruct PipeWireCursor;\n\nclass PipeWirePixelBuffer : public rfb::ManagedPixelBuffer,\n                            public PipeWireStream {\npublic:\n  PipeWirePixelBuffer(int32_t pipewireFd, uint32_t pipewireId,\n                      rfb::VNCServer* server);\n  ~PipeWirePixelBuffer();\n\nprivate:\n  virtual void processBuffer(pw_buffer* buffer) override;\n  virtual void setParameters(int width, int height, rfb::PixelFormat pf) override;\n  virtual void stopped() override;\n\nprotected:\n  void processFrame(spa_buffer* buffer);\n  void processCursor(spa_buffer* buffer);\n  void processDamage(spa_buffer* buffer);\n\n  bool hasCursorData(spa_buffer* buffer);\n\n  void setCursor(int width, int height, int hotX, int hotY,\n                 const unsigned char* rgbaData);\n  bool supportedCursorPixelformat(int format_);\n\nprivate:\n  rfb::VNCServer* server;\n  rfb::PixelFormat pipewirePixelFormat;\n  core::Region accumulatedDamage;\n  PipeWireCursor* cursor;\n  uint64_t lastSequence;\n};\n#endif // __PIPEWIRE_PIXEL_BUFFER_H__\n"
  },
  {
    "path": "unix/w0vncserver/pipewire/PipeWireSource.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <map>\n\n#include <pipewire/pipewire.h>\n#include <pipewire/stream.h>\n\n#include <core/LogWriter.h>\n\n#include \"../w0vncserver.h\"\n#include \"PipeWireSource.h\"\n\nstatic core::LogWriter vlog(\"PipewireSource\");\n\nstatic int pwInitCount = 0;\n\nstatic std::map<GSource*, PipeWireSource*> sources;\n\nGSourceFuncs PipeWireSource::pipewireSourceFuncs {\n  .prepare = nullptr,\n  .check = nullptr,\n  .dispatch = [](GSource* source, GSourceFunc, void*) {\n    assert(sources.count(source) != 0);\n    return sources[source]->sourceLoopDispatch();\n  },\n  .finalize =nullptr,\n  .closure_callback = nullptr,\n  .closure_marshal = nullptr\n};\n\nPipeWireSource::PipeWireSource()\n{\n  // pw_init() and pw_deinit() may only be called once prior to version\n  // 0.3.49.\n  if (pwInitCount++ == 0)\n    pw_init(nullptr, nullptr);\n\n  loop = pw_loop_new(nullptr);\n  pw_loop_enter(loop);\n  source = g_source_new(&pipewireSourceFuncs, sizeof(GSource));\n  g_source_add_unix_fd(source, pw_loop_get_fd (loop),\n                       (GIOCondition)(G_IO_IN | G_IO_ERR));\n  g_source_attach (source, nullptr);\n  sources[source] = this;\n}\n\nPipeWireSource::~PipeWireSource()\n{\n  sources.erase(source);\n  g_source_unref(source);\n  g_source_destroy(source);\n\n  pw_loop_leave(loop);\n  pw_loop_destroy(loop);\n\n  assert(pwInitCount > 0);\n  if (--pwInitCount == 0)\n    pw_deinit();\n}\n\nint PipeWireSource::sourceLoopDispatch()\n{\n  int result;\n\n  result = pw_loop_iterate (loop, 0);\n  if (result < 0)\n    vlog.error(\"pipewire_loop_iterate failed: %s\", g_strerror (result));\n\n  return G_SOURCE_CONTINUE;\n}\n"
  },
  {
    "path": "unix/w0vncserver/pipewire/PipeWireSource.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __PIPEWIRE_SOURCE_H__\n#define __PIPEWIRE_SOURCE_H__\n\n#include <glib.h>\n#include <pipewire/stream.h>\n\n\nclass PipeWireSource {\npublic:\n  PipeWireSource();\n  ~PipeWireSource();\n\n  pw_loop* getLoop() const { return loop; }\n\nprivate:\n  int  sourceLoopDispatch();\n  void handleStreamStateChanged(enum pw_stream_state old,\n                                enum pw_stream_state state,\n                                const char* error);\n  void handleStreamParamChanged(uint32_t id, const spa_pod* param);\n  void handleProcess();\n\nprivate:\n  pw_loop* loop;\n  GSource* source;\n  pw_stream* stream;\n  int nodeId;\n  static GSourceFuncs pipewireSourceFuncs;\n};\n\n#endif // __PIPEWIRE_SOURCE_H__\n"
  },
  {
    "path": "unix/w0vncserver/pipewire/PipeWireStream.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#include <unistd.h>\n\n#include <stdexcept>\n\n#include <pipewire/pipewire.h>\n#include <spa/param/video/format-utils.h>\n#include <spa/debug/format.h>\n#include <spa/debug/pod.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n#include <rfb/PixelFormat.h>\n\n#include \"../w0vncserver.h\"\n#include \"PipeWireSource.h\"\n#include \"PipeWireStream.h\"\n\nstatic core::LogWriter vlog(\"PipeWireStream\");\n\nconst pw_stream_events PipeWireStream::streamEventsHandler {\n  .version = PW_VERSION_STREAM_EVENTS,\n  .destroy = nullptr,\n  .state_changed = [](void* self, enum pw_stream_state old,\n                      enum pw_stream_state state, const char* error) {\n    ((PipeWireStream*)self)->handleStreamStateChanged(old, state, error);\n  },\n  .control_info = nullptr,\n  .io_changed = nullptr,\n  .param_changed = [](void* self, uint32_t id, const spa_pod* param) {\n    ((PipeWireStream*)self)->handleStreamParamChanged(id, param);\n   },\n  .add_buffer = nullptr,\n  .remove_buffer = nullptr,\n  .process = [](void* self) {\n    ((PipeWireStream*)self)->handleProcess();\n  },\n  .drained = nullptr,\n#if PW_CHECK_VERSION(0,3,39)\n  .command = nullptr,\n#endif\n#if PW_CHECK_VERSION(0,3,40)\n  .trigger_done = nullptr\n#endif\n};\n\nPipeWireStream::PipeWireStream(int pipeWireFd_, int nodeId)\n  : pipeWireFd(pipeWireFd_), active(true)\n{\n  source = new PipeWireSource();\n\n  context = pw_context_new(source->getLoop(), nullptr, 0);\n  if (!context) {\n    delete source;\n    throw std::runtime_error(\"Failed to create PipeWire context\");\n  }\n\n  core = pw_context_connect_fd(context, pipeWireFd_, nullptr, 0);\n  if (!core) {\n    pw_context_destroy(context);\n    delete source;\n    throw std::runtime_error(\"Failed to connect to PipeWire FD\");\n  }\n\n  start(nodeId);\n}\n\nPipeWireStream::~PipeWireStream()\n{\n  pw_stream_disconnect(stream);\n  // Iterate the loop once after disconnect to ensure proper cleanup.\n  // Without this, we saw issues when re-initializing PipeWire\n  pw_loop_iterate(source->getLoop(), 0);\n\n  pw_stream_destroy(stream);\n\n  pw_core_disconnect(core);\n  pw_context_destroy(context);\n\n  close(pipeWireFd);\n\n  delete source;\n}\n\nvoid PipeWireStream::start(int nodeId)\n{\n  uint8_t buffer[4096];\n  const spa_pod *params[1];\n  spa_pod_builder builder;\n  pw_properties* props;\n\n  spa_pod_builder_init(&builder, buffer, sizeof(buffer));\n\n  props = pw_properties_new(PW_KEY_REMOTE_NAME, \"pipewire-0\",\n                            PW_KEY_MEDIA_TYPE, \"Video\",\n                            PW_KEY_MEDIA_CATEGORY, \"Capture\",\n                            PW_KEY_MEDIA_ROLE, \"Screen\",\n                            nullptr);\n\n  stream = pw_stream_new(core, \"w0vncserver\", props);\n  if (!stream)\n    throw std::runtime_error(\"Failed to create PipeWire stream\");\n\n  pw_stream_add_listener(stream, &streamListener, &streamEventsHandler, this);\n\n  // FIXME: This is a bit ugly\n  spa_rectangle defaultVideoSize{1280,720};\n  spa_rectangle minVideoSize{1,1};\n  spa_rectangle maxVideoSize{4096,4096};\n  spa_fraction defaultFramerate{25,1};\n  spa_fraction minFramerate{0,1};\n  spa_fraction maxFramerate{60,1};\n\n  params[0] = (spa_pod *)spa_pod_builder_add_object(\n    &builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,\n    SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video),\n    SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),\n    SPA_FORMAT_VIDEO_format, SPA_POD_CHOICE_ENUM_Id(2, SPA_VIDEO_FORMAT_RGBx,\n                                                       SPA_VIDEO_FORMAT_BGRx),\n    SPA_FORMAT_VIDEO_size,\n    SPA_POD_CHOICE_RANGE_Rectangle(&defaultVideoSize, &minVideoSize,\n                                   &maxVideoSize),\n    SPA_FORMAT_VIDEO_framerate,\n    SPA_POD_CHOICE_RANGE_Fraction(&defaultFramerate, &minFramerate,\n                                  &maxFramerate));\n\n  if (pw_stream_connect(stream, PW_DIRECTION_INPUT, nodeId,\n                        (pw_stream_flags)(PW_STREAM_FLAG_AUTOCONNECT |\n                        PW_STREAM_FLAG_MAP_BUFFERS),\n                        params, 1) < 0) {\n    throw std::runtime_error(\"Failed to connect PipeWire stream\");\n  }\n}\n\nvoid PipeWireStream::handleStreamStateChanged(enum pw_stream_state old,\n                                              enum pw_stream_state state,\n                                              const char* error)\n{\n  if (!active)\n    return;\n\n  switch (state) {\n  case PW_STREAM_STATE_UNCONNECTED:\n    vlog.debug(\"PipeWire stream disconnected\");\n    break;\n  case PW_STREAM_STATE_PAUSED:\n    // This can happen if the compositor shuts down the session, e.g.\n    // a user logs out.\n    if (old == PW_STREAM_STATE_STREAMING)\n      stopped();\n    break;\n  case PW_STREAM_STATE_ERROR:\n    vlog.error(\"PipeWire stream error: %s\", error);\n    stopped();\n    return;\n  default:\n    vlog.debug(\"Unhandled stream state: %d\", state);\n    break;\n  }\n}\n\nvoid PipeWireStream::handleStreamParamChanged(uint32_t id,\n                                              const spa_pod *param)\n{\n  uint8_t paramsBuffer[1024];\n  spa_pod_builder builder;\n  int nParams;\n  const spa_pod *params[5];\n  int32_t mult;\n  spa_video_info spaFormat;\n  spa_rectangle fbSize;\n  int32_t fbStride;\n  rfb::PixelFormat pf;\n\n  if (!active)\n    return;\n\n  if (param == nullptr || id != SPA_PARAM_Format) {\n    vlog.debug(\"clear format\");\n    return;\n  }\n\n  if (spa_format_parse(param, &spaFormat.media_type,\n                       &spaFormat.media_subtype) < 0)\n    return;\n\n  if (spaFormat.media_type != SPA_MEDIA_TYPE_video)\n    return;\n\n  spa_pod_builder_init(&builder, paramsBuffer, sizeof(paramsBuffer));\n\n#ifdef _DEBUG\n  spa_debug_format(2, nullptr, param);\n#endif\n\n  switch (spaFormat.media_subtype) {\n  case SPA_MEDIA_SUBTYPE_raw:\n    spa_format_video_raw_parse(param, &spaFormat.info.raw);\n    fbSize = SPA_RECTANGLE(spaFormat.info.raw.size.width,\n                         spaFormat.info.raw.size.height);\n\n    try {\n      pf = convertPixelformat(spaFormat.info.raw.format);\n    } catch (std::runtime_error& e) {\n      pw_stream_set_error(stream, -EINVAL, \"%s\", e.what());\n      return;\n    }\n\n    mult = pf.bpp / 8;\n    fbStride = spaFormat.info.raw.size.width * mult;\n    break;\n  case SPA_VIDEO_FORMAT_UNKNOWN:\n    pw_stream_set_error(stream, -EINVAL, \"unknown pixel format\");\n    return;\n  default:\n    pw_stream_set_error(stream, -EINVAL, \"unsupported pixel format\");\n    return;\n  }\n\n  if (!fbSize.width || !fbSize.height) {\n    pw_stream_set_error(stream, -EINVAL, \"invalid framebuffer size: %dx%d\",\n                                          fbSize.width, fbSize.height);\n    return;\n  }\n\n  setParameters(fbSize.width, fbSize.height, pf);\n\n  nParams = 0;\n\n  params[nParams++] = (spa_pod*)spa_pod_builder_add_object(&builder,\n    SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,\n    SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(4, 2, 8),\n    SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1),\n    SPA_PARAM_BUFFERS_size, SPA_POD_Int(fbSize.width * fbSize.height * mult),\n    SPA_PARAM_BUFFERS_stride, SPA_POD_Int(fbStride),\n    SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int((1 << SPA_DATA_MemFd)));\n\n  params[nParams++] = (spa_pod*)spa_pod_builder_add_object(&builder,\n    SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,\n    SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),\n    SPA_PARAM_META_size, SPA_POD_Int(sizeof(spa_meta_header)));\n\n  params[nParams++] = (spa_pod*)spa_pod_builder_add_object(&builder,\n    SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type,\n    SPA_POD_Id(SPA_META_VideoDamage), SPA_PARAM_META_size,\n    SPA_POD_CHOICE_RANGE_Int(sizeof(struct spa_meta_region) * 16,\n                            sizeof(struct spa_meta_region) * 1,\n                            sizeof(struct spa_meta_region) * 16));\n\n  #define CURSOR_META_SIZE(w, h)                                       \\\n    (sizeof(struct spa_meta_cursor) + sizeof(struct spa_meta_bitmap) + \\\n            w * h * 4)\n\n  params[nParams++] = (spa_pod*)spa_pod_builder_add_object(&builder,\n    SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,\n    SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Cursor),\n    SPA_PARAM_META_size, SPA_POD_CHOICE_RANGE_Int(\n                             CURSOR_META_SIZE(64, 64),\n                             CURSOR_META_SIZE(1, 1),\n                             CURSOR_META_SIZE(512, 512)));\n\n  pw_stream_update_params(stream, params, nParams);\n}\n\nvoid PipeWireStream::handleProcess()\n{\n  pw_buffer* buffer;\n  spa_meta_header* header;\n\n  if (!active)\n    return;\n\n  buffer = pw_stream_dequeue_buffer(stream);\n\n  if (!buffer)\n    return;\n\n  header = (spa_meta_header*)spa_buffer_find_meta_data(buffer->buffer,\n                                                       SPA_META_Header,\n                                                       sizeof(*header));\n\n  // Frame is corrupted and does not contain any valid data\n  if (header && header->flags & SPA_META_HEADER_FLAG_CORRUPTED) {\n    vlog.debug(\"Skipping corrupted frame\");\n    pw_stream_queue_buffer(stream, buffer);\n    return;\n  }\n\n  processBuffer(buffer);\n\n  pw_stream_queue_buffer(stream, buffer);\n}\n\nvoid PipeWireStream::stopped()\n{\n  active = false;\n}\n\nrfb::PixelFormat PipeWireStream::convertPixelformat(int spaFormat)\n{\n  switch (spaFormat) {\n  case SPA_VIDEO_FORMAT_BGRx:\n  case SPA_VIDEO_FORMAT_BGRA:\n    return rfb::PixelFormat(32, 24, true, true, 255, 255, 255,\n                            8, 16, 24);\n  case SPA_VIDEO_FORMAT_RGBx:\n  case SPA_VIDEO_FORMAT_RGBA:\n    return rfb::PixelFormat(32, 24, true, true, 255, 255, 255,\n                            24, 16, 8);\n  case SPA_VIDEO_FORMAT_xBGR:\n  case SPA_VIDEO_FORMAT_ABGR:\n    return rfb::PixelFormat(32, 24, true, true, 255, 255, 255,\n                            0, 8, 16);\n  case SPA_VIDEO_FORMAT_xRGB:\n  case SPA_VIDEO_FORMAT_ARGB:\n    return rfb::PixelFormat(32, 24, true, true, 255, 255, 255,\n                            16, 8, 0);\n  case SPA_VIDEO_FORMAT_RGB:\n    return rfb::PixelFormat(24, 24, true, true, 255, 255, 255,\n                            16, 8, 0);\n  case SPA_VIDEO_FORMAT_BGR:\n    return rfb::PixelFormat(24, 24, true, true, 255, 255, 255,\n                            0, 8, 16);\n  default:\n    throw std::runtime_error(core::format(\"format %d not supported\",\n                                          spaFormat));\n  }\n}\n"
  },
  {
    "path": "unix/w0vncserver/pipewire/PipeWireStream.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __PIPEWIRE_STREAM_H__\n#define __PIPEWIRE_STREAM_H__\n\n#include <stdint.h>\n\n#include <pipewire/stream.h>\n\nnamespace rfb { class PixelFormat; }\n\nclass PipeWireSource;\n\nclass PipeWireStream {\npublic:\n  PipeWireStream(int pipeWireFd, int nodeId);\n  virtual ~PipeWireStream();\n\nprotected:\n  virtual void stopped();\n\nprivate:\n  void start(int nodeId);\n\n  void handleStreamStateChanged(enum pw_stream_state old,\n                                enum pw_stream_state state,\n                                const char* error);\n  void handleStreamParamChanged(uint32_t id, const spa_pod* param);\n  void handleProcess();\n\n  virtual void setParameters(int width, int height, rfb::PixelFormat pf) = 0;\n  virtual void processBuffer(pw_buffer* buffer) = 0;\n\n  rfb::PixelFormat convertPixelformat(int spaFormat);\n\nprivate:\n  int pipeWireFd;\n  bool active;\n\n  PipeWireSource* source;\n  pw_core* core;\n  pw_context* context;\n  pw_stream* stream;\n  spa_hook streamListener;\n  static const pw_stream_events streamEventsHandler;\n};\n\n#endif //__PIPEWIRE_STREAM_H__\n"
  },
  {
    "path": "unix/w0vncserver/portals/Clipboard.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#include <assert.h>\n#include <sys/stat.h>\n\n#include <gio/gio.h>\n#include <gio/gunixfdlist.h>\n#include <gio-unix-2.0/gio/gunixinputstream.h>\n#include <glib-object.h>\n#include <glib.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include \"../w0vncserver.h\"\n#include \"PortalProxy.h\"\n#include \"Clipboard.h\"\n\nstatic core::LogWriter vlog(\"Clipboard\");\n\nstatic const char* MIME_TEXT_PLAIN = \"text/plain\";\nstatic const char* MIME_TEXT_PLAIN_UTF8 = \"text/plain;charset=utf-8\";\n\nstatic const char* MIME_TYPES[] {\n  MIME_TEXT_PLAIN_UTF8,\n  MIME_TEXT_PLAIN,\n};\n\nstruct PendingData {\n  uint32_t serial;\n  std::string mimeType;\n};\n\nClipboard::Clipboard(std::string sessionHandle_,\n                     std::function<void(const char* data)>\n                       sendClipboardDataCb_,\n                     std::function<void(bool available)>\n                        clipboardAnnounceCb_,\n                     std::function<void()> clipboardRequestCb_)\n  : clipboard(nullptr), sessionHandle(sessionHandle_),\n    selectionOwner(true), readInProgress(false),\n    pendingReadMimeType(nullptr), readStream(nullptr),\n    readCancellable(nullptr),\n    sendClipboardDataCb(sendClipboardDataCb_),\n    clipboardAnnounceCb(clipboardAnnounceCb_),\n    clipboardRequestCb(clipboardRequestCb_)\n{\n  assert(available());\n\n  clipboard = new PortalProxy(\"org.freedesktop.portal.Desktop\",\n                              \"/org/freedesktop/portal/desktop\",\n                              \"org.freedesktop.portal.Clipboard\");\n}\n\nClipboard::~Clipboard()\n{\n  if (clipboard)\n    clearPendingSerials();\n\n  delete clipboard;\n\n  if (readStream)\n    g_object_unref(readStream);\n  // FIXME: Do we cancel a pending read here?\n  if (readCancellable)\n    g_object_unref(readCancellable);\n}\n\nbool Clipboard::available()\n{\n  return PortalProxy::interfacesAvailable({\"org.freedesktop.portal.Clipboard\"});\n}\n\nvoid Clipboard::subscribe()\n{\n  clipboard->subscribe(\"SelectionTransfer\",\n                       std::bind(&Clipboard::handleSelectionTransfer,\n                                 this, std::placeholders::_1));\n  clipboard->subscribe(\"SelectionOwnerChanged\",\n                       std::bind(&Clipboard::handleSelectionOwnerChanged,\n                                 this, std::placeholders::_1));\n}\n\nvoid Clipboard::selectionWrite(const char* data)\n{\n  while (!pendingSerials.empty()) {\n    PendingData pending;\n\n    pending = pendingSerials.front();\n    pendingSerials.pop();\n    selectionWrite(pending, data);\n  }\n}\n\nvoid Clipboard::requestClipboard()\n{\n  GVariant* params;\n  GVariantBuilder optionsBuilder;\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT);\n  params = g_variant_new(\"(oa{sv})\", sessionHandle.c_str(), &optionsBuilder);\n\n  clipboard->call(\"RequestClipboard\", params);\n}\n\nvoid Clipboard::setSelection()\n{\n  GVariantBuilder optionsBuilder;\n  GVariant* params;\n  GVariant* mimeTypes;\n\n  mimeTypes = g_variant_new_strv(MIME_TYPES, sizeof(MIME_TYPES) /\n                                             sizeof(MIME_TYPES[0]));\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT);\n  g_variant_builder_add(&optionsBuilder, \"{sv}\", \"mime_types\", mimeTypes);\n  params = g_variant_new(\"(oa{sv})\", sessionHandle.c_str(),\n                         &optionsBuilder);\n\n  try  {\n    clipboard->call(\"SetSelection\", params);\n  } catch (std::exception& e) {\n    vlog.error(\"Could not set selection: %s\", e.what());\n  }\n}\n\nvoid Clipboard::selectionWrite(PendingData pendingData, const char* data)\n{\n  GError* error = nullptr;\n  GUnixFDList* fdList = nullptr;\n  GVariant* params;\n  GVariant* response;\n  int32_t fdIndex;\n  int fd;\n  size_t remaining;\n  ssize_t written;\n  const char* buf;\n  std::string ascii;\n  uint32_t serial;\n  const char* mimeType;\n\n  serial = pendingData.serial;\n  mimeType = pendingData.mimeType.c_str();\n\n  params = g_variant_new(\"(ou)\", sessionHandle.c_str(), serial);\n\n  response = g_dbus_proxy_call_with_unix_fd_list_sync(\n               clipboard->getProxy(), \"SelectionWrite\", params,\n               G_DBUS_CALL_FLAGS_NONE, 3000, nullptr, &fdList, nullptr,\n               &error);\n\n  if (error) {\n    vlog.error(\"Error writing to clipboard: %s\", error->message);\n    g_variant_unref(response);\n    g_error_free(error);\n    selectionWriteDone(serial, false);\n    return;\n  }\n\n  g_variant_get(response, \"(h)\", &fdIndex);\n  g_variant_unref(response);\n\n  // FIXME: Can we always assume index 0?\n  fd = g_unix_fd_list_get(fdList, 0, &error);\n  if (error) {\n    g_object_unref(fdList);\n    vlog.error(\"Error writing to clipboard: %s\", error->message);\n    g_error_free(error);\n    selectionWriteDone(serial, false);\n    return;\n  }\n\n  if (strcmp(mimeType, MIME_TEXT_PLAIN) == 0) {\n    ascii = core::utf8ToAscii(data, strlen(data));\n    buf = ascii.c_str();\n    remaining = ascii.size();\n  } else if (strcmp(mimeType, MIME_TEXT_PLAIN_UTF8) == 0) {\n    buf = data;\n    remaining = strlen(data);\n  } else {\n    vlog.error(\"Error writing to clipboard: unsupported mime type: '%s'\", mimeType);\n    selectionWriteDone(serial, false);\n    return;\n  }\n\n  while (remaining > 0) {\n    written = write(fd, buf, remaining);\n\n    if (written < 0) {\n      vlog.error(\"Error writing to clipboard: %s\", strerror(errno));\n      selectionWriteDone(serial, false);\n      g_object_unref(fdList);\n      close(fd);\n      return;\n    }\n\n    remaining -= written;\n    buf += written;\n  }\n\n  if (close(fd) != 0) {\n    vlog.error(\"Error writing to clipboard: %s\", strerror(errno));\n    selectionWriteDone(serial, false);\n  } else {\n    selectionWriteDone(serial, true);\n  }\n\n  g_object_unref(fdList);\n}\n\nvoid Clipboard::clearSelection()\n{\n  GVariantBuilder optionsBuilder;\n  GVariant* params;\n\n  // Not sending 'mime_types' should make us no longer own the clipboard\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT);\n  params = g_variant_new(\"(oa{sv})\", sessionHandle.c_str(),\n                         &optionsBuilder);\n\n  try {\n    clipboard->call(\"SetSelection\", params);\n  } catch (std::exception& e) {\n    vlog.error(\"Could not remove clipboard ownership: %s\", e.what());\n  }\n\n  clearPendingSerials();\n  availableMimeTypes.clear();\n}\n\nvoid Clipboard::selectionWriteDone(uint32_t serial, bool success)\n{\n  GError* error = nullptr;\n  GVariant* params;\n  GVariant* result;\n\n  params = g_variant_new(\"(oub)\", sessionHandle.c_str(),\n                         serial, success);\n\n  result = g_dbus_proxy_call_sync(clipboard->getProxy(),\n                                  \"SelectionWriteDone\", params,\n                                  G_DBUS_CALL_FLAGS_NONE, 3000,\n                                  nullptr, &error);\n  if (error) {\n    vlog.error(\"Error writing to clipboard: %s\", error->message);\n    g_error_free(error);\n    return;\n  }\n\n  g_variant_unref(result);\n}\n\nvoid Clipboard::selectionRead()\n{\n  GError* error = nullptr;\n  GUnixFDList* fdList = nullptr;\n  GVariant* response;\n  int32_t fdIndex;\n  int fd;\n  GVariant* params;\n  const char* mimeType;\n\n  if (selectionOwner)\n    return;\n\n  if (readInProgress) {\n    // FIXME: Do we cancel our current read and read again?\n    return;\n  }\n\n  mimeType = nullptr;\n  for (uint i = 0; i < sizeof(MIME_TYPES) / sizeof(MIME_TYPES[0]); i++) {\n    if (availableMimeTypes.find(MIME_TYPES[i]) != availableMimeTypes.end()) {\n      mimeType = MIME_TYPES[i];\n      break;\n    }\n  }\n\n  if (!mimeType)\n    return;\n\n  assert(!selectionOwner);\n  assert(!readInProgress);\n  readInProgress = true;\n  pendingReadMimeType = mimeType;\n\n  params = g_variant_new(\"(os)\", sessionHandle.c_str(), mimeType);\n\n  response = g_dbus_proxy_call_with_unix_fd_list_sync(\n      clipboard->getProxy(), \"SelectionRead\", params,\n      G_DBUS_CALL_FLAGS_NONE, 3000, nullptr, &fdList, nullptr, &error);\n\n  if (error) {\n    vlog.error(\"Could not read clipboard: %s\", error->message);\n    g_error_free(error);\n    readInProgress = false;\n    return;\n  }\n\n  if (!g_variant_is_of_type(response, G_VARIANT_TYPE(\"(h)\"))) {\n    g_variant_unref(response);\n    g_object_unref(fdList);\n    vlog.error(\"Could not read clipboard: invalid response type: %s, \"\n               \"expected (h)\", g_variant_get_type_string(response));\n    readInProgress = false;\n    return;\n  }\n\n  g_variant_get(response, \"(h)\", &fdIndex);\n  g_variant_unref(response);\n\n  fd = g_unix_fd_list_get(fdList, fdIndex, &error);\n  g_object_unref(fdList);\n\n  if (error || fd == -1) {\n    readInProgress = false;\n    vlog.error(\"Could not read clipboard: %s\", error->message);\n    g_error_free(error);\n    return;\n  }\n\n  readCancellable = g_cancellable_new();\n  readStream = g_unix_input_stream_new(fd, true);\n  readBuffer.clear();\n\n  g_input_stream_read_bytes_async(\n    readStream,\n    4096,\n    G_PRIORITY_DEFAULT,\n    readCancellable,\n    [](GObject*, GAsyncResult* result, void* userData) {\n      ((Clipboard*)userData)->handleReadDataCallback(result);\n    },\n    this);\n}\n\nvoid Clipboard::handleSelectionTransfer(GVariant* parameters)\n{\n  uint32_t serial;\n  char* sessionHandle_; // ignored\n  char* mimeType;\n  bool validMimeType;\n\n  g_variant_get(parameters, \"(osu)\", &sessionHandle_, &mimeType, &serial);\n\n  free(sessionHandle_);\n\n  validMimeType = false;\n  for (uint i = 0; i < sizeof(MIME_TYPES) / sizeof(MIME_TYPES[0]); i++) {\n    if (strcmp(mimeType, MIME_TYPES[i]) == 0) {\n      validMimeType = true;\n      break;\n    }\n  }\n\n  if (!validMimeType) {\n    vlog.error(\"Unsupported mime type: %s - ignoring\", mimeType);\n    selectionWriteDone(serial, false);\n    free(mimeType);\n    return;\n  }\n\n\n  pendingSerials.push({serial, mimeType});\n  clipboardRequestCb();\n\n  free(mimeType);\n}\n\nvoid Clipboard::handleSelectionOwnerChanged(GVariant* parameters)\n{\n  GVariant* sessionHandle_; // ignored\n  GVariant* options;\n  GVariant* mimeTypes;\n  GVariant* sessionIsOwner;\n  char** mimeTypeArray;\n  bool wrappedMimeTypes;\n\n  g_variant_get(parameters, \"(@o@a{sv})\", &sessionHandle_, &options);\n\n  g_variant_unref(sessionHandle_);\n\n  mimeTypes = g_variant_lookup_value(options, \"mime_types\", nullptr);\n  sessionIsOwner = g_variant_lookup_value(options, \"session_is_owner\",\n                                          G_VARIANT_TYPE_BOOLEAN);\n  g_variant_unref(options);\n\n  if (!sessionIsOwner) {\n    readInProgress = false;\n    availableMimeTypes.clear();\n    clipboardAnnounceCb(false);\n    clearPendingSerials();\n\n    if (mimeTypes)\n      g_variant_unref(mimeTypes);\n\n    return;\n  }\n\n  selectionOwner = g_variant_get_boolean(sessionIsOwner);\n  g_variant_unref(sessionIsOwner);\n\n  if (selectionOwner) {\n    availableMimeTypes.clear();\n    clipboardAnnounceCb(false);\n    clearPendingSerials();\n\n    if (mimeTypes)\n      g_variant_unref(mimeTypes);\n\n    return;\n  }\n\n  if (!mimeTypes) {\n    availableMimeTypes.clear();\n    clipboardAnnounceCb(false);\n    clearPendingSerials();\n    return;\n  }\n\n  // The specification says that mime_types is of type \"as\", but GNOME\n  // incorrectly uses \"(as)\", so we have to double check here.\n  // https://gitlab.gnome.org/GNOME/xdg-desktop-portal-gnome/-/issues/136\n  if (g_variant_is_of_type(mimeTypes, G_VARIANT_TYPE(\"as\"))) {\n    wrappedMimeTypes = false;\n  } else if (g_variant_is_of_type(mimeTypes, G_VARIANT_TYPE(\"(as)\"))) {\n    wrappedMimeTypes = true;\n  } else {\n    char* mimeTypeString;\n\n    mimeTypeString = g_variant_print(mimeTypes, true);\n    vlog.error(\"Invalid mime types variant: %s\", mimeTypeString);\n    free(mimeTypeString);\n    g_variant_unref(mimeTypes);\n    clipboardAnnounceCb(false);\n    clearPendingSerials();\n    return;\n  }\n\n  g_variant_get(mimeTypes, wrappedMimeTypes ?  \"(^as)\" : \"^as\", &mimeTypeArray);\n\n  for (int i = 0; mimeTypeArray[i] != nullptr; i++) {\n    for (uint j = 0; j < sizeof(MIME_TYPES) / sizeof(MIME_TYPES[0]); j++) {\n      if (strcmp(mimeTypeArray[i], MIME_TYPES[j]) == 0) {\n        availableMimeTypes.insert(mimeTypeArray[i]);\n      }\n    }\n  }\n\n  clipboardAnnounceCb(true);\n  g_strfreev(mimeTypeArray);\n  g_variant_unref(mimeTypes);\n}\n\nvoid Clipboard::handleReadDataCallback(GAsyncResult* res)\n{\n  GError* error = nullptr;\n  GBytes* bytes;\n  size_t bytesRead;\n  size_t dataSize;\n  const char* data;\n\n  bytes = g_input_stream_read_bytes_finish(readStream, res, &error);\n\n  if (error) {\n    if (error->code == G_IO_ERROR_CANCELLED)\n      vlog.error(\"Cancelled reading clipboard data\");\n    else\n      vlog.error(\"Could not read clipboard data: %s\", error->message);\n\n    g_error_free(error);\n    g_object_unref(readStream);\n    g_object_unref(readCancellable);\n    readStream = nullptr;\n    readCancellable = nullptr;\n    readInProgress = false;\n    return;\n  }\n\n  bytesRead = g_bytes_get_size(bytes);\n\n  // Zero is returned on EOF, we are finished reading\n  if (bytesRead == 0) {\n    g_object_unref(readStream);\n    g_object_unref(readCancellable);\n    readStream = nullptr;\n    readCancellable = nullptr;\n    readInProgress = false;\n    g_bytes_unref(bytes);\n\n    if (strcmp(pendingReadMimeType, MIME_TEXT_PLAIN) == 0) {\n      if (!core::isValidAscii(readBuffer.c_str(), readBuffer.size())) {\n        vlog.error(\"Invalid ASCII sequence in clipboard - ignoring\");\n        readBuffer.clear();\n        readInProgress = false;\n        return;\n      }\n    } else if (strcmp(pendingReadMimeType, MIME_TEXT_PLAIN_UTF8) == 0) {\n      if (!core::isValidUTF8(readBuffer.c_str(), readBuffer.size())) {\n        vlog.error(\"Invalid UTF-8 sequence in clipboard - ignoring\");\n        readBuffer.clear();\n        readInProgress = false;\n        return;\n      }\n    }\n\n    sendClipboardDataCb(readBuffer.c_str());\n    readBuffer.clear();\n    return;\n  }\n\n  data = (const char*)g_bytes_get_data(bytes, &dataSize);\n\n  readBuffer.append(data, dataSize);\n  g_bytes_unref(bytes);\n\n  // While bytesRead > 0, continue reading until we reach EOF\n  g_input_stream_read_bytes_async(\n    readStream, 4096, G_PRIORITY_DEFAULT, readCancellable,\n    [](GObject*, GAsyncResult* result, void* userData) {\n      ((Clipboard*)userData)->handleReadDataCallback(result);\n    }, this);\n}\n\nvoid Clipboard::clearPendingSerials()\n{\n  assert(clipboard);\n\n  while (!pendingSerials.empty()) {\n    PendingData pending;\n\n    pending = pendingSerials.front();\n    pendingSerials.pop();\n    selectionWriteDone(pending.serial, false);\n  }\n}\n"
  },
  {
    "path": "unix/w0vncserver/portals/Clipboard.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __PORTAL_CLIPBOARD_H__\n#define __PORTAL_CLIPBOARD_H__\n\n#include <stdint.h>\n\n#include <string>\n#include <set>\n#include <queue>\n#include <functional>\n\n#include <gio/gio.h>\n\nstruct PendingData;\nclass PortalProxy;\n\nclass Clipboard {\npublic:\n  Clipboard(std::string sessionHandle,\n            std::function<void(const char* data)> sendClipboardDataCb,\n            std::function<void(bool available)> clipboardAnnounceCb,\n            std::function<void()> clipboardRequestCb);\n  ~Clipboard();\n\n  static bool available();\n\n  // Subscribe to the SelctionOwnerChanged and SelectionTransfer signals.\n  // Must be called once for setSelection() and selectionRead() to work.\n  void subscribe();\n\n  // Portal methods\n  void requestClipboard();\n  void setSelection();\n  void selectionRead();\n  // Called from rfb::SDesktop, writes to all pending requests\n  void selectionWrite(const char* data);\n\n  // Resets the clipboard when data is no longer avaialble.\n  void clearSelection();\n\nprivate:\n  // Portal methods\n  void selectionWrite(PendingData pendingData, const char* data);\n  void selectionWriteDone(uint32_t serial, bool success);\n\n  // Portal method callbacks\n  void handleRequestClipboard(GVariant *parameters);\n  void handleSelectionWrite(GObject* proxy, GAsyncResult* res);\n  void handleSelectionRead(GObject* proxy, GAsyncResult* res);\n\n  // Portal signals\n  void handleSelectionTransfer(GVariant* parameters);\n  void handleSelectionOwnerChanged(GVariant* parameters);\n\n  // Asynchronously reads the clipboard data. This will send the\n  // clipboard data to the client when it has finished reading.\n  void handleReadDataCallback(GAsyncResult* res);\n\n  void clearPendingSerials();\n\nprivate:\n  PortalProxy* clipboard;\n  std::string sessionHandle;\n  gboolean selectionOwner;\n  bool readInProgress;\n\n  const char* pendingReadMimeType;\n  GInputStream* readStream;\n  GCancellable* readCancellable;\n  std::string readBuffer;\n\n  std::set<std::string> availableMimeTypes;\n  std::queue<PendingData> pendingSerials;\n  std::function<void(const char* data)> sendClipboardDataCb;\n  std::function<void(bool available)> clipboardAnnounceCb;\n  std::function<void()> clipboardRequestCb;\n};\n\n#endif // __PORTAL_CLIPBOARD_H__\n"
  },
  {
    "path": "unix/w0vncserver/portals/PortalDesktop.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <gio/gio.h>\n\n#include <rfb/ScreenSet.h>\n#include <rfb/VNCServerST.h>\n#include <core/LogWriter.h>\n#include <core/xdgdirs.h>\n#include <core/string.h>\n\n#include \"../w0vncserver.h\"\n#include \"../parameters.h\"\n#include \"RemoteDesktop.h\"\n#include \"Clipboard.h\"\n#include \"PortalProxy.h\"\n#include \"../pipewire/PipeWirePixelBuffer.h\"\n#include \"PortalDesktop.h\"\n\nextern const unsigned short code_map_qnum_to_xorgevdev[];\nextern const unsigned int code_map_qnum_to_xorgevdev_len;\n\nstatic core::LogWriter vlog(\"PortalDesktop\");\n\nPortalDesktop::PortalDesktop()\n  : server(nullptr), remoteDesktop(nullptr), clipboard(nullptr),\n    pb(nullptr), restoreToken(\"\"), clipboardAccess(false)\n{\n}\n\nPortalDesktop::~PortalDesktop()\n{\n  delete remoteDesktop;\n  delete clipboard;\n}\n\nvoid PortalDesktop::init(rfb::VNCServer* vs)\n{\n  server = vs;\n}\n\nvoid PortalDesktop::start()\n{\n  assert(!remoteDesktop);\n\n  std::function<void(int, uint32_t)> startPipewire = [this](int fd, uint32_t id) {\n    try {\n      pb = new PipeWirePixelBuffer(fd, id, server);\n    } catch (std::exception& e) {\n      server->closeClients(core::format(\"error initializing PipeWirePixelBuffer: %s\",\n                                        e.what()).c_str());\n    }\n  };\n\n  // FIXME: If the session startup is canceled (e.g. the local user\n  // denies the connection), we need to close the connections to all\n  // clients. This is not the cleanest solution, but it will do for now.\n  std::function<void(const char*)> cancelStart = [this](const char* reason) {\n    server->closeClients(reason);\n  };\n\n  std::function<void(const char*)> sendClipboardData = [this](const char* data) {\n    server->sendClipboardData(data);\n  };\n\n  std::function<void(bool available)> clipboardAnnounceCb = [this](bool available) {\n    server->announceClipboard(available);\n  };\n\n  std::function<void()> clipboardRequestCb = [this]() {\n    server->requestClipboard();\n  };\n\n  std::function<void()> initClipboard = [this, sendClipboardData,\n                                         clipboardAnnounceCb,\n                                         clipboardRequestCb]() {\n    assert(remoteDesktop);\n\n    clipboard = new Clipboard(remoteDesktop->getSessionHandle(),\n                              sendClipboardData, clipboardAnnounceCb,\n                              clipboardRequestCb);\n    clipboardAccess = true;\n\n    try {\n      clipboard->requestClipboard();\n    } catch (std::exception& e) {\n      vlog.error(\"Could not get clipboard access\");\n      clipboardAccess = false;\n    }\n  };\n\n  std::function<void()> clipboardSubscribe = [this]() {\n    assert(clipboard);\n\n    clipboard->subscribe();\n  };\n\n  try {\n    remoteDesktop = new RemoteDesktop(restoreToken, startPipewire,\n                                      cancelStart, initClipboard,\n                                      clipboardSubscribe);\n  } catch (std::exception& e) {\n    vlog.error(\"error initializing RemoteDesktop: %s\", e.what());\n    server->closeClients(\"Failed to start remote desktop session\");\n    return;\n  }\n\n  remoteDesktop->createSession();\n}\n\nvoid PortalDesktop::stop()\n{\n  server->setPixelBuffer(nullptr);\n\n  delete pb;\n  pb = nullptr;\n\n  restoreToken = remoteDesktop->getRestoreToken();\n  delete remoteDesktop;\n  remoteDesktop = nullptr;\n\n  delete clipboard;\n  clipboard = nullptr;\n  clipboardAccess = false;\n}\n\nvoid PortalDesktop::queryConnection(network::Socket* sock,\n                                    const char* /* userName */)\n{\n  // FIXME: Implement this.\n  server->approveConnection(sock, false,\n                            \"Unable to query the local user to accept the connection.\");\n}\n\nvoid PortalDesktop::terminate()\n{\n  kill(getpid(), SIGTERM);\n}\n\nunsigned int PortalDesktop::setScreenLayout(int /* fb_width */,\n                                            int /* fb_height */,\n                                            const rfb::ScreenSet& /*  layout */)\n{\n  return rfb::resultProhibited;\n}\n\nvoid PortalDesktop::keyEvent(uint32_t keysym, uint32_t keycode, bool down)\n{\n  // FIXME: The RemoteDesktop API does currently not specify this, but\n  //        the keyboard methods expect evdev keycodes and\n  //        xkbcommon keysyms.\n  //        Using the Portals for input is not recommended. We should\n  //        switch over to using libei entirely instead.\n  if (rawKeyboard && (keycode < code_map_qnum_to_xorgevdev_len)) {\n    int evdevKeycode;\n    evdevKeycode = code_map_qnum_to_xorgevdev[keycode];\n    if (evdevKeycode) {\n      remoteDesktop->notifyKeyboardKeycode(evdevKeycode, down);\n      return;\n    }\n  }\n\n  remoteDesktop->notifyKeyboardKeysym(keysym, down);\n}\n\nvoid PortalDesktop::pointerEvent(const core::Point& pos,\n                            uint16_t buttonMask)\n{\n  remoteDesktop->notifyPointerMotionAbsolute(pos.x, pos.y, buttonMask);\n}\n\nvoid PortalDesktop::handleClipboardRequest()\n{\n  if (!remoteDesktop->getClipboardEnabled() || !clipboardAccess)\n    return;\n\n  assert(clipboard);\n\n  clipboard->selectionRead();\n}\n\nvoid PortalDesktop::handleClipboardAnnounce(bool available)\n{\n  if (!clipboard || !remoteDesktop->getClipboardEnabled() || !clipboardAccess)\n    return;\n\n  if (available)\n    clipboard->setSelection();\n  else\n    clipboard->clearSelection();\n}\n\nvoid PortalDesktop::handleClipboardData(const char* data)\n{\n  if (!clipboard || !remoteDesktop->getClipboardEnabled() || !clipboardAccess)\n    return;\n\n  clipboard->selectionWrite(data);\n}\nbool PortalDesktop::available()\n{\n  std::vector<std::string> interfaces = {\n    \"org.freedesktop.portal.RemoteDesktop\",\n    \"org.freedesktop.portal.ScreenCast\",\n  };\n\n  return PortalProxy::interfacesAvailable(interfaces);\n}\n"
  },
  {
    "path": "unix/w0vncserver/portals/PortalDesktop.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __PORTAL_DESKTOP_H__\n#define __PORTAL_DESKTOP_H__\n\n#include <glib.h>\n\n#include <string>\n\n#include <rfb/SDesktop.h>\n\nclass PipeWirePixelBuffer;\nclass Clipboard;\n\nnamespace rfb { class VNCServer; }\n\nclass RemoteDesktop;\n\nclass PortalDesktop : public rfb::SDesktop\n{\npublic:\n  PortalDesktop();\n  virtual ~PortalDesktop();\n\n  // -=- SDesktop interface\n  void init(rfb::VNCServer* vs) override;\n  void start() override;\n  void stop() override;\n  void queryConnection(network::Socket* sock,\n                       const char* userName) override;\n  void terminate() override;\n  unsigned int setScreenLayout(int fb_width, int fb_height,\n                               const rfb::ScreenSet& layout) override;\n  void keyEvent(uint32_t keysym, uint32_t keycode, bool down) override;\n  void pointerEvent(const core::Point& pos,\n                    uint16_t buttonMask) override;\n  void handleClipboardRequest() override;\n  void handleClipboardAnnounce(bool available) override;\n  void handleClipboardData(const char* data) override;\n\n  // Check if portals implementations are available\n  static bool available();\n\nprotected:\n  rfb::VNCServer* server;\n\n  RemoteDesktop* remoteDesktop;\n  Clipboard* clipboard;\n  PipeWirePixelBuffer* pb;\n\nprivate:\n  std::string restoreToken;\n  bool clipboardAccess;\n};\n\n#endif // __PORTAL_DESKTOP_H__\n"
  },
  {
    "path": "unix/w0vncserver/portals/PortalProxy.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <uuid/uuid.h>\n\n#include <algorithm>\n#include <stdexcept>\n\n#include <glib.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include \"../w0vncserver.h\"\n#include \"PortalProxy.h\"\n\nstatic core::LogWriter vlog(\"PortalProxy\");\n\nPortalProxy::PortalProxy(const char* name, const char* objectPath,\n                         const char* interfaceName)\n  : proxy(nullptr)\n{\n  GError* error = nullptr;\n\n  connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error);\n\n  if (error) {\n    std::string error_message(error->message);\n    g_error_free(error);\n    throw std::runtime_error(error_message);\n  }\n\n  proxy = g_dbus_proxy_new_sync(connection, G_DBUS_PROXY_FLAGS_NONE,\n                                nullptr, name, objectPath,\n                                interfaceName, nullptr, &error);\n\n  if (error) {\n    std::string error_message(error->message);\n    g_error_free(error);\n    throw std::runtime_error(error_message);\n  }\n}\n\nPortalProxy::~PortalProxy() {\n  if (proxy)\n    g_object_unref(proxy);\n\n  if (connection) {\n    for (uint32_t pendingCall : pendingCalls)\n      g_dbus_connection_signal_unsubscribe(connection, pendingCall);\n    for (uint32_t signalId : subscribedSignals)\n      g_dbus_connection_signal_unsubscribe(connection, signalId);\n\n    g_object_unref(connection);\n  }\n}\n\nvoid PortalProxy::call(const char* method, GVariant* parameters,\n                       const char* requestHandleToken,\n                       std::function<void(GVariant* parameters)> signalCallback,\n                       GDBusCallFlags flags)\n{\n  GError* error = nullptr;\n  GVariant* result;\n\n  struct PortalCall {\n    std::function<void(GVariant* parameters)> callback;\n    uint32_t signalId;\n    PortalProxy* parent;\n  };\n\n  if (signalCallback) {\n    assert(requestHandleToken);\n\n    std::string requestHandle;\n    requestHandle = newRequestHandle(requestHandleToken);\n\n    PortalCall* call;\n    call = new PortalCall{signalCallback, 0, this};\n\n    call->signalId = g_dbus_connection_signal_subscribe(\n                       connection,\n                       \"org.freedesktop.portal.Desktop\",\n                       \"org.freedesktop.portal.Request\",\n                       \"Response\", requestHandle.c_str(),\n                       nullptr, G_DBUS_SIGNAL_FLAGS_NONE,\n                       [](GDBusConnection*, const char*, const char*,\n                          const char*, const char*,\n                          GVariant *parameters_, void* userData) {\n                            PortalCall* call_ = (PortalCall*)userData;\n                            PortalProxy* self = call_->parent;\n\n                            g_dbus_connection_signal_unsubscribe(self->connection,\n                                                                 call_->signalId);\n                            self->pendingCalls.remove(call_->signalId);\n\n                            call_->callback(parameters_);\n                       },\n                       call, [](void* userData) {\n                         delete (PortalCall*)userData;\n                       });\n\n    pendingCalls.push_back(call->signalId);\n  }\n\n  result = g_dbus_proxy_call_sync(proxy, method, parameters,\n                                  flags, 3000, nullptr, &error);\n\n  if (result)\n    g_variant_unref(result);\n\n  if (error) {\n    std::string msg(error->message);\n    g_error_free(error);\n    throw std::runtime_error(msg);\n  }\n}\n\nvoid PortalProxy::subscribe(const char* member,\n                            std::function<void(GVariant* parameters)>\n                              signalCallback)\n{\n  struct Callback {\n    std::function<void(GVariant* parameters)> callback;\n  };\n\n  Callback* callback;\n  uint32_t signalId;\n\n  callback = new Callback;\n  callback->callback = signalCallback;\n\n  signalId = g_dbus_connection_signal_subscribe(\n               connection,\n               \"org.freedesktop.portal.Desktop\",\n               g_dbus_proxy_get_interface_name(proxy),\n               member, \"/org/freedesktop/portal/desktop\",\n               nullptr,\n               G_DBUS_SIGNAL_FLAGS_NONE,\n               [](GDBusConnection*, const char*, const char*,\n                 const char*, const char*,\n                 GVariant* parameters, void* userData) {\n                   ((Callback*)userData)->callback(parameters);\n               },\n               callback, [](void* userData) {\n                   delete (Callback*)userData;\n               });\n\n  subscribedSignals.push_back(signalId);\n}\n\nvoid PortalProxy::unsubscribe(uint32_t signalId)\n{\n  g_dbus_connection_signal_unsubscribe(connection, signalId);\n  subscribedSignals.remove(signalId);\n}\n\nstd::string PortalProxy::newToken()\n{\n  std::string token;\n  uuid_t uuid;\n  char uuidStr[37];\n\n  uuid_generate(uuid);\n  uuid_unparse(uuid, uuidStr);\n\n  // Valid DBus object paths may only contain\n  // the ASCII characters \"[A-Z][a-z][0-9]_\"\n  for (char* p = uuidStr; *p; ++p) {\n    if (*p == '-')\n      *p = '_';\n  }\n\n  token = uuidStr;\n\n  return token;\n}\n\nstd::string PortalProxy::newHandle()\n{\n  return core::format(\"w0vncserver_%s\", newToken().c_str());\n}\n\nbool PortalProxy::interfacesAvailable(std::vector<std::string> interfaces)\n{\n  GError* error = nullptr;\n  GDBusConnection* connection;\n  GVariant* result;\n  GDBusNodeInfo* nodeInfo;\n  GDBusInterfaceInfo* interfaceInfo;\n  const char* introspectionXml;\n  bool interfaceMissing;\n\n  connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error);\n\n  if (error) {\n    std::string error_message(error->message);\n    g_error_free(error);\n    throw std::runtime_error(error_message);\n  }\n\n  result = g_dbus_connection_call_sync(connection,\n                              \"org.freedesktop.portal.Desktop\",\n                              \"/org/freedesktop/portal/desktop\",\n                              \"org.freedesktop.DBus.Introspectable\",\n                              \"Introspect\",\n                              nullptr,\n                              G_VARIANT_TYPE(\"(s)\"),\n                              G_DBUS_CALL_FLAGS_NONE,\n                              3000,\n                              nullptr,\n                              &error);\n\n  if (error) {\n    std::string error_message(error->message);\n    g_error_free(error);\n    throw std::runtime_error(\"Introspect call failed: \" + error_message);\n  }\n\n  g_variant_get(result, \"(&s)\", &introspectionXml);\n\n  nodeInfo = g_dbus_node_info_new_for_xml(introspectionXml, &error);\n  g_variant_unref(result);\n\n  if (error) {\n    std::string error_message(error->message);\n    g_error_free(error);\n    throw std::runtime_error(error_message);\n  }\n\n  interfaceMissing = false;\n  for (std::string interface : interfaces) {\n    interfaceInfo = g_dbus_node_info_lookup_interface(nodeInfo,\n                                                      interface.c_str());\n    if (!interfaceInfo) {\n      vlog.debug(\"Interface '%s' not found\", interface.c_str());\n      interfaceMissing = true;\n    }\n  }\n\n  g_dbus_node_info_unref(nodeInfo);\n  g_object_unref(connection);\n\n  return !interfaceMissing;\n}\n\nstd::string PortalProxy::newRequestHandle(std::string token)\n{\n  std::string uniqueName;\n  std::string requestHandle;\n\n  uniqueName = g_dbus_connection_get_unique_name(connection);\n\n  /* https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Request.html#org-freedesktop-portal-request\n   * From the documentation: the caller's unique name should have its\n   * initial ':' removed, and all '.' replaced by '_'.\n   * e.g. :15759.1 -> 15759_1\n   */\n  uniqueName.erase(0,1);\n  std::replace(uniqueName.begin(), uniqueName.end(), '.', '_');\n\n  requestHandle = core::format(\"/org/freedesktop/portal/desktop/request/%s/%s\",\n                               uniqueName.c_str(), token.c_str());\n\n  return requestHandle;\n}\n"
  },
  {
    "path": "unix/w0vncserver/portals/PortalProxy.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __PORTAL_PROXY_H__\n#define __PORTAL_PROXY_H__\n\n#include <stdint.h>\n\n#include <functional>\n#include <string>\n#include <vector>\n#include <list>\n\n#include <gio/gio.h>\n\nclass PortalProxy {\npublic:\n  PortalProxy(const char* name, const char* objectPath,\n              const char* interfaceName);\n  ~PortalProxy();\n\n  // Call a DBUS method using the proxy. Will call\n  // signalCallback() when a response signal is received. A\n  // requestHandleToken must be set to link the response signal.\n  // signalCallback can be set to nullptr is no response is expected.\n  // Throws an exception if the call fails\n  void call(const char* method, GVariant* parameters,\n            const char* requestHandleToken = nullptr,\n            std::function<void(GVariant* parameters)>\n              signalCallback = nullptr,\n            GDBusCallFlags flags = G_DBUS_CALL_FLAGS_NONE);\n  // Subscribe to a DBUS signal. signalCallback() is run whenever\n  // the signal is emitted\n  void subscribe(const char* member,\n                 std::function<void(GVariant* parameters)>\n                   signalCallback);\n  // Unsubscribe from a DBUS signal\n  void unsubscribe(uint32_t signalId);\n\n  // Generates a unique request token\n  static std::string newToken();\n  // Generates a handle with a unique token\n  static std::string newHandle();\n\n  // Checks if interfaces are available\n  static bool interfacesAvailable(std::vector<std::string> interfaces);\n\n  GDBusProxy* getProxy() const { return proxy; }\n\nprivate:\n  // Generates a request handle from a token.\n  std::string newRequestHandle(std::string token);\n\nprivate:\n  GDBusConnection* connection;\n  GDBusProxy* proxy;\n  std::list<uint32_t> pendingCalls;\n  std::list<uint32_t> subscribedSignals;\n};\n\n#endif // __PORTAL_PROXY_H__\n"
  },
  {
    "path": "unix/w0vncserver/portals/RemoteDesktop.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdint.h>\n#include <stdio.h>\n#include <assert.h>\n#include <sys/select.h>\n#include <uuid/uuid.h>\n#include <linux/input-event-codes.h>\n\n#include <string>\n\n#include <glib.h>\n#include <gio/gunixfdlist.h>\n\n#include <core/Configuration.h>\n#include <core/LogWriter.h>\n#include <core/string.h>\n#include <core/xdgdirs.h>\n\n#include <rfb/KeysymStr.h>\n#include \"../w0vncserver.h\"\n#include \"portalConstants.h\"\n#include \"RemoteDesktop.h\"\n#include \"Clipboard.h\"\n#include \"PortalProxy.h\"\n\n// Maximum number of buttons\n#define BUTTONS 9\n\n// Scroll wheel events\n#define WHEEL_VERTICAL_DOWN    3\n#define WHEEL_VERTICAL_UP      4\n#define WHEEL_HORIZONTAL_LEFT  5\n#define WHEEL_HORIZONTAL_RIGHT 6\n\n// This feature is disabled by default as it doesn't work properly on\n// GNOME. https://gitlab.gnome.org/GNOME/mutter/-/issues/4135\ncore::BoolParameter\n  localCursor(\"experimentalLocalCursor\",\n              \"[EXPERIMENTAL] Render cursor locally\",\n              false);\n\ncore::EnumParameter\n  rememberDisplayChoice(\"RememberDisplayChoice\",\n                        \"Remember display choice when user connects (Always, Never, Session)\",\n                        {\"Always\", \"Never\", \"Session\"}, \"Session\");\n\n// Sync with w0vncserver-forget\nstatic const char* RESTORE_TOKEN_FILENAME =  \"restoretoken\";\n\nstatic core::LogWriter vlog(\"RemoteDesktop\");\n\nstatic int getInputCode(uint32_t button)\n{\n  switch (button) {\n  case 0x0:\n    return BTN_LEFT;\n  case 0x1:\n    return BTN_MIDDLE;\n  case 0x2:\n    return BTN_RIGHT;\n  case 0x7:\n    return BTN_SIDE;\n  case 0x8:\n    return BTN_EXTRA;\n  default:\n    assert(false);\n  }\n}\n\nRemoteDesktop::RemoteDesktop(std::string restoreToken_,\n                             std::function<void(int fd, uint32_t nodeId)>\n                               startPipewireCb_,\n                             std::function<void(const char*)>\n                               cancelStartCb_,\n                             std::function<void()> initClipboardCb_,\n                             std::function<void()> clipboardSubscribeCb_)\n  : sessionStarted(false), oldButtonMask(0), selectedDevices(0),\n    clipboardEnabled(false), sessionHandle(\"\"), remoteDesktop(nullptr),\n    screenCast(nullptr), session(nullptr), restoreToken(restoreToken_),\n    startPipewireCb(startPipewireCb_), cancelStartCb(cancelStartCb_),\n    initClipboardCb(initClipboardCb_),\n    clipboardSubscribeCb(clipboardSubscribeCb_)\n{\n  remoteDesktop = new PortalProxy(\"org.freedesktop.portal.Desktop\",\n                                  \"/org/freedesktop/portal/desktop\",\n                                  \"org.freedesktop.portal.RemoteDesktop\");\n  screenCast = new PortalProxy(\"org.freedesktop.portal.Desktop\",\n                               \"/org/freedesktop/portal/desktop\",\n                               \"org.freedesktop.portal.ScreenCast\");\n}\n\nRemoteDesktop::~RemoteDesktop()\n{\n  closeSession();\n  delete session;\n  delete screenCast;\n  delete remoteDesktop;\n}\n\nvoid RemoteDesktop::notifyKeyboardKeysym(uint32_t keysym, bool down)\n{\n  GVariantBuilder optionsBuilder;\n  GVariant* params;\n  uint32_t state;\n\n  if (!(selectedDevices & DEV_KEYBOARD))\n    return;\n\n  state = down ? 1 : 0;\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE(\"a{sv}\"));\n  params = g_variant_new(\"(oa{sv}iu)\", sessionHandle.c_str(),\n                         &optionsBuilder, keysym, state);\n  try {\n    remoteDesktop->call(\"NotifyKeyboardKeysym\", params);\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not handle keysym XK_%s (0x%04x): %s\",\n               KeySymName(keysym), keysym, e.what());\n  }\n}\n\nvoid RemoteDesktop::notifyKeyboardKeycode(uint32_t keycode, bool down)\n{\n  GVariantBuilder optionsBuilder;\n  GVariant* params;\n  uint32_t state;\n\n  if (!(selectedDevices & DEV_KEYBOARD))\n    return;\n\n  state = down ? 1 : 0;\n\n  // FIXME: We should probably verify that xkv_v1 is used, but it seems\n  // like most compositors (mutter/kwin etc.) use xkb_v1.\n  // The Wayland documentation states that:\n  //   \"clients must add 8 to the key event keycode\"\n  // when format xkb_v1 is used. Subtract 8 to get the correct keycode.\n  keycode -= 8;\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE(\"a{sv}\"));\n  params = g_variant_new(\"(oa{sv}iu)\", sessionHandle.c_str(),\n                         &optionsBuilder, keycode, state);\n  try {\n    remoteDesktop->call(\"NotifyKeyboardKeycode\", params);\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not handle key %d: %s\", keycode, e.what());\n  }\n}\n\nvoid RemoteDesktop::notifyPointerMotionAbsolute(int x, int y,\n                                                uint16_t buttonMask)\n{\n  GVariantBuilder optionsBuilder;\n  GVariant* params;\n\n  if (!(selectedDevices & DEV_POINTER))\n    return;\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE(\"a{sv}\"));\n  params = g_variant_new(\"(oa{sv}udd)\", sessionHandle.c_str(),\n                         &optionsBuilder, pipewireNodeId,\n                         (double)x,(double)y);\n\n  try {\n    remoteDesktop->call(\"NotifyPointerMotionAbsolute\", params);\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not move pointer: %s\", e.what());\n  }\n\n  if (buttonMask == oldButtonMask)\n    return;\n\n  for (int32_t i = 0; i < BUTTONS; i++) {\n    if ((buttonMask ^ oldButtonMask) & (1 << i)) {\n      if (i > 2 && i < 7)\n        notifyPointerAxisDiscrete(i);\n      else\n        notifyPointerButton(i, buttonMask & (1 << i));\n    }\n  }\n  oldButtonMask = buttonMask;\n}\n\nvoid RemoteDesktop::notifyPointerButton(int32_t button, bool down)\n{\n  GVariantBuilder optionsBuilder;\n  GVariant* params;\n\n  assert(selectedDevices & DEV_POINTER);\n\n  button = getInputCode(button);\n\n  g_variant_builder_init(&optionsBuilder,\n                         G_VARIANT_TYPE(\"a{sv}\"));\n  params = g_variant_new(\"(oa{sv}iu)\", sessionHandle.c_str(),\n                          &optionsBuilder, button, down);\n\n  try {\n    remoteDesktop->call(\"NotifyPointerButton\", params);\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not handle mouse button: %s\", e.what());\n  }\n}\n\nvoid RemoteDesktop::notifyPointerAxisDiscrete(int32_t button)\n{\n  GVariantBuilder optionsBuilder;\n  GVariant* params;\n  int32_t axis;\n  int steps;\n\n  assert(button > 2 && button < 7);\n  assert(selectedDevices & DEV_POINTER);\n\n  switch (button) {\n  case WHEEL_VERTICAL_DOWN:\n    axis = 0;\n    steps = -1;\n    break;\n  case WHEEL_VERTICAL_UP:\n    axis = 0;\n    steps = 1;\n    break;\n  case WHEEL_HORIZONTAL_LEFT:\n    axis = 1;\n    steps = -1;\n    break;\n  case WHEEL_HORIZONTAL_RIGHT:\n    axis = 1;\n    steps = 1;\n    break;\n  default:\n    assert(false);\n  }\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE(\"a{sv}\"));\n  params = g_variant_new(\"(oa{sv}ui)\", sessionHandle.c_str(),\n                         &optionsBuilder, axis, steps);\n\n  try {\n    remoteDesktop->call(\"NotifyPointerAxisDiscrete\", params);\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not handle mouse scroll: %s\", e.what());\n  }\n}\n\nvoid RemoteDesktop::createSession()\n{\n  std::string requestHandleToken;\n  std::string sessionHandleToken;\n  GVariantBuilder optionsBuilder;\n  GVariant* params;\n\n  requestHandleToken = remoteDesktop->newHandle();\n  sessionHandleToken = remoteDesktop->newHandle();\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE(\"a{sv}\"));\n  g_variant_builder_add(&optionsBuilder, \"{sv}\", \"handle_token\",\n                        g_variant_new_string(requestHandleToken.c_str()));\n  g_variant_builder_add(&optionsBuilder, \"{sv}\", \"session_handle_token\",\n                        g_variant_new_string(sessionHandleToken.c_str()));\n\n  params = g_variant_new(\"(a{sv})\", &optionsBuilder);\n\n  try {\n    remoteDesktop->call(\"CreateSession\", params,\n                        requestHandleToken.c_str(),\n                        std::bind(&RemoteDesktop::handleCreateSession,\n                                  this, std::placeholders::_1));\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not create session: %s\", e.what());\n    cancelStartCb(\"Failed to start remote desktop session\");\n  }\n}\n\nvoid RemoteDesktop::closeSession()\n{\n  if (session && sessionStarted) {\n    try {\n      session->call(\"Close\", nullptr, nullptr, nullptr);\n    } catch (const std::exception& e) {\n      // This is not necessarily unexpected, as the session can be\n      // closed by the compositor.\n      vlog.info(\"Could not close session: %s\", e.what());\n    }\n  }\n}\n\nvoid RemoteDesktop::selectDevices()\n{\n  std::string requestHandleToken;\n  GVariantBuilder optionsBuilder;\n  GVariant *params;\n\n  requestHandleToken = remoteDesktop->newHandle();\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT);\n  g_variant_builder_add(&optionsBuilder, \"{sv}\", \"types\",\n                        g_variant_new_uint32(DEV_KEYBOARD | DEV_POINTER));\n\n  if (rememberDisplayChoice != \"Never\") {\n    g_variant_builder_add(&optionsBuilder, \"{sv}\", \"persist_mode\",\n                          g_variant_new_uint32(PERSIST_UNTIL_REVOKED));\n  }\n\n  g_variant_builder_add(&optionsBuilder, \"{sv}\", \"handle_token\",\n                        g_variant_new_string(requestHandleToken.c_str()));\n\n  if (loadRestoreToken()) {\n    g_variant_builder_add(&optionsBuilder, \"{sv}\", \"restore_token\",\n                          g_variant_new_string(restoreToken.c_str()));\n  }\n\n  params = g_variant_new(\"(oa{sv})\", sessionHandle.c_str(), &optionsBuilder);\n\n  try {\n    remoteDesktop->call(\"SelectDevices\", params, requestHandleToken.c_str(),\n                        std::bind(&RemoteDesktop::handleSelectDevices,\n                        this, std::placeholders::_1));\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not select devices: %s\", e.what());\n    cancelStartCb(\"Failed to start remote desktop session\");\n  }\n}\n\nvoid RemoteDesktop::selectSources()\n{\n  GVariant* params;\n  GVariantBuilder optionsBuilder;\n  std::string requestHandleToken;\n  int cursorMode;\n\n  requestHandleToken = screenCast->newHandle();\n\n  cursorMode = localCursor ? CUR_METADATA : CUR_EMBEDDED;\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT);\n  g_variant_builder_add(&optionsBuilder, \"{sv}\", \"types\",\n                        g_variant_new_uint32(SRC_MONITOR));\n  g_variant_builder_add(&optionsBuilder, \"{sv}\", \"cursor_mode\",\n                        g_variant_new_uint32(cursorMode));\n  g_variant_builder_add(&optionsBuilder, \"{sv}\", \"multiple\",\n                        g_variant_new_boolean(false));\n\n  g_variant_builder_add(&optionsBuilder, \"{sv}\", \"handle_token\",\n                        g_variant_new_string(requestHandleToken.c_str()));\n\n  params = g_variant_new(\"(oa{sv})\", sessionHandle.c_str(),\n                         &optionsBuilder);\n\n  try {\n    screenCast->call(\"SelectSources\", params, requestHandleToken.c_str(),\n                     std::bind(&RemoteDesktop::handleSelectSources,\n                     this, std::placeholders::_1));\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not select sources: %s\", e.what());\n    cancelStartCb(\"Failed to start remote desktop session\");\n  }\n}\n\nvoid RemoteDesktop::start()\n{\n  std::string requestHandleToken;\n  GVariantBuilder optionsBuilder;\n  GVariant *params;\n\n  requestHandleToken = remoteDesktop->newHandle();\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT);\n  g_variant_builder_add(&optionsBuilder, \"{sv}\", \"handle_token\",\n                        g_variant_new_string(requestHandleToken.c_str()));\n\n  params = g_variant_new(\"(osa{sv})\", sessionHandle.c_str(), \"\",\n                         &optionsBuilder);\n  try {\n    remoteDesktop->call(\"Start\", params, requestHandleToken.c_str(),\n                        std::bind(&RemoteDesktop::handleStart,\n                        this, std::placeholders::_1));\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not start session: %s\", e.what());\n    cancelStartCb(\"Failed to start remote desktop session\");\n  }\n}\n\nvoid RemoteDesktop::openPipewireRemote()\n{\n  GVariantBuilder optionsBuilder;\n\n  g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT);\n\n  g_dbus_proxy_call_with_unix_fd_list(\n    screenCast->getProxy(),\n    \"OpenPipeWireRemote\",\n    g_variant_new(\"(oa{sv})\",\n    sessionHandle.c_str(),\n    &optionsBuilder),\n    G_DBUS_CALL_FLAGS_NONE,\n    3000,\n    nullptr,\n    nullptr,\n    [](GObject* proxy, GAsyncResult *res, void *userData) {\n      RemoteDesktop* self = (RemoteDesktop*)(userData);\n      self->handleOpenPipewireRemote(proxy, res);\n    },\n    this);\n}\n\nvoid RemoteDesktop::handleCreateSession(GVariant *parameters)\n{\n  GVariant* result;\n  uint32_t response;\n  GVariant* sessionHandleVariant;\n\n  assert(sessionHandle.empty());\n\n  if (!g_variant_is_of_type(parameters, G_VARIANT_TYPE(\"(ua{sv})\"))) {\n    vlog.error(\"Could not create session: unexpected parameters: %s\",\n               g_variant_print(parameters, true));\n    cancelStartCb(\"Failed to start remote desktop session\");\n    return;\n  }\n\n  g_variant_get(parameters, \"(u@a{sv})\", &response, &result);\n\n  if (response == 1)  {\n    vlog.error(\"Session was cancelled\");\n    cancelStartCb(\"Failed to start remote desktop session\");\n    return;\n  }\n  else if (response == 2) {\n    vlog.error(\"Failed to create session\");\n    cancelStartCb(\"Failed to start remote desktop session\");\n    return;\n  }\n\n  sessionHandleVariant = g_variant_lookup_value(result, \"session_handle\",\n                                                G_VARIANT_TYPE_STRING);\n  g_variant_unref(result);\n\n  if (!sessionHandleVariant) {\n    vlog.error(\"Failed to create session: no session handle\");\n    cancelStartCb(\"Failed to start remote desktop session\");\n    return;\n  }\n\n  sessionHandle = g_variant_get_string(sessionHandleVariant, nullptr);\n  g_variant_unref(sessionHandleVariant);\n\n  // This proxy is used to to close the session.\n  session = new PortalProxy(\"org.freedesktop.portal.Desktop\",\n                            sessionHandle.c_str(),\n                            \"org.freedesktop.portal.Session\");\n\n  selectDevices();\n}\n\nvoid RemoteDesktop::handleStart(GVariant* parameters)\n{\n  uint32_t responseCode;\n  GVariant* result;\n  GVariant* streams;\n  GVariant* devices;\n  GVariant* newRestoreToken;\n  GVariant* clipboardEnabled_;\n\n  assert(!sessionStarted);\n\n  if (!g_variant_is_of_type(parameters, G_VARIANT_TYPE(\"(ua{sv})\"))) {\n    vlog.error(\"Could not start remote desktop: unexpected parameters %s\",\n               g_variant_get_type_string(parameters));\n    cancelStartCb(\"Failed to start remote desktop session\");\n    return;\n  }\n\n  g_variant_get(parameters, \"(u@a{sv})\", &responseCode, &result);\n\n  if (responseCode == 1) {\n    g_variant_unref(result);\n    vlog.error(\"Could not start remote desktop - local user denied the connection.\");\n    cancelStartCb(\"Failed to start remote desktop session\");\n    return;\n  } else if (responseCode == 2) {\n    g_variant_unref(result);\n    vlog.error(\"Failed to start remote desktop session\");\n    cancelStartCb(\"Failed to start remote desktop session\");\n    return;\n  }\n\n  sessionStarted = true;\n\n  devices = g_variant_lookup_value(result, \"devices\", G_VARIANT_TYPE_UINT32);\n\n  if (!devices) {\n    g_variant_unref(result);\n    vlog.error(\"Failed to get devices\");\n    cancelStartCb(\"Failed to start remote desktop session\");\n    return;\n  }\n\n  selectedDevices = g_variant_get_uint32(devices);\n  g_variant_unref(devices);\n\n  streams = g_variant_lookup_value(result, \"streams\",\n                                    G_VARIANT_TYPE_ARRAY);\n  g_variant_unref(result);\n\n  if (!streams) {\n    vlog.error(\"Failed to start remote desktop session\");\n    cancelStartCb(\"Failed to get streams\");\n    return;\n  }\n\n  clipboardEnabled_ = g_variant_lookup_value(result,\"clipboard_enabled\",\n                                             G_VARIANT_TYPE_BOOLEAN);\n  if (clipboardEnabled_) {\n    clipboardEnabled = g_variant_get_boolean(clipboardEnabled_);\n    g_variant_unref(clipboardEnabled_);\n  }\n\n  if (clipboardEnabled)\n    clipboardSubscribeCb();\n\n  if (!parseStreams(streams)) {\n    vlog.error(\"Failed to parse streams\");\n    cancelStartCb(\"Failed to start remote desktop session\");\n    g_variant_unref(streams);\n    return;\n  }\n  g_variant_unref(streams);\n\n  newRestoreToken = g_variant_lookup_value(result, \"restore_token\",\n                                         G_VARIANT_TYPE_STRING);\n\n  if (newRestoreToken) {\n    storeRestoreToken(g_variant_get_string(newRestoreToken, nullptr));\n    g_variant_unref(newRestoreToken);\n  } else {\n    vlog.info(\"Could not get restore token - display choice will not be saved\");\n  }\n\n  openPipewireRemote();\n}\n\nvoid RemoteDesktop::handleSelectSources(GVariant* /* parameters */)\n{\n  if (Clipboard::available())\n    initClipboardCb();\n\n  start();\n}\n\nvoid RemoteDesktop::handleSelectDevices(GVariant* /* parameters */)\n{\n  selectSources();\n}\n\nvoid RemoteDesktop::handleOpenPipewireRemote(GObject *proxy,\n                                             GAsyncResult *res)\n{\n  GError* error = nullptr;\n  GUnixFDList* fdList = nullptr;\n  GVariant* response;\n  int32_t fdIndex;\n  int fd;\n\n  assert(G_IS_DBUS_PROXY(proxy));\n\n  response = g_dbus_proxy_call_with_unix_fd_list_finish(G_DBUS_PROXY(proxy),\n                                                        &fdList, res,\n                                                        &error);\n\n  if (error) {\n    vlog.error(\"Could not start PipeWire remote: %s\", error->message);\n    g_error_free(error);\n    cancelStartCb(\"Failed to start remote desktop session\");\n    return;\n  }\n\n  if (!g_variant_is_of_type(response, G_VARIANT_TYPE(\"(h)\"))) {\n    g_variant_unref(response);\n    vlog.error(\"Could not start PipeWire: invalid response type: %s\",\n               g_variant_get_type_string(response));\n    cancelStartCb(\"Failed to start remote desktop session\");\n    return;\n  }\n\n  g_variant_get(response, \"(h)\", &fdIndex);\n  g_variant_unref(response);\n\n  fd = g_unix_fd_list_get(fdList, fdIndex, &error);\n  g_object_unref(fdList);\n\n  if (error) {\n    vlog.error(\"Could not start PipeWire remote: error getting fd list:  %s\",\n               error->message);\n    g_error_free(error);\n    cancelStartCb(\"Failed to start remote desktop session\");\n\n    return;\n  }\n\n  // FIXME: Handle multiple streams\n  startPipewireCb(fd, pipewireNodeId);\n}\n\nbool RemoteDesktop::parseStreams(GVariant* streams)\n{\n  GVariantIter iter;\n  GVariant* stream;\n  int n_streams;\n\n  g_variant_iter_init(&iter, streams);\n  n_streams = g_variant_iter_n_children(&iter);\n\n  if (n_streams  < 1) {\n    vlog.error(\"Could not find streams to parse\");\n    return false;\n  }\n\n  if (n_streams != 1) {\n    vlog.error(\"Only one stream supported, got %d\",\n               n_streams);\n  }\n\n  stream = g_variant_get_child_value(streams, 0);\n  g_variant_get_child(stream, 0, \"u\", &pipewireNodeId);\n\n  g_variant_unref(stream);\n\n  return true;\n}\n\nbool RemoteDesktop::loadRestoreToken()\n{\n  char filepath[PATH_MAX];\n  FILE* f;\n  const char* stateDir;\n  char restoreToken_[37];\n\n  if (rememberDisplayChoice == \"Never\")\n    return false;\n\n  // restoreToken will be empty the first time, we want to prompt the user\n  if (rememberDisplayChoice == \"Session\")\n    return !restoreToken.empty();\n\n  assert(rememberDisplayChoice == \"Always\");\n\n  // Only load from disk the first time\n  if (!restoreToken.empty())\n    return true;\n\n  stateDir = core::getvncstatedir();\n  if (!stateDir) {\n    vlog.error(\"Could not get state directory\");\n    return false;\n  }\n\n  snprintf(filepath, sizeof(filepath), \"%s/%s\", stateDir, RESTORE_TOKEN_FILENAME);\n  f = fopen(filepath, \"r\");\n  if (!f) {\n    if (errno != ENOENT)\n      vlog.error(\"Could not open \\\"%s\\\": %s\", filepath, strerror(errno));\n\n    return false;\n  }\n\n  if (fgets(restoreToken_, sizeof(restoreToken_), f)) {\n    uuid_t uuid;\n\n    fclose(f);\n    if (uuid_parse(restoreToken_, uuid) < 0) {\n      vlog.error(\"Invalid restore token, not a valid UUID string \\\"%s\\\"\", restoreToken_);\n      return false;\n    }\n\n    restoreToken = restoreToken_;\n    return true;\n  }\n  fclose(f);\n\n  vlog.error(\"Could not read restore token from \\\"%s\\\"\", filepath);\n  return false;\n}\n\nbool RemoteDesktop::storeRestoreToken(const char* newToken)\n{\n  char filepath[PATH_MAX];\n  FILE* f;\n  const char* stateDir;\n\n  if (!newToken)\n    return false;\n\n  // Don't store anything\n  if (rememberDisplayChoice == \"Never\")\n    return true;\n\n  // Store token in memory\n  restoreToken = newToken;\n\n  if (rememberDisplayChoice == \"Session\")\n    return true;\n\n  assert(rememberDisplayChoice == \"Always\");\n\n  // Store token to file so it can be re-used on next startup\n  stateDir = core::getvncstatedir();\n  if (!stateDir) {\n    vlog.error(\"Could not determine VNC state directory path, cannot store restore token\");\n    return false;\n  }\n\n  if (core::mkdir_p(stateDir, 0755) == -1) {\n    if (errno != EEXIST) {\n      vlog.error(\"Could not create VNC config directory \\\"%s\\\": %s\",\n                  stateDir, strerror(errno));\n      return false;\n    }\n  }\n\n  snprintf(filepath, sizeof(filepath), \"%s/%s\", stateDir,\n           RESTORE_TOKEN_FILENAME);\n\n  f = fopen(filepath, \"w\");\n  if (!f) {\n    vlog.error(\"Could not store token to \\\"%s\\\": %s\", filepath, strerror(errno));\n    return false;\n  }\n\n  fprintf(f, \"%s\", newToken);\n  fclose(f);\n\n  return true;\n}\n"
  },
  {
    "path": "unix/w0vncserver/portals/RemoteDesktop.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __REMOTE_DESKTOP_H__\n#define __REMOTE_DESKTOP_H__\n\n#include <stdint.h>\n\n#include <functional>\n#include <string>\n\n#include <gio/gio.h>\n\nnamespace rfb { class VNCServer; }\n\nclass PortalProxy;\nclass Clipboard;\nstruct PendingData;\n\nclass RemoteDesktop {\npublic:\n  RemoteDesktop(std::string restoreToken,\n                std::function<void(int fd, uint32_t nodeId)> startPipewireCb,\n                std::function<void(const char*)> cancelStartCb,\n                std::function<void()> initClipboardCb,\n                std::function<void()> clipboardSubscribeCb);\n  ~RemoteDesktop();\n\n  // Methods called from SDesktop\n\n  // keyEvent\n  void notifyKeyboardKeysym(uint32_t keysym, bool down);\n  // keyEvent using rawKeyboard\n  void notifyKeyboardKeycode(uint32_t xtcode, bool down);\n  // pointerEvent\n  void notifyPointerMotionAbsolute(int32_t x, int32_t y, uint16_t buttonMask);\n\n  // Create a Portal session\n  void createSession();\n\n  std::string getRestoreToken() const { return restoreToken; }\n  std::string getSessionHandle() const { return sessionHandle; }\n  bool getClipboardEnabled() const { return clipboardEnabled; }\n\nprivate:\n  // Portal methods\n  void selectionWrite(uint32_t serial);\n  void selectionWriteDone(uint32_t serial, bool success);\n  void closeSession();\n  void selectDevices();\n  void selectSources();\n  void start();\n  void openPipewireRemote();\n\n  // Portal signal callbacks\n  void handleCreateSession(GVariant *parameters);\n  void handleStart(GVariant *parameters);\n  void handleSelectDevices(GVariant *parameters);\n  void handleSelectSources(GVariant *parameters);\n  void handleRequestClipboard(GVariant *parameters);\n  void handleOpenPipewireRemote(GObject *proxy, GAsyncResult *res);\n\n  // pointerEvent help functions\n  void notifyPointerButton(int32_t button, bool down);\n  void notifyPointerAxisDiscrete(int32_t button);\n\n  // Parses ScreenCast streams. Returns false on error\n  bool parseStreams(GVariant* streams);\n\n  // Loads the restore token, returns false on error\n  bool loadRestoreToken();\n  // Stores the restore token, returns false on error\n  bool storeRestoreToken(const char* restoreToken);\n\nprivate:\n  bool sessionStarted;\n  uint16_t oldButtonMask;\n  uint32_t selectedDevices;\n  bool clipboardEnabled;\n  std::string sessionHandle;\n\n  uint32_t pipewireNodeId;\n  PortalProxy* remoteDesktop;\n  PortalProxy* screenCast;\n  PortalProxy* session;\n\n  std::string restoreToken;\n\n  std::function<void(int fd, uint32_t nodeId)> startPipewireCb;\n  std::function<void(const char* reason)> cancelStartCb;\n  std::function<void()> initClipboardCb;\n  std::function<void()> clipboardSubscribeCb;\n};\n\n#endif // __REMOTE_DESKTOP_H__\n"
  },
  {
    "path": "unix/w0vncserver/portals/portalConstants.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __PORTAL_CONSTANTS_H__\n#define __PORTAL_CONSTANTS_H__\n\n// Source types\nstatic const int SRC_MONITOR = (1 << 0);\nstatic const int SRC_WINDOW =  (1 << 1);\nstatic const int SRC_VIRTUAL = (1 << 2);\n\n// Cursor modes\nstatic const int CUR_HIDDEN =   (1 << 0);\nstatic const int CUR_EMBEDDED = (1 << 1);\nstatic const int CUR_METADATA = (1 << 2);\n\n// Devices types\nstatic const int DEV_KEYBOARD =    (1 << 0);\nstatic const int DEV_POINTER =     (1 << 1);\nstatic const int DEV_TOUCHSCREEN = (1 << 2);\n\n// Persist modes\nstatic const int DO_NOT_PERSIST = 0;\nstatic const int PERSIST_WHILE_RUNNING = 1;\nstatic const int PERSIST_UNTIL_REVOKED = 2;\n\n#endif // __PORTAL_CONSTANTS_H__\n"
  },
  {
    "path": "unix/w0vncserver/qnum_to_xorgevdev.c",
    "content": "/*\n * This file is auto-generated from keymaps.csv\n * Database checksum sha256(527727ef96d7103a8d7725a6ed9738812660b5a3f4aec086dd7b587b1ba9fcca)\n * To re-generate, run:\n *   keymap-gen code-map --lang=stdc keymaps.csv qnum xorgevdev\n*/\nconst unsigned short code_map_qnum_to_xorgevdev[254] = {\n  [0x1] = 0x9, /* qnum:1 -> linux:1 (KEY_ESC) -> xorgevdev:9 */\n  [0x2] = 0xa, /* qnum:2 -> linux:2 (KEY_1) -> xorgevdev:10 */\n  [0x3] = 0xb, /* qnum:3 -> linux:3 (KEY_2) -> xorgevdev:11 */\n  [0x4] = 0xc, /* qnum:4 -> linux:4 (KEY_3) -> xorgevdev:12 */\n  [0x5] = 0xd, /* qnum:5 -> linux:5 (KEY_4) -> xorgevdev:13 */\n  [0x6] = 0xe, /* qnum:6 -> linux:6 (KEY_5) -> xorgevdev:14 */\n  [0x7] = 0xf, /* qnum:7 -> linux:7 (KEY_6) -> xorgevdev:15 */\n  [0x8] = 0x10, /* qnum:8 -> linux:8 (KEY_7) -> xorgevdev:16 */\n  [0x9] = 0x11, /* qnum:9 -> linux:9 (KEY_8) -> xorgevdev:17 */\n  [0xa] = 0x12, /* qnum:10 -> linux:10 (KEY_9) -> xorgevdev:18 */\n  [0xb] = 0x13, /* qnum:11 -> linux:11 (KEY_0) -> xorgevdev:19 */\n  [0xc] = 0x14, /* qnum:12 -> linux:12 (KEY_MINUS) -> xorgevdev:20 */\n  [0xd] = 0x15, /* qnum:13 -> linux:13 (KEY_EQUAL) -> xorgevdev:21 */\n  [0xe] = 0x16, /* qnum:14 -> linux:14 (KEY_BACKSPACE) -> xorgevdev:22 */\n  [0xf] = 0x17, /* qnum:15 -> linux:15 (KEY_TAB) -> xorgevdev:23 */\n  [0x10] = 0x18, /* qnum:16 -> linux:16 (KEY_Q) -> xorgevdev:24 */\n  [0x11] = 0x19, /* qnum:17 -> linux:17 (KEY_W) -> xorgevdev:25 */\n  [0x12] = 0x1a, /* qnum:18 -> linux:18 (KEY_E) -> xorgevdev:26 */\n  [0x13] = 0x1b, /* qnum:19 -> linux:19 (KEY_R) -> xorgevdev:27 */\n  [0x14] = 0x1c, /* qnum:20 -> linux:20 (KEY_T) -> xorgevdev:28 */\n  [0x15] = 0x1d, /* qnum:21 -> linux:21 (KEY_Y) -> xorgevdev:29 */\n  [0x16] = 0x1e, /* qnum:22 -> linux:22 (KEY_U) -> xorgevdev:30 */\n  [0x17] = 0x1f, /* qnum:23 -> linux:23 (KEY_I) -> xorgevdev:31 */\n  [0x18] = 0x20, /* qnum:24 -> linux:24 (KEY_O) -> xorgevdev:32 */\n  [0x19] = 0x21, /* qnum:25 -> linux:25 (KEY_P) -> xorgevdev:33 */\n  [0x1a] = 0x22, /* qnum:26 -> linux:26 (KEY_LEFTBRACE) -> xorgevdev:34 */\n  [0x1b] = 0x23, /* qnum:27 -> linux:27 (KEY_RIGHTBRACE) -> xorgevdev:35 */\n  [0x1c] = 0x24, /* qnum:28 -> linux:28 (KEY_ENTER) -> xorgevdev:36 */\n  [0x1d] = 0x25, /* qnum:29 -> linux:29 (KEY_LEFTCTRL) -> xorgevdev:37 */\n  [0x1e] = 0x26, /* qnum:30 -> linux:30 (KEY_A) -> xorgevdev:38 */\n  [0x1f] = 0x27, /* qnum:31 -> linux:31 (KEY_S) -> xorgevdev:39 */\n  [0x20] = 0x28, /* qnum:32 -> linux:32 (KEY_D) -> xorgevdev:40 */\n  [0x21] = 0x29, /* qnum:33 -> linux:33 (KEY_F) -> xorgevdev:41 */\n  [0x22] = 0x2a, /* qnum:34 -> linux:34 (KEY_G) -> xorgevdev:42 */\n  [0x23] = 0x2b, /* qnum:35 -> linux:35 (KEY_H) -> xorgevdev:43 */\n  [0x24] = 0x2c, /* qnum:36 -> linux:36 (KEY_J) -> xorgevdev:44 */\n  [0x25] = 0x2d, /* qnum:37 -> linux:37 (KEY_K) -> xorgevdev:45 */\n  [0x26] = 0x2e, /* qnum:38 -> linux:38 (KEY_L) -> xorgevdev:46 */\n  [0x27] = 0x2f, /* qnum:39 -> linux:39 (KEY_SEMICOLON) -> xorgevdev:47 */\n  [0x28] = 0x30, /* qnum:40 -> linux:40 (KEY_APOSTROPHE) -> xorgevdev:48 */\n  [0x29] = 0x31, /* qnum:41 -> linux:41 (KEY_GRAVE) -> xorgevdev:49 */\n  [0x2a] = 0x32, /* qnum:42 -> linux:42 (KEY_LEFTSHIFT) -> xorgevdev:50 */\n  [0x2b] = 0x33, /* qnum:43 -> linux:43 (KEY_BACKSLASH) -> xorgevdev:51 */\n  [0x2c] = 0x34, /* qnum:44 -> linux:44 (KEY_Z) -> xorgevdev:52 */\n  [0x2d] = 0x35, /* qnum:45 -> linux:45 (KEY_X) -> xorgevdev:53 */\n  [0x2e] = 0x36, /* qnum:46 -> linux:46 (KEY_C) -> xorgevdev:54 */\n  [0x2f] = 0x37, /* qnum:47 -> linux:47 (KEY_V) -> xorgevdev:55 */\n  [0x30] = 0x38, /* qnum:48 -> linux:48 (KEY_B) -> xorgevdev:56 */\n  [0x31] = 0x39, /* qnum:49 -> linux:49 (KEY_N) -> xorgevdev:57 */\n  [0x32] = 0x3a, /* qnum:50 -> linux:50 (KEY_M) -> xorgevdev:58 */\n  [0x33] = 0x3b, /* qnum:51 -> linux:51 (KEY_COMMA) -> xorgevdev:59 */\n  [0x34] = 0x3c, /* qnum:52 -> linux:52 (KEY_DOT) -> xorgevdev:60 */\n  [0x35] = 0x3d, /* qnum:53 -> linux:53 (KEY_SLASH) -> xorgevdev:61 */\n  [0x36] = 0x3e, /* qnum:54 -> linux:54 (KEY_RIGHTSHIFT) -> xorgevdev:62 */\n  [0x37] = 0x3f, /* qnum:55 -> linux:55 (KEY_KPASTERISK) -> xorgevdev:63 */\n  [0x38] = 0x40, /* qnum:56 -> linux:56 (KEY_LEFTALT) -> xorgevdev:64 */\n  [0x39] = 0x41, /* qnum:57 -> linux:57 (KEY_SPACE) -> xorgevdev:65 */\n  [0x3a] = 0x42, /* qnum:58 -> linux:58 (KEY_CAPSLOCK) -> xorgevdev:66 */\n  [0x3b] = 0x43, /* qnum:59 -> linux:59 (KEY_F1) -> xorgevdev:67 */\n  [0x3c] = 0x44, /* qnum:60 -> linux:60 (KEY_F2) -> xorgevdev:68 */\n  [0x3d] = 0x45, /* qnum:61 -> linux:61 (KEY_F3) -> xorgevdev:69 */\n  [0x3e] = 0x46, /* qnum:62 -> linux:62 (KEY_F4) -> xorgevdev:70 */\n  [0x3f] = 0x47, /* qnum:63 -> linux:63 (KEY_F5) -> xorgevdev:71 */\n  [0x40] = 0x48, /* qnum:64 -> linux:64 (KEY_F6) -> xorgevdev:72 */\n  [0x41] = 0x49, /* qnum:65 -> linux:65 (KEY_F7) -> xorgevdev:73 */\n  [0x42] = 0x4a, /* qnum:66 -> linux:66 (KEY_F8) -> xorgevdev:74 */\n  [0x43] = 0x4b, /* qnum:67 -> linux:67 (KEY_F9) -> xorgevdev:75 */\n  [0x44] = 0x4c, /* qnum:68 -> linux:68 (KEY_F10) -> xorgevdev:76 */\n  [0x45] = 0x4d, /* qnum:69 -> linux:69 (KEY_NUMLOCK) -> xorgevdev:77 */\n  [0x46] = 0x4e, /* qnum:70 -> linux:70 (KEY_SCROLLLOCK) -> xorgevdev:78 */\n  [0x47] = 0x4f, /* qnum:71 -> linux:71 (KEY_KP7) -> xorgevdev:79 */\n  [0x48] = 0x50, /* qnum:72 -> linux:72 (KEY_KP8) -> xorgevdev:80 */\n  [0x49] = 0x51, /* qnum:73 -> linux:73 (KEY_KP9) -> xorgevdev:81 */\n  [0x4a] = 0x52, /* qnum:74 -> linux:74 (KEY_KPMINUS) -> xorgevdev:82 */\n  [0x4b] = 0x53, /* qnum:75 -> linux:75 (KEY_KP4) -> xorgevdev:83 */\n  [0x4c] = 0x54, /* qnum:76 -> linux:76 (KEY_KP5) -> xorgevdev:84 */\n  [0x4d] = 0x55, /* qnum:77 -> linux:77 (KEY_KP6) -> xorgevdev:85 */\n  [0x4e] = 0x56, /* qnum:78 -> linux:78 (KEY_KPPLUS) -> xorgevdev:86 */\n  [0x4f] = 0x57, /* qnum:79 -> linux:79 (KEY_KP1) -> xorgevdev:87 */\n  [0x50] = 0x58, /* qnum:80 -> linux:80 (KEY_KP2) -> xorgevdev:88 */\n  [0x51] = 0x59, /* qnum:81 -> linux:81 (KEY_KP3) -> xorgevdev:89 */\n  [0x52] = 0x5a, /* qnum:82 -> linux:82 (KEY_KP0) -> xorgevdev:90 */\n  [0x53] = 0x5b, /* qnum:83 -> linux:83 (KEY_KPDOT) -> xorgevdev:91 */\n  [0x54] = 0x6b, /* qnum:84 -> linux:99 (KEY_SYSRQ) -> xorgevdev:107 */\n  [0x55] = 0xc2, /* qnum:85 -> linux:186 (KEY_F16) -> xorgevdev:194 */\n  [0x56] = 0x5e, /* qnum:86 -> linux:86 (KEY_102ND) -> xorgevdev:94 */\n  [0x57] = 0x5f, /* qnum:87 -> linux:87 (KEY_F11) -> xorgevdev:95 */\n  [0x58] = 0x60, /* qnum:88 -> linux:88 (KEY_F12) -> xorgevdev:96 */\n  [0x59] = 0x7d, /* qnum:89 -> linux:117 (KEY_KPEQUAL) -> xorgevdev:125 */\n  [0x5a] = 0xc6, /* qnum:90 -> linux:190 (KEY_F20) -> xorgevdev:198 */\n  [0x5b] = 0x6d, /* qnum:91 -> linux:101 (KEY_LINEFEED) -> xorgevdev:109 */\n  [0x5c] = 0x67, /* qnum:92 -> linux:95 (KEY_KPJPCOMMA) -> xorgevdev:103 */\n  [0x5d] = 0xbf, /* qnum:93 -> linux:183 (KEY_F13) -> xorgevdev:191 */\n  [0x5e] = 0xc0, /* qnum:94 -> linux:184 (KEY_F14) -> xorgevdev:192 */\n  [0x5f] = 0xc1, /* qnum:95 -> linux:185 (KEY_F15) -> xorgevdev:193 */\n  [0x63] = 0xb1, /* qnum:99 -> linux:169 (KEY_PHONE) -> xorgevdev:177 */\n  [0x64] = 0x8e, /* qnum:100 -> linux:134 (KEY_OPEN) -> xorgevdev:142 */\n  [0x65] = 0x8f, /* qnum:101 -> linux:135 (KEY_PASTE) -> xorgevdev:143 */\n  [0x66] = 0x95, /* qnum:102 -> linux:141 (KEY_SETUP) -> xorgevdev:149 */\n  [0x67] = 0x98, /* qnum:103 -> linux:144 (KEY_FILE) -> xorgevdev:152 */\n  [0x68] = 0x99, /* qnum:104 -> linux:145 (KEY_SENDFILE) -> xorgevdev:153 */\n  [0x69] = 0x9a, /* qnum:105 -> linux:146 (KEY_DELETEFILE) -> xorgevdev:154 */\n  [0x6a] = 0x9f, /* qnum:106 -> linux:151 (KEY_MSDOS) -> xorgevdev:159 */\n  [0x6b] = 0xa1, /* qnum:107 -> linux:153 (KEY_DIRECTION) -> xorgevdev:161 */\n  [0x6c] = 0xa9, /* qnum:108 -> linux:161 (KEY_EJECTCD) -> xorgevdev:169 */\n  [0x6d] = 0xc9, /* qnum:109 -> linux:193 (KEY_F23) -> xorgevdev:201 */\n  [0x6f] = 0xca, /* qnum:111 -> linux:194 (KEY_F24) -> xorgevdev:202 */\n  [0x70] = 0x65, /* qnum:112 -> linux:93 (KEY_KATAKANAHIRAGANA) -> xorgevdev:101 */\n  [0x71] = 0x83, /* qnum:113 -> linux:123 (KEY_HANJA) -> xorgevdev:131 */\n  [0x72] = 0x82, /* qnum:114 -> linux:122 (KEY_HANGEUL) -> xorgevdev:130 */\n  [0x73] = 0x61, /* qnum:115 -> linux:89 (KEY_RO) -> xorgevdev:97 */\n  [0x74] = 0xc7, /* qnum:116 -> linux:191 (KEY_F21) -> xorgevdev:199 */\n  [0x75] = 0xb9, /* qnum:117 -> linux:177 (KEY_SCROLLUP) -> xorgevdev:185 */\n  [0x76] = 0x5d, /* qnum:118 -> linux:85 (KEY_ZENKAKUHANKAKU) -> xorgevdev:93 */\n  [0x77] = 0x63, /* qnum:119 -> linux:91 (KEY_HIRAGANA) -> xorgevdev:99 */\n  [0x78] = 0x62, /* qnum:120 -> linux:90 (KEY_KATAKANA) -> xorgevdev:98 */\n  [0x79] = 0x64, /* qnum:121 -> linux:92 (KEY_HENKAN) -> xorgevdev:100 */\n  [0x7b] = 0x66, /* qnum:123 -> linux:94 (KEY_MUHENKAN) -> xorgevdev:102 */\n  [0x7d] = 0x84, /* qnum:125 -> linux:124 (KEY_YEN) -> xorgevdev:132 */\n  [0x7e] = 0x81, /* qnum:126 -> linux:121 (KEY_KPCOMMA) -> xorgevdev:129 */\n  [0x81] = 0xb3, /* qnum:129 -> linux:171 (KEY_CONFIG) -> xorgevdev:179 */\n  [0x82] = 0x9e, /* qnum:130 -> linux:150 (KEY_WWW) -> xorgevdev:158 */\n  [0x83] = 0xc3, /* qnum:131 -> linux:187 (KEY_F17) -> xorgevdev:195 */\n  [0x84] = 0xc5, /* qnum:132 -> linux:189 (KEY_F19) -> xorgevdev:197 */\n  [0x85] = 0x89, /* qnum:133 -> linux:129 (KEY_AGAIN) -> xorgevdev:137 */\n  [0x86] = 0x8a, /* qnum:134 -> linux:130 (KEY_PROPS) -> xorgevdev:138 */\n  [0x87] = 0x8b, /* qnum:135 -> linux:131 (KEY_UNDO) -> xorgevdev:139 */\n  [0x88] = 0xb8, /* qnum:136 -> linux:176 (KEY_EDIT) -> xorgevdev:184 */\n  [0x89] = 0xbd, /* qnum:137 -> linux:181 (KEY_NEW) -> xorgevdev:189 */\n  [0x8a] = 0xbe, /* qnum:138 -> linux:182 (KEY_REDO) -> xorgevdev:190 */\n  [0x8b] = 0x80, /* qnum:139 -> linux:120 (KEY_SCALE) -> xorgevdev:128 */\n  [0x8c] = 0x8c, /* qnum:140 -> linux:132 (KEY_FRONT) -> xorgevdev:140 */\n  [0x8e] = 0xf1, /* qnum:142 -> linux:233 (KEY_FORWARDMAIL) -> xorgevdev:241 */\n  [0x8f] = 0xba, /* qnum:143 -> linux:178 (KEY_SCROLLDOWN) -> xorgevdev:186 */\n  [0x90] = 0xad, /* qnum:144 -> linux:165 (KEY_PREVIOUSSONG) -> xorgevdev:173 */\n  [0x92] = 0xa0, /* qnum:146 -> linux:152 (KEY_SCREENLOCK) -> xorgevdev:160 */\n  [0x93] = 0x9b, /* qnum:147 -> linux:147 (KEY_XFER) -> xorgevdev:155 */\n  [0x94] = 0xe6, /* qnum:148 -> linux:222 (KEY_ALTERASE) -> xorgevdev:230 */\n  [0x95] = 0xcb, /* qnum:149 -> linux:195 (unnamed) -> xorgevdev:203 */\n  [0x96] = 0xcc, /* qnum:150 -> linux:196 (unnamed) -> xorgevdev:204 */\n  [0x97] = 0x9d, /* qnum:151 -> linux:149 (KEY_PROG2) -> xorgevdev:157 */\n  [0x98] = 0xb0, /* qnum:152 -> linux:168 (KEY_REWIND) -> xorgevdev:176 */\n  [0x99] = 0xab, /* qnum:153 -> linux:163 (KEY_NEXTSONG) -> xorgevdev:171 */\n  [0x9a] = 0xcd, /* qnum:154 -> linux:197 (unnamed) -> xorgevdev:205 */\n  [0x9b] = 0xce, /* qnum:155 -> linux:198 (unnamed) -> xorgevdev:206 */\n  [0x9c] = 0x68, /* qnum:156 -> linux:96 (KEY_KPENTER) -> xorgevdev:104 */\n  [0x9d] = 0x69, /* qnum:157 -> linux:97 (KEY_RIGHTCTRL) -> xorgevdev:105 */\n  [0x9e] = 0x93, /* qnum:158 -> linux:139 (KEY_MENU) -> xorgevdev:147 */\n  [0x9f] = 0x9c, /* qnum:159 -> linux:148 (KEY_PROG1) -> xorgevdev:156 */\n  [0xa0] = 0x79, /* qnum:160 -> linux:113 (KEY_MUTE) -> xorgevdev:121 */\n  [0xa1] = 0x94, /* qnum:161 -> linux:140 (KEY_CALC) -> xorgevdev:148 */\n  [0xa2] = 0xac, /* qnum:162 -> linux:164 (KEY_PLAYPAUSE) -> xorgevdev:172 */\n  [0xa3] = 0xa8, /* qnum:163 -> linux:160 (KEY_CLOSECD) -> xorgevdev:168 */\n  [0xa4] = 0xae, /* qnum:164 -> linux:166 (KEY_STOPCD) -> xorgevdev:174 */\n  [0xa5] = 0xd5, /* qnum:165 -> linux:205 (KEY_SUSPEND) -> xorgevdev:213 */\n  [0xa6] = 0xa2, /* qnum:166 -> linux:154 (KEY_CYCLEWINDOWS) -> xorgevdev:162 */\n  [0xa7] = 0xcf, /* qnum:167 -> linux:199 (unnamed) -> xorgevdev:207 */\n  [0xa8] = 0xd0, /* qnum:168 -> linux:200 (KEY_PLAYCD) -> xorgevdev:208 */\n  [0xa9] = 0xd1, /* qnum:169 -> linux:201 (KEY_PAUSECD) -> xorgevdev:209 */\n  [0xab] = 0xd2, /* qnum:171 -> linux:202 (KEY_PROG3) -> xorgevdev:210 */\n  [0xac] = 0xd3, /* qnum:172 -> linux:203 (KEY_PROG4) -> xorgevdev:211 */\n  [0xad] = 0xd4, /* qnum:173 -> linux:204 (KEY_DASHBOARD) -> xorgevdev:212 */\n  [0xae] = 0x7a, /* qnum:174 -> linux:114 (KEY_VOLUMEDOWN) -> xorgevdev:122 */\n  [0xaf] = 0xd6, /* qnum:175 -> linux:206 (KEY_CLOSE) -> xorgevdev:214 */\n  [0xb0] = 0x7b, /* qnum:176 -> linux:115 (KEY_VOLUMEUP) -> xorgevdev:123 */\n  [0xb1] = 0xaf, /* qnum:177 -> linux:167 (KEY_RECORD) -> xorgevdev:175 */\n  [0xb2] = 0xb4, /* qnum:178 -> linux:172 (KEY_HOMEPAGE) -> xorgevdev:180 */\n  [0xb3] = 0xd7, /* qnum:179 -> linux:207 (KEY_PLAY) -> xorgevdev:215 */\n  [0xb4] = 0xd8, /* qnum:180 -> linux:208 (KEY_FASTFORWARD) -> xorgevdev:216 */\n  [0xb5] = 0x6a, /* qnum:181 -> linux:98 (KEY_KPSLASH) -> xorgevdev:106 */\n  [0xb6] = 0xd9, /* qnum:182 -> linux:209 (KEY_BASSBOOST) -> xorgevdev:217 */\n  [0xb7] = 0x6b, /* qnum:183 -> linux:99 (KEY_SYSRQ) -> xorgevdev:107 */\n  [0xb8] = 0x6c, /* qnum:184 -> linux:100 (KEY_RIGHTALT) -> xorgevdev:108 */\n  [0xb9] = 0xda, /* qnum:185 -> linux:210 (KEY_PRINT) -> xorgevdev:218 */\n  [0xba] = 0xdb, /* qnum:186 -> linux:211 (KEY_HP) -> xorgevdev:219 */\n  [0xbb] = 0xdc, /* qnum:187 -> linux:212 (KEY_CAMERA) -> xorgevdev:220 */\n  [0xbc] = 0x91, /* qnum:188 -> linux:137 (KEY_CUT) -> xorgevdev:145 */\n  [0xbd] = 0xdd, /* qnum:189 -> linux:213 (KEY_SOUND) -> xorgevdev:221 */\n  [0xbe] = 0xde, /* qnum:190 -> linux:214 (KEY_QUESTION) -> xorgevdev:222 */\n  [0xbf] = 0xdf, /* qnum:191 -> linux:215 (KEY_EMAIL) -> xorgevdev:223 */\n  [0xc0] = 0xe0, /* qnum:192 -> linux:216 (KEY_CHAT) -> xorgevdev:224 */\n  [0xc1] = 0x90, /* qnum:193 -> linux:136 (KEY_FIND) -> xorgevdev:144 */\n  [0xc2] = 0xe2, /* qnum:194 -> linux:218 (KEY_CONNECT) -> xorgevdev:226 */\n  [0xc3] = 0xe3, /* qnum:195 -> linux:219 (KEY_FINANCE) -> xorgevdev:227 */\n  [0xc4] = 0xe4, /* qnum:196 -> linux:220 (KEY_SPORT) -> xorgevdev:228 */\n  [0xc5] = 0xe5, /* qnum:197 -> linux:221 (KEY_SHOP) -> xorgevdev:229 */\n  [0xc6] = 0x7f, /* qnum:198 -> linux:119 (KEY_PAUSE) -> xorgevdev:127 */\n  [0xc7] = 0x6e, /* qnum:199 -> linux:102 (KEY_HOME) -> xorgevdev:110 */\n  [0xc8] = 0x6f, /* qnum:200 -> linux:103 (KEY_UP) -> xorgevdev:111 */\n  [0xc9] = 0x70, /* qnum:201 -> linux:104 (KEY_PAGEUP) -> xorgevdev:112 */\n  [0xca] = 0xe7, /* qnum:202 -> linux:223 (KEY_CANCEL) -> xorgevdev:231 */\n  [0xcb] = 0x71, /* qnum:203 -> linux:105 (KEY_LEFT) -> xorgevdev:113 */\n  [0xcc] = 0xe8, /* qnum:204 -> linux:224 (KEY_BRIGHTNESSDOWN) -> xorgevdev:232 */\n  [0xcd] = 0x72, /* qnum:205 -> linux:106 (KEY_RIGHT) -> xorgevdev:114 */\n  [0xce] = 0x7e, /* qnum:206 -> linux:118 (KEY_KPPLUSMINUS) -> xorgevdev:126 */\n  [0xcf] = 0x73, /* qnum:207 -> linux:107 (KEY_END) -> xorgevdev:115 */\n  [0xd0] = 0x74, /* qnum:208 -> linux:108 (KEY_DOWN) -> xorgevdev:116 */\n  [0xd1] = 0x75, /* qnum:209 -> linux:109 (KEY_PAGEDOWN) -> xorgevdev:117 */\n  [0xd2] = 0x76, /* qnum:210 -> linux:110 (KEY_INSERT) -> xorgevdev:118 */\n  [0xd3] = 0x77, /* qnum:211 -> linux:111 (KEY_DELETE) -> xorgevdev:119 */\n  [0xd4] = 0xe9, /* qnum:212 -> linux:225 (KEY_BRIGHTNESSUP) -> xorgevdev:233 */\n  [0xd5] = 0xf2, /* qnum:213 -> linux:234 (KEY_SAVE) -> xorgevdev:242 */\n  [0xd6] = 0xeb, /* qnum:214 -> linux:227 (KEY_SWITCHVIDEOMODE) -> xorgevdev:235 */\n  [0xd7] = 0xec, /* qnum:215 -> linux:228 (KEY_KBDILLUMTOGGLE) -> xorgevdev:236 */\n  [0xd8] = 0xed, /* qnum:216 -> linux:229 (KEY_KBDILLUMDOWN) -> xorgevdev:237 */\n  [0xd9] = 0xee, /* qnum:217 -> linux:230 (KEY_KBDILLUMUP) -> xorgevdev:238 */\n  [0xda] = 0xef, /* qnum:218 -> linux:231 (KEY_SEND) -> xorgevdev:239 */\n  [0xdb] = 0x85, /* qnum:219 -> linux:125 (KEY_LEFTMETA) -> xorgevdev:133 */\n  [0xdc] = 0x86, /* qnum:220 -> linux:126 (KEY_RIGHTMETA) -> xorgevdev:134 */\n  [0xdd] = 0x87, /* qnum:221 -> linux:127 (KEY_COMPOSE) -> xorgevdev:135 */\n  [0xde] = 0x7c, /* qnum:222 -> linux:116 (KEY_POWER) -> xorgevdev:124 */\n  [0xdf] = 0x96, /* qnum:223 -> linux:142 (KEY_SLEEP) -> xorgevdev:150 */\n  [0xe3] = 0x97, /* qnum:227 -> linux:143 (KEY_WAKEUP) -> xorgevdev:151 */\n  [0xe4] = 0xf0, /* qnum:228 -> linux:232 (KEY_REPLY) -> xorgevdev:240 */\n  [0xe5] = 0xe1, /* qnum:229 -> linux:217 (KEY_SEARCH) -> xorgevdev:225 */\n  [0xe6] = 0xa4, /* qnum:230 -> linux:156 (KEY_BOOKMARKS) -> xorgevdev:164 */\n  [0xe7] = 0xb5, /* qnum:231 -> linux:173 (KEY_REFRESH) -> xorgevdev:181 */\n  [0xe8] = 0x88, /* qnum:232 -> linux:128 (KEY_STOP) -> xorgevdev:136 */\n  [0xe9] = 0xa7, /* qnum:233 -> linux:159 (KEY_FORWARD) -> xorgevdev:167 */\n  [0xea] = 0xa6, /* qnum:234 -> linux:158 (KEY_BACK) -> xorgevdev:166 */\n  [0xeb] = 0xa5, /* qnum:235 -> linux:157 (KEY_COMPUTER) -> xorgevdev:165 */\n  [0xec] = 0xa3, /* qnum:236 -> linux:155 (KEY_MAIL) -> xorgevdev:163 */\n  [0xed] = 0xea, /* qnum:237 -> linux:226 (KEY_MEDIA) -> xorgevdev:234 */\n  [0xef] = 0x78, /* qnum:239 -> linux:112 (KEY_MACRO) -> xorgevdev:120 */\n  [0xf0] = 0xf3, /* qnum:240 -> linux:235 (KEY_DOCUMENTS) -> xorgevdev:243 */\n  [0xf1] = 0xf4, /* qnum:241 -> linux:236 (KEY_BATTERY) -> xorgevdev:244 */\n  [0xf2] = 0xf5, /* qnum:242 -> linux:237 (KEY_BLUETOOTH) -> xorgevdev:245 */\n  [0xf3] = 0xf6, /* qnum:243 -> linux:238 (KEY_WLAN) -> xorgevdev:246 */\n  [0xf4] = 0xf7, /* qnum:244 -> linux:239 (KEY_UWB) -> xorgevdev:247 */\n  [0xf5] = 0x92, /* qnum:245 -> linux:138 (KEY_HELP) -> xorgevdev:146 */\n  [0xf6] = 0xbb, /* qnum:246 -> linux:179 (KEY_KPLEFTPAREN) -> xorgevdev:187 */\n  [0xf7] = 0xc4, /* qnum:247 -> linux:188 (KEY_F18) -> xorgevdev:196 */\n  [0xf8] = 0x8d, /* qnum:248 -> linux:133 (KEY_COPY) -> xorgevdev:141 */\n  [0xf9] = 0xc8, /* qnum:249 -> linux:192 (KEY_F22) -> xorgevdev:200 */\n  [0xfb] = 0xbc, /* qnum:251 -> linux:180 (KEY_KPRIGHTPAREN) -> xorgevdev:188 */\n  [0xfd] = 0xaa, /* qnum:253 -> linux:162 (KEY_EJECTCLOSECD) -> xorgevdev:170 */\n};\nconst unsigned int code_map_qnum_to_xorgevdev_len = sizeof(code_map_qnum_to_xorgevdev)/sizeof(code_map_qnum_to_xorgevdev[0]);\n"
  },
  {
    "path": "unix/w0vncserver/w0vncserver-forget.cxx",
    "content": "\n/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <errno.h>\n#include <string.h>\n#include <linux/limits.h>\n\n#include <core/xdgdirs.h>\n#include <core/Configuration.h>\n\n// Sync with RemoteDesktop.cxx\nstatic const char* RESTORE_TOKEN_FILENAME =  \"restoretoken\";\n\nchar* programName = nullptr;\n\nstatic void printVersion(FILE *fp)\n{\n  fprintf(fp, \"TigerVNC server version %s\\n\", PACKAGE_VERSION);\n}\n\nstatic void usage()\n{\n  printVersion(stderr);\n  fprintf(stderr,\"Usage: %s\\n\", programName);\n  exit(1);\n}\n\nint main(int argc, char** argv)\n{\n  char filepath[PATH_MAX];\n  const char* stateDir;\n\n  programName = argv[0];\n\n  for (int i = 1; i < argc; i++) {\n   if ((strcmp(argv[i], \"-h\") == 0) ||\n       (strcmp(argv[i], \"--help\") == 0)) {\n      usage();\n    } else if ((strcmp(argv[i], \"-v\") == 0) ||\n               (strcmp(argv[i], \"--version\") == 0)) {\n      printVersion(stderr);\n      exit(0);\n    } else {\n      fprintf(stderr, \"%s: Extra argument '%s'\\n\", programName, argv[i]);\n      fprintf(stderr, \"See '%s --help' for more information.\\n\",\n              programName);\n      exit(1);\n    }\n  }\n\n  stateDir = core::getvncstatedir();\n  if (!stateDir) {\n    fprintf(stderr, \"Could not get state directory\");\n    return 1;\n  }\n\n  snprintf(filepath, sizeof(filepath), \"%s/%s\", stateDir, RESTORE_TOKEN_FILENAME);\n\n  if (remove(filepath) != 0) {\n    if (errno != ENOENT) {\n      fprintf(stderr, \"Could not remove restore token from \\\"%s\\\": %s\", filepath, strerror(errno));\n      return 1;\n    }\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "unix/w0vncserver/w0vncserver-forget.man",
    "content": ".TH w0vncserver-forget 1 \"\" \"TigerVNC\" \"TigerVNC Manual\"\n.SH NAME\nw0vncserver-forget \\- forget w0vncserver display choice\n.SH SYNOPSIS\n.B w0vncserver-forget\n.SH DESCRIPTION\n.B w0vncserver-forget\nis a utility for \\fBw0vncserver\\fP(1) which will forget the stored\ndisplay choice configuration.\n\n.SH FILES\n.TP\n\\fI$XDG_STATE_HOME/tigervnc/restoretoken\\fP\nDefault location of the restoretoken file.\n\n.SH SEE ALSO\n.BR w0vncserver (1),\n.br\nhttps://www.tigervnc.org/\n\n.SH AUTHOR\nTigerVNC Team\n\nVNC was originally developed by the RealVNC team while at Olivetti\nResearch Ltd / AT&T Laboratories Cambridge.  TightVNC additions were\nimplemented by Constantin Kaplinsky. Many other people have since\nparticipated in development, testing and support. This manual is part\nof the TigerVNC software suite.\n"
  },
  {
    "path": "unix/w0vncserver/w0vncserver.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <glib.h>\n#include <glib-unix.h>\n#include <gio/gio.h>\n\n#include <network/TcpSocket.h>\n#include <network/UnixSocket.h>\n#include <rfb/VNCServerST.h>\n#include <rfb/ServerCore.h>\n#include <rdr/FdOutStream.h>\n#include <core/Logger_stdio.h>\n#include <core/LogWriter.h>\n\n#include \"parameters.h\"\n#include \"GSocketSource.h\"\n#include \"RFBTimerSource.h\"\n#include \"portals/PortalDesktop.h\"\n#include \"wayland/WaylandDesktop.h\"\n\nstatic core::LogWriter vlog(\"main\");\n\nchar* programName;\nstatic GMainLoop* loop = nullptr;\nstatic GDBusConnection* connection = nullptr;\nstatic bool fatalError = false;\n\nvoid fatal_error(const char *error, ...) {\n  char exitError[1024];\n\n  // Prioritise the first error we get as that is probably the most\n  // relevant one.\n  if (fatalError)\n    return;\n\n  fatalError = true;\n\n  va_list ap;\n  va_start(ap, error);\n  vsnprintf(exitError, sizeof(exitError), error, ap);\n  va_end(ap);\n\n  vlog.error(\"%s\", exitError);\n\n  assert(loop);\n  g_main_loop_quit(loop);\n}\n\nstatic void printVersion(FILE *fp)\n{\n  fprintf(fp, \"TigerVNC server version %s\\n\", PACKAGE_VERSION);\n}\n\nstatic void usage()\n{\n  printVersion(stderr);\n  fprintf(stderr, \"\\nUsage: %s [<parameters>]\\n\", programName);\n  fprintf(stderr, \"       %s --version\\n\", programName);\n  fprintf(stderr,\"\\n\"\n          \"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n          \"Parameters which take a value can be specified as \"\n          \"-<param> <value>\\n\"\n          \"Other valid forms are <param>=<value> -<param>=<value> \"\n          \"--<param>=<value>\\n\"\n          \"Parameter names are case-insensitive.  The parameters are:\\n\\n\");\n  core::Configuration::listParams(79, 14);\n  exit(1);\n}\n\nint CleanupSignalHandler(void*)\n{\n  g_main_loop_quit(loop);\n  return 1;\n}\n\nint main(int argc, char** argv)\n{\n  std::list<network::SocketListener*> listeners;\n  int32_t sigintTag;\n  int32_t sigtermTag;\n  int32_t sighupTag;\n  RFBTimerSource* timerSource;\n  GSocketSource* monitor;\n  rfb::SDesktop* desktop;\n  rfb::VNCServerST* server;\n\n  programName = argv[0];\n\n  core::initStdIOLoggers();\n  core::LogWriter::setLogParams(\"*:stderr:30\");\n\n  core::Configuration::removeParam(\"AcceptSetDesktopSize\");\n\n  for (int i = 1; i < argc;) {\n    int ret;\n\n    ret = core::Configuration::handleParamArg(argc, argv, i);\n    if (ret > 0) {\n      i += ret;\n      continue;\n    }\n\n    if (strcmp(argv[i], \"-h\") == 0 ||\n        strcmp(argv[i], \"-help\") == 0 ||\n        strcmp(argv[i], \"--help\") == 0) {\n      usage();\n    }\n\n    if (strcmp(argv[i], \"-v\") == 0 ||\n        strcmp(argv[i], \"-version\") == 0 ||\n        strcmp(argv[i], \"--version\") == 0) {\n      printVersion(stderr);\n      return 0;\n    }\n\n    if (argv[i][0] == '-') {\n      fprintf(stderr, \"%s: Unrecognized option '%s'\\n\",\n              programName, argv[i]);\n      fprintf(stderr, \"See '%s --help' for more information.\\n\",\n              programName);\n      exit(1);\n    }\n\n    fprintf(stderr, \"%s: Extra argument '%s'\\n\", programName, argv[i]);\n    fprintf(stderr, \"See '%s --help' for more information.\\n\",\n            programName);\n    exit(1);\n  }\n\n  try {\n    if (rfbunixpath.getValueStr()[0] != '\\0') {\n      listeners.push_back(new network::UnixListener(rfbunixpath, rfbunixmode));\n      vlog.info(\"Listening on %s (mode %04o)\", (const char*)rfbunixpath, (int)rfbunixmode);\n    }\n\n    if ((int)rfbport != -1) {\n      std::list<network::SocketListener*> tcp_listeners;\n      const char *addr = interface;\n\n      if (strcasecmp(addr, \"all\") == 0)\n        addr = nullptr;\n      if (localhostOnly)\n        createLocalTcpListeners(&tcp_listeners, (int)rfbport);\n      else\n        createTcpListeners(&tcp_listeners, addr, (int)rfbport);\n\n      if (!tcp_listeners.empty()) {\n        listeners.splice (listeners.end(), tcp_listeners);\n        vlog.info(\"Listening for VNC connections on %s interface(s), port %d\",\n                  localhostOnly ? \"local\" : (const char*)interface,\n                  (int)rfbport);\n      }\n    }\n  } catch (std::exception& e) {\n    fprintf(stderr, \"%s\\n\", e.what());\n    return -1;\n  }\n\n  loop = g_main_loop_new(nullptr, false);\n  sigintTag = g_unix_signal_add(SIGINT, CleanupSignalHandler, nullptr);\n  sigtermTag = g_unix_signal_add(SIGTERM, CleanupSignalHandler, nullptr);\n  sighupTag = g_unix_signal_add(SIGHUP, CleanupSignalHandler, nullptr);\n\n  try {\n    if (PortalDesktop::available()) {\n      desktop = new PortalDesktop();\n    } else if (WaylandDesktop::available()) {\n      desktop = new WaylandDesktop(loop);\n    } else {\n      fprintf(stderr, \"No remote desktop implementation found.\\n\");\n      return -1;\n    }\n    server = new rfb::VNCServerST(desktopName, desktop);\n    timerSource = new RFBTimerSource();\n    monitor = new GSocketSource(server, &listeners);\n  } catch (std::exception& e) {\n    vlog.error(\"main: %s\", e.what());\n    return 1;\n  }\n\n  monitor->attach(g_main_loop_get_context(loop));\n  timerSource->attach(g_main_loop_get_context(loop));\n  monitor->listen();\n  g_main_loop_run(loop);\n\n  g_source_remove(sigintTag);\n  g_source_remove(sigtermTag);\n  g_source_remove(sighupTag);\n\n  delete monitor;\n  delete timerSource;\n  delete server;\n  delete desktop;\n\n  for (network::SocketListener* listener : listeners)\n    delete listener;\n\n  // The GDBusConnection is a singleton that we want to close once\n  // before we exit.\n  connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);\n  if (connection)\n    g_dbus_connection_close_sync(connection, nullptr, nullptr);\n\n  g_main_loop_unref(loop);\n}\n"
  },
  {
    "path": "unix/w0vncserver/w0vncserver.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\nvoid fatal_error(const char *error, ...)\n       __attribute__((__format__ (__printf__, 1, 2)));\n"
  },
  {
    "path": "unix/w0vncserver/w0vncserver.man",
    "content": ".TH w0vncserver 1 \"\" \"TigerVNC\" \"TigerVNC Manual\"\n.SH NAME\nw0vncserver \\- TigerVNC server for Wayland compositors\n.SH SYNOPSIS\n.B w0vncserver\n.RI [ options ]\n.br\n.B w0vncserver -version\n.SH DESCRIPTION\n.B w0vncserver\nis a TigerVNC server which makes a Wayland compositor that is based on\nwlroots, or has the RemoteDesktop portal implemented, remotely\naccessible via VNC, TigerVNC or compatible viewers. It does not create\na virtual display, instead, it shares an existing display (typically,\nhat one connected to the physical screen).\n\n.SH OPTIONS\n.B w0vncserver\ninterprets the command line as a list of parameters with optional values.\nRunning \\fBw0vncserver \\-h\\fP will show a list of all valid parameters with\nshort descriptions.  All parameters are optional, but normally you would have\nto use the \\fBPasswordFile\\fP parameter (see its description below).\n.PP\nThere are several forms of specifying parameters in the command line (here we\nuse `\\fISomeParameter\\fP' as an example parameter name):\n\n.TP\n.B -\\fISomeParameter\\fP\nEnable the parameter, turn the feature on.  This form can be used with\nparameters that simply enable or disable some feature.\n.\n.TP\n.B -\\fISomeParameter\\fP=0\nDisable the parameter, turn the feature off.\n.\n.TP\n.B -\\fISomeParameter\\fP=\\fIvalue\\fP\nAssign the specified \\fIvalue\\fP to the parameter.  The leading dash can be\nomitted, or it can be doubled if desired (like in GNU-style long options).\n.PP\nParameter names are case-insensitive, their order in the command line can be\narbitrary.\n\n.SH PARAMETERS\n\n.TP\n.B \\-AcceptCutText\nAccept clipboard updates from clients. Default is on.\n.\n.TP\n.B \\-AcceptKeyEvents\nAccept key press and release events from clients. Default is on.\n.\n.TP\n.B \\-AcceptPointerEvents\nAccept pointer movement and button events from clients. Default is on.\n.\n.TP\n.B \\-AlwaysShared\nAlways treat incoming connections as shared, regardless of the client-specified\nsetting. Default is off.\n.\n.TP\n.B \\-BlacklistThreshold \\fIcount\\fP\nThe number of unauthenticated connection attempts allowed from any individual\nhost before that host is black-listed.  Default is 5.\n.\n.TP\n.B \\-BlacklistTimeout \\fIseconds\\fP\nThe initial timeout applied when a host is first black-listed.  The host\ncannot re-attempt a connection until the timeout expires.  Default is 10.\n.\n.TP\n.B \\-CompareFB \\fImode\\fP\nPerform pixel comparison on framebuffer to reduce unnecessary updates. Can\nbe either \\fB0\\fP (off), \\fB1\\fP (always) or \\fB2\\fP (auto). Default is\n\\fB2\\fP.\n.\n.TP\n.B \\-desktop \\fIdesktop-name\\fP\nEach desktop has a name which may be displayed by the viewer. It defaults to\n\"<user>@<hostname>\".\n.\n.TP\n.B \\-DisconnectClients\nDisconnect existing clients if an incoming connection is non-shared. Default is\non. If \\fBDisconnectClients\\fP is false, then a new non-shared connection will\nbe refused while there is a client active.  When combined with\n\\fBNeverShared\\fP this means only one client is allowed at a time.\n.\n.TP\n.B \\-FrameRate \\fIfps\\fP\nThe maximum number of updates per second sent to each client. If the screen\nupdates any faster then those changes will be aggregated and sent in a single\nupdate to the client. Note that this only controls the maximum rate and a\nclient may get a lower rate when resources are limited. Default is \\fB60\\fP.\n.\n.TP\n.B \\-GnuTLSPriority \\fIpriority\\fP\nGnuTLS priority string that controls the TLS session’s handshake algorithms.\nSee the GnuTLS manual for possible values. Default is \\fBNORMAL\\fP.\n.\n.TP\n.B \\-IdleTimeout \\fIseconds\\fP\nThe number of seconds after which an idle VNC connection will be dropped.\nDefault is 0, which means that idle connections will never be dropped.\n.\n.TP\n.B \\-ImprovedHextile\nUse improved compression algorithm for Hextile encoding which achieves better\ncompression ratios by the cost of using slightly more CPU time.  Default is\non.\n.\n.TP\n.B \\-interface \\fIIP address\\fP\nListen on interface. By default w0vncserver listens on all available interfaces.\n.\n.TP\n.B \\-localhost\nOnly allow connections from the same machine. Useful if you use SSH and want to\nstop non-SSH connections from any other hosts.\n.\n.TP\n.B \\-Log \\fIlogname\\fP:\\fIdest\\fP:\\fIlevel\\fP[, ...]\nConfigures the debug log settings.  \\fIdest\\fP can currently be \\fBstderr\\fP,\n\\fBstdout\\fP or \\fBsyslog\\fP, and \\fIlevel\\fP is between 0 and 100, 100 meaning\nmost verbose output.  \\fIlogname\\fP is usually \\fB*\\fP meaning all, but you can\ntarget a specific source file if you know the name of its \"LogWriter\".  Default\nis \\fB*:stderr:30\\fP.\n.\n.TP\n.B \\-MaxConnectionTime \\fIseconds\\fP\nTerminate when a client has been connected for \\fIN\\fP seconds.  Default is\n0.\n.TP\n.B \\-MaxCutText \\fIbytes\\fP\nThe maximum permitted size of an incoming clipboard update.\nDefault is \\fB262144\\fP.\n.\n.\n.TP\n.B \\-MaxDisconnectionTime \\fIseconds\\fP\nTerminate when no client has been connected for \\fIN\\fP seconds.  Default is\n0.\n.\n.TP\n.B \\-MaxIdleTime \\fIseconds\\fP\nTerminate after \\fIN\\fP seconds of user inactivity.  Default is 0.\n.\n.TP\n.B \\-NeverShared\nNever treat incoming connections as shared, regardless of the client-specified\nsetting. Default is off.\n.\n.TP\n.B \\-pam_service \\fIname\\fP, \\-PAMService \\fIname\\fP\nPAM service name to use when authentication users using any of the \"Plain\"\nsecurity types. Default is \\fBvnc\\fP.\n.\n.TP\n.B \\-Password \\fIpassword\\fP\nObfuscated binary encoding of the password which clients must supply to\naccess the server.  Using this parameter is insecure, use \\fBPasswordFile\\fP\nparameter instead.\n.\n.TP\n.B \\-PasswordFile \\fIpasswd-file\\fP, \\-rfbauth \\fIpasswd-file\\fP\nPassword file for VNC authentication.  There is no default, you should\nspecify the password file explicitly.  Password file should be created with\nthe \\fBvncpasswd\\fP(1) utility.  The file is accessed each time a connection\ncomes in, so it can be changed on the fly.\n.\n.TP\n.B \\-PlainUsers \\fIuser-list\\fP\nA comma separated list of user names that are allowed to authenticate via\nany of the \"Plain\" security types (Plain, TLSPlain, etc.). Specify \\fB*\\fP\nto allow any user to authenticate using this security type. Specify \\fB%u\\fP\nto allow the user of the server process. Default is to deny all users.\n.\n.TP\n.B \\-Protocol3.3\nAlways use protocol version 3.3 for backwards compatibility with badly-behaved\nclients. Default is off.\n.\n.TP\n.B \\-QueryConnect\nPrompts the user of the desktop to explicitly accept or reject incoming\nconnections. Default is off.\n.\n.TP\n.B \\-RawKeyboard\nSend keyboard events straight through and avoid mapping them to the current\nkeyboard layout. This effectively makes the keyboard behave according to the\nlayout configured on the server instead of the layout configured on the\nclient. Default is off.\n.\n.TP\n.B \\-RemapKeys \\fImapping\nSets up a keyboard mapping.\n.I mapping\nis a comma-separated string of character mappings, each of the form\n.IR char -> char ,\nor\n.IR char <> char ,\nwhere\n.I char\nis a hexadecimal keysym. For example, to exchange the \" and @ symbols you would specify the following:\n\n.RS 10\nRemapKeys=0x22<>0x40\n.RE\n.\n.TP\n.B \\-RememberDisplayChoice \\fImode\\fP\nRemember display choice when a user connects. Can be either\n\\fBAlways\\fP, \\fBNever\\fP, or \\fBSession\\fP. Choosing \\fBNever\\fP means\na prompt dialog will be be shown every time a user connects to the\nserver. \\fBSession\\fP means a prompt will be shown only once during the\nprogram's lifetime. When choosing \\fBAlways\\fP, the choice you make will\nbe remembered and persist. To reset your choice, see\n\\fBw0vncserver-forget\\fP(1). Default is \\fBSession\\fP.\n.\n.TP\n.B \\-RequireUsername\nRequire username for the RSA-AES security types. Default is off.\n.\n.TP\n.B \\-rfbport \\fIport\\fP\nSpecifies the TCP port on which w0vncserver listens for connections from\nviewers (the protocol used in VNC is called RFB - \"remote framebuffer\").\nSpecify \\fB-1\\fP to disable listening on a TCP port. The default port is\n5900 when started directly, and -1 when activated by a systemd socket.\n.\n.TP\n.B \\-rfbunixmode \\fImode\\fP\nSpecifies the mode of the Unix domain socket.  The default is 0600.\n.\n.TP\n.B \\-rfbunixpath \\fIpath\\fP\nSpecifies the path of a Unix domain socket on which w0vncserver listens for\nconnections from viewers. Default is to not listen to any Unix domain\nsocket.\n.\n.TP\n.B \\-RSAKey \\fIpath\\fP\nPath to the RSA key for the RSA-AES security types (\\fBRA2\\fP, \\fBRA2ne\\fP,\n\\fBRA2_256\\fP and \\fBRA2ne_256\\fP) in PEM format.\n.\n.TP\n.B \\-SecurityTypes \\fIsec-types\\fP\nSpecify which security scheme to use for incoming connections.  Valid values\nare a comma separated list of \\fBNone\\fP, \\fBVncAuth\\fP, \\fBPlain\\fP,\n\\fBTLSNone\\fP, \\fBTLSVnc\\fP, \\fBTLSPlain\\fP, \\fBX509None\\fP, \\fBX509Vnc\\fP,\n\\fBX509Plain\\fP, \\fBRA2\\fP, \\fBRA2ne\\fP, \\fBRA2_256\\fP and \\fBRA2ne_256\\fP.\nDefault is \\fBTLSVnc,VncAuth\\fP.\n.\n.TP\n.B \\-SendCutText\nSend clipboard changes to clients. Default is on.\n.\n.B \\-SendPrimary\nSend the primary as well as the selection clipboard to clients. Note\nthat this does not work on all compositors. Default is on.\n.\n.TP\n.B \\-SetPrimary\nSet the primary as well as the selection clipboard. Note that this does\nnot work on all compositors. Default is on.\n.\n.TP\n.B \\-UseBlacklist\nTemporarily reject connections from a host if it repeatedly fails to\nauthenticate. Default is on.\n.\n.TP\n.B \\-UseIPv4\nUse IPv4 for incoming and outgoing connections. Default is on.\n.\n.TP\n.B \\-UseIPv6\nUse IPv6 for incoming and outgoing connections. Default is on.\n.\n.TP\n.B \\-X509Cert \\fIpath\\fP\nPath to a X509 certificate in PEM format to be used for all X509 based\nsecurity types (X509None, X509Vnc, etc.).\n.\n.TP\n.B \\-X509Key \\fIpath\\fP\nPrivate key counter part to the certificate given in \\fBX509Cert\\fP. Must\nalso be in PEM format.\n\n.SH SEE ALSO\n.BR w0vncserver-forget (1),\n.BR x0vncserver (1),\n.BR Xvnc (1),\n.BR vncpasswd (1),\n.br\nhttps://www.tigervnc.org/\n\n.SH AUTHOR\nTigerVNC Team\n\nVNC was originally developed by the RealVNC team while at Olivetti\nResearch Ltd / AT&T Laboratories Cambridge.  TightVNC additions were\nimplemented by Constantin Kaplinsky. Many other people have since\nparticipated in development, testing and support. This manual is part\nof the TigerVNC software suite.\n"
  },
  {
    "path": "unix/w0vncserver/wayland/GWaylandSource.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <map>\n\n#include <glib.h>\n\n#include <wayland-client-core.h>\n\n#include <core/LogWriter.h>\n\n#include \"objects/Display.h\"\n#include \"GWaylandSource.h\"\n\nusing namespace wayland;\n\nstatic core::LogWriter vlog(\"GWaylandSource\");\n\nstatic std::map<GSource*, GWaylandSource*> sources;\n\nGSourceFuncs GWaylandSource::sourceFuncs {\n  .prepare = [](GSource* source, int* timeout) {\n    assert(sources.count(source) != 0);\n    return sources[source]->prepare(timeout);\n  },\n  .check = [](GSource* source) {\n    assert(sources.count(source) != 0);\n    return sources[source]->check();\n  },\n  .dispatch = [](GSource* source, GSourceFunc,\n                 void*) {\n    assert(sources.count(source) != 0);\n    return sources[source]->dispatch();\n  },\n  .finalize = nullptr,\n  .closure_callback = nullptr,\n  .closure_marshal = nullptr\n};\n\nGWaylandSource::GWaylandSource(Display* display_)\n  : source(nullptr), display(display_), tag(nullptr)\n{\n  int fd;\n  GIOCondition conditions;\n\n  source = g_source_new(&sourceFuncs, sizeof(GSource));\n\n  conditions = (GIOCondition) (G_IO_IN | G_IO_HUP | G_IO_ERR);\n  fd = wl_display_get_fd(display->getDisplay());\n\n  tag = g_source_add_unix_fd(source, fd, conditions);\n  prepared = false;\n\n  sources[source] = this;\n}\n\nGWaylandSource::~GWaylandSource() {\n  sources.erase(source);\n  if (source && prepared)\n    wl_display_cancel_read(display->getDisplay());\n  if (source)\n    g_source_destroy(source);\n}\n\nvoid GWaylandSource::attach(GMainContext* context) {\n  g_source_attach(source, context);\n}\n\nint GWaylandSource::prepare(int* timeout)\n{\n  wl_display_flush(display->getDisplay());\n\n  *timeout = -1;\n\n  if (prepared)\n    return FALSE;\n\n  // We only want to call wl_display_prepare_read() once\n  prepared = true;\n\n  if (wl_display_prepare_read(display->getDisplay()) != 0) {\n    if (wl_display_dispatch_pending(display->getDisplay()) < 0) {\n      // FIXME: Stop here?\n      vlog.error(\"Failed to flush wl_display: %s\", strerror(errno));\n    }\n  }\n\n  return FALSE;\n}\n\nint GWaylandSource::check()\n{\n  return g_source_query_unix_fd(source, tag) > 0;\n}\n\nint GWaylandSource::dispatch()\n{\n  GIOCondition events;\n\n  events = g_source_query_unix_fd(source, tag);\n\n  assert(prepared);\n\n  if (events & G_IO_IN)\n    wl_display_read_events(display->getDisplay());\n  if (events & G_IO_HUP || events & G_IO_ERR)\n    wl_display_cancel_read(display->getDisplay());\n\n  wl_display_dispatch_pending(display->getDisplay());\n  prepared = false;\n\n  return G_SOURCE_CONTINUE;\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/GWaylandSource.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __G_WAYLAND_SOURCE_H__\n#define __G_WAYLAND_SOURCE_H__\n\n#include <glib.h>\n\nnamespace wayland { class Display; }\n\nclass GWaylandSource {\npublic:\n  GWaylandSource(wayland::Display* display);\n  ~GWaylandSource();\n\n  void attach(GMainContext* context);\nprivate:\n  int prepare(int* timeout);\n  int check();\n  int dispatch();\n\nprivate:\n  GSource* source;\n  wayland::Display* display;\n  void* tag;\n  bool prepared;\n  static GSourceFuncs sourceFuncs;\n};\n\n#endif // __G_WAYLAND_SOURCE_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/WaylandDesktop.cxx",
    "content": "/* Copyright 2025-2026 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <unistd.h>\n#include <sys/mman.h>\n\n#include <glib.h>\n#include <wayland-client.h>\n#include <wayland-client-core.h>\n#include <wayland-client-protocol.h>\n\n#include <core/LogWriter.h>\n#include <rfb/VNCServerST.h>\n\n#include \"../w0vncserver.h\"\n#include \"../parameters.h\"\n#include \"objects/Display.h\"\n#include \"objects/DataControl.h\"\n#include \"objects/Output.h\"\n#include \"objects/Seat.h\"\n#include \"objects/VirtualPointer.h\"\n#include \"objects/VirtualKeyboard.h\"\n#include \"GWaylandSource.h\"\n#include \"WaylandPixelBuffer.h\"\n#include \"WaylandDesktop.h\"\n\nstatic core::LogWriter vlog(\"WaylandDesktop\");\n\n#define BUTTONS 9\n\nWaylandDesktop::WaylandDesktop(GMainLoop* loop_)\n  : server(nullptr), pb(nullptr), loop(loop_), waylandSource(nullptr),\n    display(nullptr), seat(nullptr), virtualPointer(nullptr),\n    virtualKeyboard(nullptr), dataControl(nullptr)\n{\n  assert(available());\n\n  display = new wayland::Display();\n  output = new wayland::Output(display);\n  seat = new wayland::Seat(display, std::bind(&WaylandDesktop::setLEDState,\n                                              this, std::placeholders::_1));\n}\n\nWaylandDesktop::~WaylandDesktop()\n{\n  delete pb;\n  delete waylandSource;\n  delete virtualPointer;\n  delete virtualKeyboard;\n  delete seat;\n  delete output;\n  delete display;\n}\n\nvoid WaylandDesktop::init(rfb::VNCServer* vs)\n{\n  server = vs;\n}\n\nvoid WaylandDesktop::start()\n{\n  std::function<void()> desktopReadyCb = [this]() {\n    try {\n      virtualPointer = new wayland::VirtualPointer(display, seat);\n    } catch (std::exception& e) {\n      vlog.error(\"%s - pointer will be disabled\", e.what());\n    }\n    try {\n      virtualKeyboard = new wayland::VirtualKeyboard(display, seat);\n    } catch (std::exception& e) {\n      vlog.error(\"%s - keyboard will be disabled\", e.what());\n    }\n\n    if (display->interfaceAvailable(\"ext_data_control_manager_v1\")) {\n      std::function<void(bool available)> clipboardAnnounceCb = [this](bool available) {\n        server->announceClipboard(available);\n      };\n      std::function<void(const char* data)> sendClipboardData = [this](const char* data) {\n        server->sendClipboardData(data);\n      };\n      std::function<void()> clipboardRequestCb = [this]() {\n        server->requestClipboard();\n      };\n\n      dataControl = new wayland::DataControl(display, seat,\n                                             clipboardAnnounceCb,\n                                             clipboardRequestCb,\n                                             sendClipboardData);\n    } else {\n      vlog.info(\"ext-data-control-v1 not available, Clipboard disabled\");\n    }\n\n    server->setPixelBuffer(pb);\n    server->setLEDState(virtualKeyboard->getLEDState());\n  };\n\n  try {\n    pb = new WaylandPixelBuffer(display, output, seat, server, desktopReadyCb);\n  } catch (std::exception& e) {\n    vlog.error(\"Error initializing pixel buffer: %s\", e.what());\n    server->closeClients(\"Failed to start remote desktop session\");\n  }\n\n  waylandSource = new GWaylandSource(display);\n  waylandSource->attach(g_main_loop_get_context(loop));\n}\n\nvoid WaylandDesktop::stop()\n{\n  server->setPixelBuffer(nullptr);\n\n  delete virtualKeyboard;\n  virtualKeyboard = nullptr;\n\n  delete waylandSource;\n  waylandSource = nullptr;\n\n  delete virtualPointer;\n  virtualPointer = nullptr;\n\n  delete pb;\n  pb = nullptr;\n\n  delete dataControl;\n  dataControl = nullptr;\n}\n\nvoid WaylandDesktop::pointerEvent(const core::Point& pos, uint16_t buttonMask)\n{\n  if (!virtualPointer)\n    return;\n\n  virtualPointer->motionAbsolute(pos.x, pos.y, pb->width(), pb->height());\n\n  if (buttonMask == oldButtonMask)\n    return;\n\n  for (int32_t i = 0; i < BUTTONS; i++) {\n    if ((buttonMask ^ oldButtonMask) & (1 << i)) {\n      if (i > 2 && i < 7)\n        virtualPointer->axisDiscrete(i);\n      else\n        virtualPointer->button(i, buttonMask & (1 << i));\n    }\n  }\n\n  oldButtonMask = buttonMask;\n}\n\nvoid WaylandDesktop::keyEvent(uint32_t keysym, uint32_t keycode, bool down)\n{\n  if (!virtualKeyboard)\n    return;\n\n  virtualKeyboard->key(keysym, keycode, down);\n}\n\nvoid WaylandDesktop::queryConnection(network::Socket* sock,\n                                     const char* /* userName */)\n{\n  // FIXME: Implement this.\n  server->approveConnection(sock, false,\n                            \"Unable to query the local user to accept the connection.\");\n}\n\nvoid WaylandDesktop::terminate()\n{\n  kill(getpid(), SIGTERM);\n}\n\nvoid WaylandDesktop::handleClipboardRequest()\n{\n  if (!dataControl)\n    return;\n\n  dataControl->receive();\n}\n\nvoid WaylandDesktop::handleClipboardAnnounce(bool available)\n{\n  if (!dataControl)\n    return;\n\n  if (available) {\n    dataControl->setSelection();\n    if (setPrimary)\n      dataControl->setPrimarySelection();\n  } else {\n    dataControl->clearSelection();\n    if (setPrimary)\n      dataControl->clearPrimarySelection();\n  }\n}\n\nvoid WaylandDesktop::handleClipboardData(const char* data)\n{\n  if (!dataControl)\n    return;\n\n  dataControl->writePending(data);\n}\n\nbool WaylandDesktop::available()\n{\n  wayland::Display display;\n\n  // We need either wlr-screencopy OR ext-image-copy-capture\n  return (display.interfaceAvailable(\"zwlr_screencopy_manager_v1\") ||\n         (\n            display.interfaceAvailable(\"ext_image_copy_capture_manager_v1\") &&\n            display.interfaceAvailable(\"ext_output_image_capture_source_manager_v1\")\n         )) &&\n         display.interfaceAvailable(\"zwlr_virtual_pointer_manager_v1\") &&\n         display.interfaceAvailable(\"zwp_virtual_keyboard_manager_v1\");\n}\n\nvoid WaylandDesktop::setLEDState(unsigned int state)\n{\n  if (server)\n    server->setLEDState(state);\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/WaylandDesktop.h",
    "content": "/* Copyright 2025-2026 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_DESKTOP_H__\n#define __WAYLAND_DESKTOP_H__\n\n#include <glib.h>\n#include <stdint.h>\n\n#include <rfb/SDesktop.h>\n\nnamespace rfb { class VNCServer; }\n\nnamespace wayland {\n  class Output;\n  class Display;\n  class Seat;\n  class VirtualPointer;\n  class VirtualKeyboard;\n  class DataControl;\n};\n\nclass WaylandPixelBuffer;\nclass GWaylandSource;\n\nclass WaylandDesktop : public rfb::SDesktop {\npublic:\n  WaylandDesktop(GMainLoop* loop);\n  virtual ~WaylandDesktop();\n\n  // // -=- SDesktop interface\n  void init(rfb::VNCServer* vs) override;\n  void start() override;\n  virtual void stop() override;\n  virtual void keyEvent(uint32_t keysym, uint32_t keycode,\n                        bool down) override;\n  virtual void pointerEvent(const core::Point& pos,\n                            uint16_t buttonMask) override;\n  void queryConnection(network::Socket* sock,\n                        const char* userName) override;\n  void terminate() override;\n\n  virtual void handleClipboardRequest() override;\n  virtual void handleClipboardAnnounce(bool available) override;\n  virtual void handleClipboardData(const char* data) override;\n\n  // Check if necessary wayland protocols are available\n  static bool available();\n\nprivate:\n  void setLEDState(unsigned int state);\n\nprotected:\n  rfb::VNCServer* server;\n\nprivate:\n  uint16_t oldButtonMask;\n  WaylandPixelBuffer* pb;\n  GMainLoop* loop;\n  GWaylandSource* waylandSource;\n  wayland::Display* display;\n  wayland::Seat* seat;\n  wayland::Output* output;\n  wayland::VirtualPointer* virtualPointer;\n  wayland::VirtualKeyboard* virtualKeyboard;\n  wayland::DataControl* dataControl;\n};\n#endif // __WAYLAND_DESKTOP_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/WaylandPixelBuffer.cxx",
    "content": "/* Copyright 2025-2026 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <unistd.h>\n\n#include <stdexcept>\n\n#include <pixman.h>\n#include <wayland-client-core.h>\n#include <wayland-client-protocol.h>\n#include <wayland-client.h>\n\n#include <core/Region.h>\n#include <core/string.h>\n#include <core/LogWriter.h>\n#include <core/Rect.h>\n#include <rfb/VNCServerST.h>\n\n#include \"../w0vncserver.h\"\n#include \"objects/Output.h\"\n#include \"objects/Display.h\"\n#include \"objects/ScreencopyManager.h\"\n#include \"objects/ImageCaptureSource.h\"\n#include \"objects/ImageCopyCaptureManager.h\"\n#include \"WaylandPixelBuffer.h\"\n\nstatic core::LogWriter vlog(\"WaylandPixelBuffer\");\n\nWaylandPixelBuffer::WaylandPixelBuffer(wayland::Display* display,\n                                       wayland::Output* output_,\n                                       wayland::Seat* seat,\n                                       rfb::VNCServer* server_,\n                                       std::function<void()> desktopReadyCallback_)\n  : firstFrame(true), desktopReadyCallback(desktopReadyCallback_),\n    server(server_), output(output_), screencopyManager(nullptr),\n    imageCaptureSource(nullptr), imageCopyCaptureManager(nullptr),\n    resized(false)\n{\n  std::function<void(uint8_t*, core::Region, uint32_t, uint32_t)> bufferEventCb =\n    std::bind(&WaylandPixelBuffer::bufferEvent, this, std::placeholders::_1,\n              std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);\n\n  std::function<void(int, int, const core::Point&, uint32_t, uint32_t, const uint8_t*)>\n    cursorImageCb = std::bind(&WaylandPixelBuffer::cursorImageEvent, this,\n                              std::placeholders::_1, std::placeholders::_2,\n                              std::placeholders::_3, std::placeholders::_4,\n                              std::placeholders::_5, std::placeholders::_6);\n\n  std::function<void(const core::Point&)> cursorPosCb =\n    std::bind(&WaylandPixelBuffer::cursorPosEvent, this, std::placeholders::_1);\n\n  std::function<void()> stoppedCb = [this]() {\n    server->closeClients(\"The remote session stopped\");\n  };\n\n  if (display->interfaceAvailable(\"ext_image_copy_capture_manager_v1\") &&\n      display->interfaceAvailable(\"ext_output_image_capture_source_manager_v1\")) {\n    imageCaptureSource = new wayland::OutputImageCaptureSource(display, output_);\n\n    imageCopyCaptureManager = new wayland::ImageCopyCaptureManager(display,\n                                                                   imageCaptureSource,\n                                                                   seat,\n                                                                   bufferEventCb,\n                                                                   cursorImageCb,\n                                                                   cursorPosCb,\n                                                                   stoppedCb);\n    imageCopyCaptureManager->createSession();\n  } else {\n    screencopyManager = new wayland::ScreencopyManager(display, output_,\n                                                       bufferEventCb, stoppedCb);\n  }\n}\n\nWaylandPixelBuffer::~WaylandPixelBuffer()\n{\n  delete screencopyManager;\n  delete imageCopyCaptureManager;\n  delete imageCaptureSource;\n}\n\nvoid WaylandPixelBuffer::cursorImageEvent(int width, int height,\n                                          const core::Point& hotspot,\n                                          uint32_t shmFormat,\n                                          uint32_t transform,\n                                          const uint8_t* src)\n{\n  const uint8_t* cursorSrc;\n  uint8_t* cursorData;\n  uint8_t* transformedCursorData;\n\n  cursorData = nullptr;\n  transformedCursorData = nullptr;\n  cursorSrc = src;\n  try {\n    if (transform != WL_OUTPUT_TRANSFORM_NORMAL) {\n      transformedCursorData = undoTransformation(src, width, height,\n                                                 width * 4, shmFormat,\n                                                 transform);\n      cursorSrc = transformedCursorData;\n    }\n    cursorData = convertCursorBuffer(cursorSrc, shmFormat, width, height);\n    server->setCursor(width, height, hotspot, cursorData);\n  } catch (std::exception& e) {\n    vlog.error(\"Failed to set cursor: %s\", e.what());\n  }\n\n  delete [] cursorData;\n  delete [] transformedCursorData;\n}\n\nvoid WaylandPixelBuffer::cursorPosEvent(const core::Point& pos)\n{\n  server->setCursorPos(pos, true);\n}\n\nvoid WaylandPixelBuffer::bufferEvent(uint8_t* buffer, core::Region damage,\n                                     uint32_t shmFormat, uint32_t transform)\n{\n  uint32_t bufferWidth;\n  uint32_t bufferHeight;\n  bool transformed;\n  bool rotated;\n\n  bufferWidth = output->getWidth();\n  bufferHeight = output->getHeight();\n  transformed = false;\n  rotated = false;\n\n  transformed = transform != WL_OUTPUT_TRANSFORM_NORMAL;\n\n  rotated = transform == WL_OUTPUT_TRANSFORM_90 ||\n            transform == WL_OUTPUT_TRANSFORM_270 ||\n            transform == WL_OUTPUT_TRANSFORM_FLIPPED_90 ||\n            transform == WL_OUTPUT_TRANSFORM_FLIPPED_270;\n\n  if (rotated) {\n    bufferWidth = output->getHeight();\n    bufferHeight = output->getWidth();\n  }\n\n  if (bufferWidth != (uint32_t)width() || bufferHeight != (uint32_t)height()) {\n    if (!firstFrame && !resized) {\n      resized = true;\n      if (screencopyManager)\n        screencopyManager->resize();\n      return;\n    }\n  }\n\n  // We need to capture our first frame before we know which format\n  // the display is using.\n  // FIXME: Can we query the compositor instead of doing this?\n  if (firstFrame) {\n    try {\n      format = shmToRfbFormat(shmFormat);\n    } catch (std::exception& e) {\n      vlog.error(\"Failed to convert pixelformat: %s\", e.what());\n      server->closeClients(\"Failed to start remote session\");\n      return;\n    }\n\n    if (rotated)\n      setSize(output->getHeight(), output->getWidth());\n    else\n      setSize(output->getWidth(), output->getHeight());\n\n    desktopReadyCallback();\n  }\n\n  firstFrame = false;\n\n  if (transformed) {\n    try {\n      syncBuffersTransformed(buffer, damage, shmFormat, transform);\n    } catch (std::exception& e) {\n      vlog.error(\"Failed to sync transformed buffers: %s\", e.what());\n      server->closeClients(\"Error copying buffers\");\n      return;\n    }\n  } else {\n    syncBuffers(buffer, damage);\n  }\n}\n\nvoid WaylandPixelBuffer::syncBuffers(uint8_t* buffer, core::Region damage)\n{\n  int srcStride;\n  int dstStride;\n  uint8_t* srcBuffer;\n  uint8_t* dstBuffer;\n  pixman_bool_t ret;\n  core::Region region;\n  std::vector<core::Rect> rects;\n\n  if (resized) {\n    setSize(output->getWidth(), output->getHeight());\n    server->setPixelBuffer(this);\n    damage = getRect();\n    resized = false;\n  }\n\n  region = damage;\n\n  if (region.is_empty())\n    region = getRect();\n\n  srcBuffer = buffer;\n  srcStride = width();\n\n  region.get_rects(&rects);\n  for (core::Rect &rect : rects) {\n    dstBuffer = getBufferRW(getRect(), &dstStride);\n    ret = pixman_blt((uint32_t*)srcBuffer, (uint32_t*)dstBuffer,\n                     srcStride, dstStride, format.bpp, format.bpp,\n                     rect.tl.x, rect.tl.y, rect.tl.x, rect.tl.y,\n                     rect.width(), rect.height());\n    commitBufferRW(rect);\n\n    if (!ret) {\n      uint8_t* damagedBuffer;\n\n      damagedBuffer = &srcBuffer[(format.bpp / 8) *\n                                 (rect.tl.y * srcStride + rect.tl.x)];\n      imageRect(rect, damagedBuffer, srcStride);\n    }\n  }\n\n  server->add_changed(damage);\n}\n\nvoid WaylandPixelBuffer::syncBuffersTransformed(uint8_t* buffer,\n                                                core::Region damage,\n                                                uint32_t shmFormat,\n                                                uint32_t transform)\n{\n  int srcWidth;\n  int srcHeight;\n  int dstWidth;\n  int dstHeight;\n  bool wasResized;\n  core::Region region;\n  std::vector<core::Rect> rects;\n  std::vector<core::Rect> transformedRects;\n  core::Region transformedDamage;\n  bool rotated;\n  pixman_format_code_t pixmanFormat;\n  pixman_image_t* srcImg;\n\n  assert(transform != WL_OUTPUT_TRANSFORM_NORMAL);\n\n  rotated = transform == WL_OUTPUT_TRANSFORM_90 ||\n            transform == WL_OUTPUT_TRANSFORM_270 ||\n            transform == WL_OUTPUT_TRANSFORM_FLIPPED_90 ||\n            transform == WL_OUTPUT_TRANSFORM_FLIPPED_270;\n\n  wasResized = resized;\n  if (resized) {\n    if (rotated)\n      setSize(output->getHeight(), output->getWidth());\n    else\n      setSize(output->getWidth(), output->getHeight());\n    server->setPixelBuffer(this);\n    resized = false;\n  }\n\n  region = damage;\n\n  if (region.is_empty())\n    region = getRect();\n\n  dstWidth = width();\n  dstHeight = height();\n  if (rotated) {\n    srcWidth = dstHeight;\n    srcHeight = dstWidth;\n  } else {\n    srcWidth = dstWidth;\n    srcHeight = dstHeight;\n  }\n\n  region.get_rects(&rects);\n\n  if (!wasResized) {\n    // Transform the damage rects\n    for (core::Rect &rect : rects) {\n      int x;\n      int y;\n      int w;\n      int h;\n      int dx;\n      int dy;\n      int dw;\n      int dh;\n\n      x = rect.tl.x;\n      y = rect.tl.y;\n      w = rect.width();\n      h = rect.height();\n\n      switch (transform) {\n      case WL_OUTPUT_TRANSFORM_NORMAL:\n        dx = x;\n        dy = y;\n        break;\n      case WL_OUTPUT_TRANSFORM_90:\n        dx = srcHeight - y - h;\n        dy = x;\n        break;\n      case WL_OUTPUT_TRANSFORM_180:\n        dx = srcWidth - x - w;\n        dy = srcHeight - y - h;\n        break;\n      case WL_OUTPUT_TRANSFORM_270:\n        dx = y;\n        dy = srcWidth - x - w;\n        break;\n      case WL_OUTPUT_TRANSFORM_FLIPPED:\n        dx = srcWidth - x - w;\n        dy = y;\n        break;\n      case WL_OUTPUT_TRANSFORM_FLIPPED_90:\n        dx = y;\n        dy = x;\n        break;\n      case WL_OUTPUT_TRANSFORM_FLIPPED_180:\n        dx = x;\n        dy = srcHeight - y - h;\n        break;\n      case WL_OUTPUT_TRANSFORM_FLIPPED_270:\n        dx = srcHeight - y - h;\n        dy = srcWidth - x - w;\n        break;\n      default:\n        throw std::runtime_error(core::format(\"Unknown transform: %d\", transform));\n      }\n\n      if (rotated) {\n        dw = h;\n        dh = w;\n      } else {\n        dw = w;\n        dh = h;\n      }\n\n      transformedDamage.assign_union({{dx, dy, dx + dw, dy + dh}});\n    }\n  } else {\n    // Mark entire screen as dirty when we resize\n    transformedDamage = getRect();\n  }\n\n  pixmanFormat = shmToPixmanFormat(shmFormat);\n\n  srcImg = pixman_image_create_bits(pixmanFormat, srcWidth, srcHeight,\n                                   (uint32_t*)(buffer), srcWidth * 4);\n\n  transformedDamage.get_rects(&transformedRects);\n  for (core::Rect &rect : transformedRects) {\n    uint8_t* dstBuffer;\n    int dstStride;\n    pixman_image_t* dstImg;\n    pixman_transform_t inverseTransform;\n\n    dstBuffer = getBufferRW(getRect(), &dstStride);\n\n    dstImg = pixman_image_create_bits(pixmanFormat, dstWidth, dstHeight,\n                                     (uint32_t*)(dstBuffer), dstStride * 4);\n\n    inverseTransform = wlToPixmanInverseTransform(transform, srcWidth, srcHeight);\n    pixman_image_set_transform(srcImg, &inverseTransform);\n\n    pixman_image_composite32(PIXMAN_OP_SRC, srcImg, nullptr, dstImg,\n                             rect.tl.x, rect.tl.y, 0, 0, rect.tl.x,\n                             rect.tl.y, rect.width(), rect.height());\n\n    pixman_image_unref(dstImg);\n    commitBufferRW(rect);\n  }\n\n  pixman_image_unref(srcImg);\n  server->add_changed(transformedDamage);\n}\n\nuint8_t* WaylandPixelBuffer::convertCursorBuffer(const uint8_t* src,\n                                                 uint32_t shmFormat,\n                                                 uint32_t width,\n                                                 uint32_t height)\n{\n  const unsigned char* in;\n  uint8_t* out;\n  uint8_t* cursorData;\n  bool hasAlpha;\n\n  cursorData = new uint8_t[width * height * 4];\n\n  in = src;\n  out = cursorData;\n\n  hasAlpha = (shmFormat == WL_SHM_FORMAT_ARGB8888 ||\n              shmFormat == WL_SHM_FORMAT_RGBA8888 ||\n              shmFormat == WL_SHM_FORMAT_ABGR8888);\n\n  for (uint32_t y = 0; y < height; y++) {\n    for (uint32_t x = 0; x < width; x++) {\n      uint8_t r, g, b, a;\n\n      switch (shmFormat) {\n        case WL_SHM_FORMAT_ARGB8888:\n          b = in[0];\n          g = in[1];\n          r = in[2];\n          a = in[3];\n          break;\n        case WL_SHM_FORMAT_XRGB8888:\n          b = in[0];\n          g = in[1];\n          r = in[2];\n          a = 0xff;\n          break;\n        case WL_SHM_FORMAT_RGBA8888:\n          r = in[0];\n          g = in[1];\n          b = in[2];\n          a = in[3];\n          break;\n        case WL_SHM_FORMAT_RGBX8888:\n          r = in[0];\n          g = in[1];\n          b = in[2];\n          a = 0xff;\n          break;\n        case WL_SHM_FORMAT_ABGR8888:\n          a = in[0];\n          b = in[1];\n          g = in[2];\n          r = in[3];\n          break;\n        case WL_SHM_FORMAT_XBGR8888:\n          b = in[1];\n          g = in[2];\n          r = in[3];\n          a = 0xff;\n          break;\n        default:\n          throw std::runtime_error(\"Unsupported cursor format\");\n      }\n\n      if (hasAlpha) {\n        if (a == 0) {\n          r = g = b = 0;\n        } else {\n          r = (uint8_t)((uint16_t)r * 255 / a);\n          g = (uint8_t)((uint16_t)g * 255 / a);\n          b = (uint8_t)((uint16_t)b * 255 / a);\n        }\n      }\n\n      *out++ = r;\n      *out++ = g;\n      *out++ = b;\n      *out++ = a;\n\n      in += 4;\n    }\n  }\n\n  return cursorData;\n}\n\nrfb::PixelFormat WaylandPixelBuffer::shmToRfbFormat(uint32_t shmFormat)\n{\n  switch (shmFormat) {\n    case WL_SHM_FORMAT_XRGB8888:\n    case WL_SHM_FORMAT_ARGB8888:\n      return rfb::PixelFormat(32, 24, false, true, 255, 255, 255,\n                              16, 8, 0);\n    case WL_SHM_FORMAT_RGBX8888:\n    case WL_SHM_FORMAT_RGBA8888:\n      return rfb::PixelFormat(32, 24, false, true, 255, 255, 255,\n                              24, 16, 8);\n    case WL_SHM_FORMAT_XBGR8888:\n    case WL_SHM_FORMAT_ABGR8888:\n      return rfb::PixelFormat(32, 24, false, true, 255, 255, 255,\n                              0, 8, 16);\n    default:\n      throw std::runtime_error(core::format(\"format %d not supported\",\n                                            shmFormat));\n  }\n}\n\npixman_format_code_t WaylandPixelBuffer::shmToPixmanFormat(uint32_t shmFormat)\n{\n  switch (shmFormat) {\n    case WL_SHM_FORMAT_XRGB8888:\n      return PIXMAN_x8r8g8b8;\n    case WL_SHM_FORMAT_ARGB8888:\n      return PIXMAN_a8r8g8b8;\n    case WL_SHM_FORMAT_RGBX8888:\n      return PIXMAN_r8g8b8x8;\n    case WL_SHM_FORMAT_RGBA8888:\n      return PIXMAN_r8g8b8a8;\n    case WL_SHM_FORMAT_XBGR8888:\n      return PIXMAN_x8b8g8r8;\n    case WL_SHM_FORMAT_ABGR8888:\n      return PIXMAN_a8b8g8r8;\n   default:\n    throw std::runtime_error(core::format(\"format %d not supported\", shmFormat));\n  }\n}\n\nuint8_t* WaylandPixelBuffer::undoTransformation(const uint8_t* srcBuffer,\n                                                int srcWidth,\n                                                int srcHeight,\n                                                int srcStride,\n                                                uint32_t shmFormat,\n                                                uint32_t transform)\n{\n  pixman_image_t* srcImg;\n  pixman_image_t* dstImg;\n  pixman_format_code_t pixmanFormat;\n  pixman_transform_t pxTransform;\n  uint8_t* dstBuffer;\n  int dstWidth;\n  int dstHeight;\n  int dstStride;\n\n  if (transform == WL_OUTPUT_TRANSFORM_NORMAL ||\n      transform == WL_OUTPUT_TRANSFORM_FLIPPED) {\n    dstWidth = srcWidth;\n    dstHeight = srcHeight;\n  } else {\n    dstWidth = srcHeight;\n    dstHeight = srcWidth;\n  }\n\n  dstStride = dstWidth * 4;\n  dstBuffer = new uint8_t[dstHeight * dstStride];\n\n  pixmanFormat = shmToPixmanFormat(shmFormat);\n  srcImg = pixman_image_create_bits(pixmanFormat, srcWidth, srcHeight,\n                                   (uint32_t*)(srcBuffer), srcStride);\n  dstImg = pixman_image_create_bits(pixmanFormat, dstWidth, dstHeight,\n                                   (uint32_t*)(dstBuffer), dstStride);\n\n  pxTransform = wlToPixmanInverseTransform(transform, srcWidth, srcHeight);\n  pixman_image_set_transform(srcImg, &pxTransform);\n\n  pixman_image_composite32(PIXMAN_OP_SRC, srcImg, nullptr, dstImg,\n                           0, 0, 0, 0, 0, 0, dstWidth, dstHeight);\n\n  pixman_image_unref(srcImg);\n  pixman_image_unref(dstImg);\n\n  return dstBuffer;\n}\n\npixman_transform_t WaylandPixelBuffer::wlToPixmanInverseTransform(uint32_t transform,\n                                                                  int srcWidth, int srcHeight)\n{\n  pixman_fixed_t w;\n  pixman_fixed_t h;\n\n  w = srcWidth * pixman_fixed_1;\n  h = srcHeight * pixman_fixed_1;\n\n  switch (transform) {\n  case WL_OUTPUT_TRANSFORM_NORMAL:\n    return {{{pixman_fixed_1, 0, 0},\n             {0, pixman_fixed_1, 0},\n             {0, 0, pixman_fixed_1}}};\n  case WL_OUTPUT_TRANSFORM_90:\n    return {{{0, pixman_fixed_1, 0},\n             {-pixman_fixed_1, 0, h},\n             {0, 0, pixman_fixed_1}}};\n  case WL_OUTPUT_TRANSFORM_180:\n    return {{{-pixman_fixed_1, 0, w},\n             {0, -pixman_fixed_1, h},\n             {0, 0, pixman_fixed_1}}};\n  case WL_OUTPUT_TRANSFORM_270:\n    return {{{0, -pixman_fixed_1, w},\n             {pixman_fixed_1, 0, 0},\n             {0, 0, pixman_fixed_1}}};\n  case WL_OUTPUT_TRANSFORM_FLIPPED:\n    return {{{-pixman_fixed_1, 0, w},\n             {0, pixman_fixed_1, 0},\n             {0, 0, pixman_fixed_1}}};\n  case WL_OUTPUT_TRANSFORM_FLIPPED_90:\n    return {{{0, pixman_fixed_1, 0},\n             {pixman_fixed_1, 0, 0},\n             {0, 0, pixman_fixed_1}}};\n  case WL_OUTPUT_TRANSFORM_FLIPPED_180:\n    return {{{pixman_fixed_1, 0, 0},\n             {0, -pixman_fixed_1, h},\n             {0, 0, pixman_fixed_1}}};\n  case WL_OUTPUT_TRANSFORM_FLIPPED_270:\n    return {{{0, -pixman_fixed_1, w},\n             {-pixman_fixed_1, 0, h},\n             {0, 0, pixman_fixed_1}}};\n  default:\n    assert(false);\n  }\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/WaylandPixelBuffer.h",
    "content": "/* Copyright 2025-2026 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_PIXELBUFFER_H__\n#define __WAYLAND_PIXELBUFFER_H__\n\n#include <functional>\n\n#include <pixman.h>\n\n#include <rfb/PixelBuffer.h>\n\nnamespace rfb { class VNCServer; class PixelFormat; }\n\nnamespace wayland {\n  class Output;\n  class Display;\n  class ScreencopyManager;\n  class ImageCaptureSource;\n  class Seat;\n  class ImageCopyCaptureManager;\n};\n\nclass WaylandPixelBuffer : public rfb::ManagedPixelBuffer {\npublic:\n  WaylandPixelBuffer(wayland::Display* display, wayland::Output* output,\n                     wayland::Seat* seat, rfb::VNCServer* server,\n                     std::function<void()> desktopReadyCallback);\n  ~WaylandPixelBuffer();\n\nprotected:\n  // Called when there is pixel data available to read\n  void bufferEvent(uint8_t* buffer, core::Region damage, uint32_t format,\n                   uint32_t transform);\n\nprivate:\n  // Called when the cursor image is updated\n  void cursorImageEvent(int width, int height, const core::Point& hotspot,\n                        uint32_t shmFormat, uint32_t transform, const uint8_t* src);\n  // Called when the cursor position is updated\n  void cursorPosEvent(const core::Point& pos);\n\n  // Sync the shadow framebuffer to the actual framebuffer\n  void syncBuffers(uint8_t* buffer, core::Region damage);\n  void syncBuffersTransformed(uint8_t* buffer, core::Region damage, uint32_t shmFormat, uint32_t transform);\n\n  // Convert from wl_shm_format to RGB. Will un-premultiply alpha when\n  // applicable. Caller owns returned buffer\n  uint8_t* convertCursorBuffer(const uint8_t* src, uint32_t format,\n                               uint32_t width, uint32_t height);\n\n  // Convert from wl_shm_format to rfb::PixelFormat\n  rfb::PixelFormat shmToRfbFormat(uint32_t shmFormat);\n\n  // Converts a wl_shm_format to a pixman format\n  pixman_format_code_t shmToPixmanFormat(uint32_t shmFormat);\n\n  // Takes a transformed buffer and will return a new buffer that has\n  // undone the transformation\n  uint8_t* undoTransformation(const uint8_t* srcBuffer, int srcWidth, int srcHeight,\n                              int srcStride, uint32_t shmFormat,\n                              uint32_t transform);\n\n  // Returns an inverse pixman transform for the given wayland transform.\n  // The inverse transform can be used to undo the transform\n  pixman_transform_t wlToPixmanInverseTransform(uint32_t transform,\n                                                int srcWidth, int srcHeight);\n\nprivate:\n  bool firstFrame;\n  std::function<void()> desktopReadyCallback;\n  rfb::VNCServer* server;\n  wayland::Output* output;\n\n  // wlr-screencopy\n  wayland::ScreencopyManager* screencopyManager;\n\n  // ext-image-copy-capture-v1\n  wayland::ImageCaptureSource* imageCaptureSource;\n  wayland::ImageCopyCaptureManager* imageCopyCaptureManager;\n\n  bool resized;\n};\n\n#endif // __WAYLAND_PIXELBUFFER_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/DataControl.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string.h>\n#include <unistd.h>\n#include <assert.h>\n#include <fcntl.h>\n\n#include <stdexcept>\n\n#include <gio-unix-2.0/gio/gunixinputstream.h>\n#include <gio/gio.h>\n#include <ext-data-control-v1.h>\n\n#include <core/string.h>\n#include <core/LogWriter.h>\n\n#include \"../../parameters.h\"\n#include \"Display.h\"\n#include \"Seat.h\"\n#include \"DataControl.h\"\n\nusing namespace wayland;\n\nstatic const char* MIME_TEXT_PLAIN = \"text/plain\";\nstatic const char* MIME_TEXT_PLAIN_UTF8 = \"text/plain;charset=utf-8\";\n\nstatic const char* MIME_TYPES[] {\n  MIME_TEXT_PLAIN_UTF8,\n  MIME_TEXT_PLAIN,\n};\n\n/* FIXME: There is currently no way of knowing if it is us or some\n*  other application that owns the clipboard. This means we can't\n*  distinguish if a clipboard change was initiated by us, or by\n*  someone else. A workaround for now is to use a unique mime type to\n*  indicate ownership.\n*  https://gitlab.freedesktop.org/wlroots/wlr-protocols/-/issues/111\n*/\nstatic std::string tigervncMimeType = \"application/x-tigervnc-data-control-\" + std::to_string(getpid());\n\nstruct PendingData {\n  int32_t fd;\n  std::string mimeType;\n};\n\nstatic core::LogWriter vlog(\"WaylandDataControl\");\n\nconst ext_data_control_device_v1_listener DataControl::deviceListener = {\n  .data_offer = [](void* data, ext_data_control_device_v1*,\n                   ext_data_control_offer_v1* offer) {\n    ((DataControl*)data)->handleDataOffer(offer);\n  },\n  .selection = [](void* data, ext_data_control_device_v1*,\n                  ext_data_control_offer_v1* offer) {\n    ((DataControl*)data)->handleSelection(offer);\n\n  },\n  .finished = [](void* data, ext_data_control_device_v1*) {\n    ((DataControl*)data)->handleFinished();\n  },\n  .primary_selection = [](void* data, ext_data_control_device_v1*,\n                          ext_data_control_offer_v1* offer) {\n    ((DataControl*)data)->handlePrimarySelection(offer);\n  }\n};\n\nconst ext_data_control_source_v1_listener DataControl::sourceListener = {\n  .send = [](void* data, ext_data_control_source_v1*,\n             const char* mimeType, int32_t fd) {\n    ((DataControl*)data)->handleSend(mimeType, fd);\n  },\n  .cancelled = [](void* data, ext_data_control_source_v1* source) {\n    ((DataControl*)data)->handleCancelled(source);\n  }\n};\n\nconst ext_data_control_offer_v1_listener DataControl::offerListener = {\n  .offer = [](void* data, ext_data_control_offer_v1*,\n              const char* mimeType) {\n    ((DataControl*)data)->handleOffer(mimeType);\n  }\n};\n\nDataControl::DataControl(Display* display, Seat* seat,\n                         std::function<void(bool)> clipboardAnnounceCb_,\n                         std::function<void()> clipboardRequestCb_,\n                         std::function<void(const char*)> sendClipboardDataCb_)\n:  Object(display, \"ext_data_control_manager_v1\",\n          &ext_data_control_manager_v1_interface),\n   manager(nullptr), device(nullptr), lastOffer(nullptr),\n   selectionSource(nullptr), primarySource(nullptr),\n   readInProgress(false), pendingReadMimeType(nullptr),\n   readStream(nullptr), readCancellable(nullptr), readBuffer(\"\"),\n   clipboardAnnounceCb(clipboardAnnounceCb_),\n   clipboardRequestCb(clipboardRequestCb_),\n   sendClipboardDataCb(sendClipboardDataCb_)\n{\n  manager = (ext_data_control_manager_v1*)boundObject;\n  device = ext_data_control_manager_v1_get_data_device(manager, seat->getSeat());\n\n  if (!device)\n    throw std::runtime_error(\"Failed to get data device\");\n\n  ext_data_control_device_v1_add_listener(device, &deviceListener, this);\n\n  display->roundtrip();\n}\n\nDataControl::~DataControl()\n{\n  clearPendingWrites();\n\n  if (device)\n    ext_data_control_device_v1_destroy(device);\n  if (manager)\n    ext_data_control_manager_v1_destroy(manager);\n  if (selectionSource)\n    ext_data_control_source_v1_destroy(selectionSource);\n  if (primarySource)\n    ext_data_control_source_v1_destroy(primarySource);\n\n  if (readInProgress)\n    g_cancellable_cancel(readCancellable);\n\n  if (readStream)\n    g_object_unref(readStream);\n  if (readCancellable)\n    g_object_unref(readCancellable);\n\n  if (lastOffer) {\n    ext_data_control_offer_v1_destroy(lastOffer);\n    lastOffer = nullptr;\n  }\n}\n\nvoid DataControl::setSelection()\n{\n  clearPendingWrites();\n  if (readInProgress)\n    g_cancellable_cancel(readCancellable);\n\n  if (selectionSource)\n    ext_data_control_source_v1_destroy(selectionSource);\n  selectionSource = nullptr;\n\n  try {\n    selectionSource = createDataSource();\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not set selection: %s\", e.what());\n    return;\n  }\n\n  ext_data_control_device_v1_set_selection(device, selectionSource);\n}\n\nvoid DataControl::setPrimarySelection()\n{\n  clearPendingWrites();\n  if (readInProgress)\n    g_cancellable_cancel(readCancellable);\n\n  if (primarySource)\n    ext_data_control_source_v1_destroy(primarySource);\n  primarySource = nullptr;\n\n  try {\n    primarySource = createDataSource();\n  } catch (const std::exception& e) {\n    vlog.error(\"Could not set primary selection: %s\", e.what());\n    return;\n  }\n\n  ext_data_control_device_v1_set_primary_selection(device, primarySource);\n}\n\nvoid DataControl::clearSelection()\n{\n  if (selectionSource)\n    ext_data_control_source_v1_destroy(selectionSource);\n  selectionSource = nullptr;\n\n  ext_data_control_device_v1_set_selection(device, nullptr);\n\n  clearPendingWrites();\n  if (readInProgress)\n    g_cancellable_cancel(readCancellable);\n}\n\nvoid DataControl::clearPrimarySelection()\n{\n  if (primarySource)\n    ext_data_control_source_v1_destroy(primarySource);\n  primarySource = nullptr;\n\n  ext_data_control_device_v1_set_primary_selection(device, nullptr);\n\n  clearPendingWrites();\n  if (readInProgress)\n    g_cancellable_cancel(readCancellable);\n}\n\nvoid DataControl::receive()\n{\n  int pipeFd[2];\n  const char* mimeType;\n\n  // Nothing to receive\n  if (!lastOffer)\n    return;\n\n  if (readInProgress)\n    return;\n\n  mimeType = nullptr;\n  for (const char* m : MIME_TYPES) {\n    if (availableMimeTypes.find(m) != availableMimeTypes.end()) {\n      mimeType = m;\n      break;\n    }\n  }\n\n  if (!mimeType)\n    return;\n\n  if (pipe2(pipeFd, O_NONBLOCK) == -1) {\n    vlog.error(\"Failed to read clipboard data: %s\", strerror(errno));\n    return;\n  }\n\n  readInProgress = true;\n  pendingReadMimeType = mimeType;\n\n  ext_data_control_offer_v1_receive(lastOffer, mimeType, pipeFd[1]);\n  close(pipeFd[1]);\n\n  readCancellable = g_cancellable_new();\n  readStream = g_unix_input_stream_new(pipeFd[0], true);\n  readBuffer.clear();\n\n  g_input_stream_read_bytes_async(\n    readStream,\n    4096,\n    G_PRIORITY_DEFAULT,\n    readCancellable,\n    [](GObject *, GAsyncResult* res, void* userData) {\n      ((DataControl*)userData)->handleReadDataCallback(res);\n    },\n    this);\n}\n\nvoid DataControl::writePending(const char* data)\n{\n  if (!core::isValidUTF8(data)) {\n    vlog.error(\"Could not write to clipboard: invalid UTF-8\");\n    clearPendingWrites();\n    return;\n  }\n\n  while (!pendingWrites.empty()) {\n    PendingData pending;\n    const char* mimeType;\n    uint32_t fd;\n    std::string clientData;\n\n    pending = pendingWrites.front();\n    pendingWrites.pop();\n\n    mimeType = pending.mimeType.c_str();\n    fd = pending.fd;\n    if (strcmp(mimeType, MIME_TEXT_PLAIN_UTF8) == 0) {\n      clientData = data;\n    } else if (strcmp(mimeType, MIME_TEXT_PLAIN) == 0) {\n      clientData = core::utf8ToAscii(data, strlen(data));\n    } else {\n      // FIXME: This shouldn't be possible\n      vlog.error(\"Could not write to clipboard: unsupported mime type %s\", mimeType);\n      return;\n    }\n\n    if (write(fd, clientData.c_str(), clientData.size()) == -1)\n      vlog.error(\"Could not write to clipboard: %s\", strerror(errno));\n\n    close(fd);\n  }\n}\n\nvoid DataControl::handleDataOffer(ext_data_control_offer_v1* offer)\n{\n  ext_data_control_offer_v1_add_listener(offer, &offerListener, this);\n  lastOffer = offer;\n  availableMimeTypes.clear();\n\n  clearPendingWrites();\n  if (readInProgress)\n    g_cancellable_cancel(readCancellable);\n  clipboardAnnounceCb(false);\n}\n\nvoid DataControl::handleSelection(ext_data_control_offer_v1* offer)\n{\n  bool validMimeType;\n\n  if (!offer) {\n    clipboardAnnounceCb(false);\n    return;\n  }\n\n  if (offer != lastOffer) {\n    vlog.error(\"Got unexpected clipboard offer - ignoring\");\n    return;\n  }\n\n  // Ignore our own requests\n  if (availableMimeTypes.find(tigervncMimeType) != availableMimeTypes.end())\n    return;\n\n  validMimeType = false;\n  for (const char* m : MIME_TYPES) {\n    if (availableMimeTypes.find(m) != availableMimeTypes.end()) {\n      validMimeType = true;\n      break;\n    }\n  }\n\n  if (validMimeType)\n    clipboardAnnounceCb(true);\n}\n\nvoid DataControl::handlePrimarySelection(ext_data_control_offer_v1* offer)\n{\n  bool validMimeType;\n\n  if (!sendPrimary)\n    return;\n\n  if (!offer) {\n    clipboardAnnounceCb(false);\n    return;\n  }\n\n  if (offer != lastOffer) {\n    vlog.error(\"Got unexpected clipboard offer - ignoring\");\n    return;\n  }\n\n  // Ignore our own requests\n  if (availableMimeTypes.find(tigervncMimeType) != availableMimeTypes.end())\n    return;\n\n  validMimeType = false;\n  for (const char* m : MIME_TYPES) {\n    if (availableMimeTypes.find(m) != availableMimeTypes.end()) {\n      validMimeType = true;\n      break;\n    }\n  }\n\n  if (validMimeType)\n    clipboardAnnounceCb(true);\n}\n\nvoid DataControl::handleFinished()\n{\n  ext_data_control_device_v1_destroy(device);\n  device = nullptr;\n}\n\nvoid DataControl::handleSend(const char* mimeType, int32_t fd)\n{\n  bool validMimeType;\n\n  lastOffer = nullptr;\n  validMimeType = false;\n\n  for (const char* m : MIME_TYPES) {\n    if (strcmp(mimeType, m) == 0) {\n      validMimeType = true;\n      break;\n    }\n  }\n\n  // FIXME: There doesn't seem to be a way to indicate a failure properly\n  if (!validMimeType) {\n    vlog.error(\"Could not write to clipboard: unsupported mime type %s\", mimeType);\n    if (close(fd) == -1)\n      vlog.error(\"Could not write to clipboard: %s\", strerror(errno));\n    return;\n  }\n\n  pendingWrites.push({fd, mimeType});\n  clipboardRequestCb();\n}\n\nvoid DataControl::handleCancelled(ext_data_control_source_v1* source)\n{\n  ext_data_control_source_v1_destroy(source);\n  if (source == primarySource)\n    primarySource = nullptr;\n  if (source == selectionSource)\n    selectionSource = nullptr;\n}\n\nvoid DataControl::handleOffer(const char* mimeType)\n{\n  // FIXME: How do we distinguish between selection and primary?\n  availableMimeTypes.insert(mimeType);\n}\n\n// FIXME: This is identical to the Portal's\n//        Clipboard::handleReadDataCallback(). Keep in sync\nvoid DataControl::handleReadDataCallback(GAsyncResult* res)\n{\n  GError* error = nullptr;\n  GBytes* bytes;\n  size_t bytesRead;\n  size_t dataSize;\n  const char* data;\n\n  bytes = g_input_stream_read_bytes_finish(readStream, res, &error);\n\n  if (error) {\n    if (error->code == G_IO_ERROR_CANCELLED)\n      vlog.error(\"Cancelled reading clipboard data\");\n    else\n      vlog.error(\"Failed to read clipboard data: %s\", error->message);\n\n    g_error_free(error);\n    g_object_unref(readStream);\n    g_object_unref(readCancellable);\n    readStream = nullptr;\n    readCancellable = nullptr;\n    readInProgress = false;\n    return;\n  }\n\n  bytesRead = g_bytes_get_size(bytes);\n\n  // Zero is returned on EOF, we are finished reading\n  if (bytesRead == 0) {\n    std::string utf8string;\n\n    g_object_unref(readStream);\n    g_object_unref(readCancellable);\n    readStream = nullptr;\n    readCancellable = nullptr;\n    readInProgress = false;\n    g_bytes_unref(bytes);\n\n    if (strcmp(pendingReadMimeType, MIME_TEXT_PLAIN) == 0) {\n      if (!core::isValidAscii(readBuffer.c_str(), readBuffer.size())) {\n        vlog.error(\"Invalid ASCII sequence in clipboard - ignoring\");\n        readBuffer.clear();\n        readInProgress = false;\n        return;\n      }\n\n      utf8string = core::utf8ToAscii(readBuffer.c_str(), readBuffer.size());\n      readBuffer = utf8string;\n    } else if (strcmp(pendingReadMimeType, MIME_TEXT_PLAIN_UTF8) == 0) {\n      if (!core::isValidUTF8(readBuffer.c_str(), readBuffer.size())) {\n        vlog.error(\"Invalid UTF-8 sequence in clipboard - ignoring\");\n        readBuffer.clear();\n        readInProgress = false;\n        return;\n      }\n    }\n\n    sendClipboardDataCb(readBuffer.c_str());\n    readBuffer.clear();\n    return;\n  }\n\n  data = (const char*)g_bytes_get_data(bytes, &dataSize);\n\n  readBuffer.append(data, dataSize);\n  g_bytes_unref(bytes);\n\n  // While bytesRead > 0, continue reading until we reach EOF\n  g_input_stream_read_bytes_async(\n    readStream, 4096, G_PRIORITY_DEFAULT, readCancellable,\n    [](GObject*, GAsyncResult* result, void* userData) {\n      ((DataControl*)userData)->handleReadDataCallback(result);\n    }, this);\n}\n\next_data_control_source_v1* DataControl::createDataSource()\n{\n  ext_data_control_source_v1* source;\n\n  assert(manager);\n\n  source = ext_data_control_manager_v1_create_data_source(manager);\n  if (!source)\n    throw std::runtime_error(\"Failed to create data source\");\n\n  ext_data_control_source_v1_add_listener(source, &sourceListener, this);\n\n  ext_data_control_source_v1_offer(source, tigervncMimeType.c_str());\n  for (const char* mimeType : MIME_TYPES)\n    ext_data_control_source_v1_offer(source, mimeType);\n\n  return source;\n}\n\nvoid DataControl::clearPendingWrites()\n{\n  while (!pendingWrites.empty()) {\n    close(pendingWrites.front().fd);\n    pendingWrites.pop();\n  }\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/DataControl.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_DATA_CONTROL_H__\n#define __WAYLAND_DATA_CONTROL_H__\n\nstruct ext_data_control_manager_v1;\nstruct ext_data_control_device_v1;\nstruct ext_data_control_source_v1;\nstruct ext_data_control_offer_v1;\nstruct ext_data_control_device_v1_listener;\nstruct ext_data_control_source_v1_listener;\nstruct ext_data_control_offer_v1_listener;\n\n#include <functional>\n#include <string>\n#include <queue>\n#include <set>\n\n#include <gio/gio.h>\n\n#include \"Object.h\"\n\nstruct PendingData;\n\nnamespace wayland {\n  class Seat;\n\n  class DataControl : public Object {\n  public:\n    DataControl(Display* display, Seat* seat,\n                std::function<void(bool available)> clipboardAnnounceCb,\n                std::function<void()> clipboardRequestCb,\n                std::function<void(const char* data)> sendClipboardDataCb);\n    virtual ~DataControl();\n\n    // ext_data_control_device_v1 functions\n    void setSelection();\n    void setPrimarySelection();\n\n    void clearSelection();\n    void clearPrimarySelection();\n\n    // ext_data_control_offer_v1 functions\n    void receive();\n\n    // Write to all pending clipboard requests\n    void writePending(const char* data);\n\n  private:\n    // ext_data_control_device_v1 handlers\n    void handleDataOffer(ext_data_control_offer_v1* offer);\n    void handleSelection(ext_data_control_offer_v1* offer);\n    void handlePrimarySelection(ext_data_control_offer_v1* offer);\n    void handleFinished();\n\n    // ext_data_control_source_v1 handlers\n    void handleSend(const char* mimeType, int32_t fd);\n    void handleCancelled(ext_data_control_source_v1* source);\n\n    // ext_data_control_offer_v1 handlers\n    void handleOffer(const char* mimeType);\n\n    void handleReadDataCallback(GAsyncResult* res);\n\n    ext_data_control_source_v1* createDataSource();\n\n    void clearPendingWrites();\n\n  private:\n    ext_data_control_manager_v1* manager;\n    ext_data_control_device_v1* device;\n\n    // Keep track of the most recent offer\n    ext_data_control_offer_v1* lastOffer;\n\n    ext_data_control_source_v1* selectionSource;\n    ext_data_control_source_v1* primarySource;\n\n    bool readInProgress;\n    const char* pendingReadMimeType;\n    GInputStream* readStream;\n    GCancellable* readCancellable;\n    std::string readBuffer;\n\n\n    std::set<std::string> availableMimeTypes;\n    std::queue<PendingData> pendingWrites;\n\n    std::function<void(bool available)> clipboardAnnounceCb;\n    std::function<void()> clipboardRequestCb;\n    std::function<void(const char* data)> sendClipboardDataCb;\n\n    static const ext_data_control_device_v1_listener deviceListener;\n    static const ext_data_control_source_v1_listener sourceListener;\n    static const ext_data_control_offer_v1_listener offerListener;\n  };\n};\n\n#endif // __WAYLAND_DATA_CONTROL_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Display.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <string.h>\n\n#include <stdexcept>\n\n#include <wayland-client-core.h>\n#include <wayland-client-protocol.h>\n\n#include <core/string.h>\n#include <core/LogWriter.h>\n\n#include \"../../w0vncserver.h\"\n#include \"Object.h\"\n#include \"Display.h\"\n\nusing namespace wayland;\n\nstatic core::LogWriter vlog(\"WDisplay\");\n\nconst wl_registry_listener Display::listener = {\n  .global = [](void* data, wl_registry*, uint32_t name,\n               const char* interface, uint32_t version) {\n    ((Display*)data)->handleGlobalRegistry(name, interface, version);\n  },\n  .global_remove = [](void* data, wl_registry*, uint32_t name) {\n    ((Display*)data)->handleGlobalRemove(name);\n  }\n};\n\nDisplay::Display(const char* name)\n  : display(nullptr), registry(nullptr)\n{\n  display = wl_display_connect(name);\n  if (!display)\n    throw std::runtime_error(\"Failed to connect to wayland display\");\n\n  registry = wl_display_get_registry(display);\n  if (!registry) {\n    wl_display_disconnect(display);\n    throw std::runtime_error(\"Failed to get registry\");\n  }\n\n  wl_registry_add_listener(registry, &listener, this);\n  wl_display_roundtrip(display);\n}\n\nDisplay::~Display()\n{\n  wl_display_flush(display);\n  wl_registry_destroy(registry);\n  wl_display_disconnect(display);\n}\n\nbool Display::interfaceAvailable(const char* interface)\n{\n  return objects.find(interface) != objects.end();\n}\n\nvoid Display::roundtrip()\n{\n  // Display errors are fatal, the display can no longer be used\n  if (wl_display_roundtrip(display) < 0) {\n    if (wl_display_get_error(display))\n      fatal_error(\"Failed to roundtrip: %s\",\n                  strerror(wl_display_get_error(display)));\n  }\n}\n\nObjectInfo* Display::getObjectInfo(const char* interface)\n{\n  return &objects[interface];\n}\n\nvoid Display::handleGlobalRegistry(uint32_t name,\n                                    const char* interface,\n                                    uint32_t version)\n{\n  objects[interface] = { name, version };\n}\n\nvoid Display::handleGlobalRemove(uint32_t name)\n{\n  vlog.debug(\"Removing global: %d\", name);\n\n  for (auto it = objects.begin(); it != objects.end(); ++it) {\n    if (it->second.name == name) {\n      objects.erase(it);\n      break;\n    }\n  }\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Display.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_DISPLAY_H__\n#define __WAYLAND_DISPLAY_H__\n\n#include <stdint.h>\n\n#include <string>\n#include <map>\n\nstruct wl_display;\nstruct wl_registry;\nstruct wl_registry_listener;\n\nnamespace wayland {\n  struct ObjectInfo {\n    uint32_t name;\n    uint32_t version;\n  };\n\n  class Display {\n  public:\n    Display(const char* name = nullptr);\n    ~Display();\n\n    bool interfaceAvailable(const char* interface);\n    void roundtrip();\n\n    wl_display* getDisplay() const { return display; }\n    wl_registry* getRegistry() const { return registry; }\n    ObjectInfo* getObjectInfo(const char* interface);\n\n  private:\n    void handleGlobalRegistry(uint32_t name, const char *interface,\n                              uint32_t version);\n    void handleGlobalRemove(uint32_t name);\n\n  private:\n    wl_display* display;\n    wl_registry* registry;\n    static const struct wl_registry_listener listener;\n    std::map<std::string, ObjectInfo> objects;\n  };\n};\n\n#endif // __WAYLAND_DISPLAY_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ImageCaptureSource.cxx",
    "content": "/* Copyright 2026 Tobias Fahleson for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdexcept>\n\n#include <ext-image-capture-source-v1.h>\n\n#include <core/LogWriter.h>\n\n#include \"Display.h\"\n#include \"Output.h\"\n#include \"ImageCaptureSource.h\"\n\nusing namespace wayland;\n\nstatic core::LogWriter vlog(\"WaylandImageCaptureSource\");\n\nImageCaptureSource::~ImageCaptureSource()\n{\n  if (source)\n    ext_image_capture_source_v1_destroy(source);\n}\n\nOutputImageCaptureSource::OutputImageCaptureSource(Display* display,\n                                                   Output* output)\n  : Object(display, \"ext_output_image_capture_source_manager_v1\",\n           &ext_output_image_capture_source_manager_v1_interface)\n{\n  manager = (ext_output_image_capture_source_manager_v1*)boundObject;\n  source = ext_output_image_capture_source_manager_v1_create_source(manager, output->getOutput());\n  if (!source) {\n    ext_output_image_capture_source_manager_v1_destroy(manager);\n    throw std::runtime_error(\"Failed to create capture source\");\n  }\n}\n\nOutputImageCaptureSource::~OutputImageCaptureSource()\n{\n  if (manager)\n    ext_output_image_capture_source_manager_v1_destroy(manager);\n}\n\n// FIXME: Create a ext_foreign_toplevel_handle_v1 object wrapper\nForeignToplevelImageCaptureSource::ForeignToplevelImageCaptureSource(Display* display_,\n                                                                     ext_foreign_toplevel_handle_v1* toplevel)\n  : Object(display_, \"ext_foreign_toplevel_image_capture_source_manager_v1\",\n           &ext_foreign_toplevel_image_capture_source_manager_v1_interface),\n    manager(nullptr)\n{\n  manager = (ext_foreign_toplevel_image_capture_source_manager_v1*)boundObject;\n  source = ext_foreign_toplevel_image_capture_source_manager_v1_create_source(manager, toplevel);\n  if (!source) {\n    ext_foreign_toplevel_image_capture_source_manager_v1_destroy(manager);\n    throw std::runtime_error(\"Failed to create capture source\");\n  }\n}\n\nForeignToplevelImageCaptureSource::~ForeignToplevelImageCaptureSource()\n{\n  if (manager)\n    ext_foreign_toplevel_image_capture_source_manager_v1_destroy(manager);\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ImageCaptureSource.h",
    "content": "/* Copyright 2026 Tobias Fahleson for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_IMAGE_CAPTURE_SOURCE_H__\n#define __WAYLAND_IMAGE_CAPTURE_SOURCE_H__\n\n#include \"Object.h\"\n\nstruct ext_foreign_toplevel_handle_v1;\nstruct ext_image_capture_source_v1;\nstruct ext_output_image_capture_source_manager_v1;\nstruct ext_foreign_toplevel_image_capture_source_manager_v1;\n\nnamespace wayland {\n  class Display;\n  class Output;\n\n  class ImageCaptureSource {\n  protected:\n    ImageCaptureSource() {};\n  public:\n    virtual ~ImageCaptureSource();\n\n    ext_image_capture_source_v1* getSource() { return source; }\n\n  protected:\n    ext_image_capture_source_v1* source;\n  };\n\n  class OutputImageCaptureSource : public Object,\n                                   public ImageCaptureSource {\n  public:\n    OutputImageCaptureSource(Display* display, Output* output);\n    ~OutputImageCaptureSource();\n\n  private:\n    ext_output_image_capture_source_manager_v1* manager;\n  };\n\n  class ForeignToplevelImageCaptureSource : public Object,\n                                            public ImageCaptureSource {\n  public:\n    ForeignToplevelImageCaptureSource(Display* display,\n                                      ext_foreign_toplevel_handle_v1* toplevel);\n    ~ForeignToplevelImageCaptureSource();\n\n  private:\n    ext_foreign_toplevel_image_capture_source_manager_v1* manager;\n  };\n};\n\n#endif // __WAYLAND_IMAGE_CAPTURE_SOURCE_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ImageCopyCaptureCursorSession.cxx",
    "content": "/* Copyright 2026 Tobias Fahleson for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdexcept>\n\n#include <ext-image-copy-capture-v1.h>\n\n#include <core/LogWriter.h>\n#include <core/Rect.h>\n\n#include \"ImageCopyCaptureSession.h\"\n#include \"ImageCopyCaptureCursorSession.h\"\n\nusing namespace wayland;\n\nstatic core::LogWriter vlog(\"WaylandImageCopyCaptureCursorSession\");\n\nconst ext_image_copy_capture_cursor_session_v1_listener\nImageCopyCaptureCursorSession::listener = {\n  .enter = [](void* data, ext_image_copy_capture_cursor_session_v1*) {\n    ((ImageCopyCaptureCursorSession*)data)->handleEnter();\n  },\n  .leave = [](void* data, ext_image_copy_capture_cursor_session_v1*) {\n    ((ImageCopyCaptureCursorSession*)data)->handleLeave();\n  },\n  .position = [](void* data, ext_image_copy_capture_cursor_session_v1*,\n                 int32_t x, int32_t y) {\n    ((ImageCopyCaptureCursorSession*)data)->handlePosition(x, y);\n  },\n  .hotspot = [](void* data, ext_image_copy_capture_cursor_session_v1*,\n                int32_t x, int32_t y) {\n    ((ImageCopyCaptureCursorSession*)data)->handleHotspot(x, y);\n  },\n};\n\nImageCopyCaptureCursorSession::ImageCopyCaptureCursorSession(Display* display_,\n                                                             ext_image_copy_capture_cursor_session_v1* session_,\n                                                             std::function<void(int, int, const core::Point&, uint32_t, uint32_t, const uint8_t*)>\n                                                               cursorFrameCb_,\n                                                             std::function<void(const core::Point&)>\n                                                               cursorPosCb_,\n                                                             std::function<void()>\n                                                               stoppedCb_)\n  : session(session_), captureSession(nullptr),\n    cursorFrameCb(cursorFrameCb_), cursorPosCb(cursorPosCb_),\n    hotspot({0, 0})\n{\n  ext_image_copy_capture_cursor_session_v1_add_listener(session, &listener, this);\n\n  ext_image_copy_capture_session_v1* captureSessionHandle =\n    ext_image_copy_capture_cursor_session_v1_get_capture_session(session);\n\n  if (!captureSessionHandle) {\n    ext_image_copy_capture_cursor_session_v1_destroy(session);\n    throw std::runtime_error(\"Could not create cursor capture session\");\n  }\n\n  std::function<void(uint8_t*, core::Region, uint32_t, uint32_t)> bufferEventCb =\n    [this](uint8_t*, core::Region, uint32_t, uint32_t) {\n      cursorFrameCb(captureSession->getWidth(),\n                    captureSession->getHeight(),\n                    hotspot, captureSession->getFormat(),\n                    captureSession->getTransform(),\n                    captureSession->getBufferData());\n  };\n\n  captureSession = new ImageCopyCaptureSession(display_,\n                                               captureSessionHandle,\n                                               bufferEventCb,\n                                               stoppedCb_);\n}\n\nImageCopyCaptureCursorSession::~ImageCopyCaptureCursorSession()\n{\n  delete captureSession;\n  if (session)\n    ext_image_copy_capture_cursor_session_v1_destroy(session);\n}\n\nvoid ImageCopyCaptureCursorSession::handleEnter()\n{\n}\n\nvoid ImageCopyCaptureCursorSession::handleLeave()\n{\n}\n\nvoid ImageCopyCaptureCursorSession::handlePosition(int32_t x, int32_t y)\n{\n  cursorPosCb({x, y});\n}\n\nvoid ImageCopyCaptureCursorSession::handleHotspot(int32_t x, int32_t y)\n{\n  hotspot = {x, y};\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ImageCopyCaptureCursorSession.h",
    "content": "/* Copyright 2026 Tobias Fahleson for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_IMAGE_COPY_CAPTURE_CURSOR_SESSION_H__\n#define __WAYLAND_IMAGE_COPY_CAPTURE_CURSOR_SESSION_H__\n\n#include <functional>\n\n#include <core/Rect.h>\n\n#include \"Object.h\"\n\nstruct ext_image_copy_capture_cursor_session_v1;\nstruct ext_image_copy_capture_cursor_session_v1_listener;\n\nnamespace wayland {\n  class Display;\n  class ImageCopyCaptureSession;\n\n  class ImageCopyCaptureCursorSession {\n  public:\n    ImageCopyCaptureCursorSession(Display* display,\n                                  ext_image_copy_capture_cursor_session_v1* session,\n                                  std::function<void(int, int, const core::Point&, uint32_t, uint32_t, const uint8_t*)>\n                                    cursorFrameCb,\n                                  std::function<void(const core::Point&)> cursorPosCb,\n                                  std::function<void()> stoppedCb);\n    ~ImageCopyCaptureCursorSession();\n\n  private:\n    void handleEnter();\n    void handleLeave();\n    void handlePosition(int32_t x, int32_t y);\n    void handleHotspot(int32_t x, int32_t y);\n\n  private:\n    ext_image_copy_capture_cursor_session_v1* session;\n    ImageCopyCaptureSession* captureSession;\n    std::function<void(int, int, const core::Point&, uint32_t, uint32_t, const uint8_t*)> cursorFrameCb;\n    std::function<void(const core::Point&)> cursorPosCb;\n    core::Point hotspot;\n    static const ext_image_copy_capture_cursor_session_v1_listener listener;\n  };\n};\n\n#endif // __WAYLAND_IMAGE_COPY_CAPTURE_CURSOR_SESSION_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ImageCopyCaptureManager.cxx",
    "content": "/* Copyright 2026 Tobias Fahleson for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdexcept>\n\n#include <ext-image-copy-capture-v1.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include \"Display.h\"\n#include \"Pointer.h\"\n#include \"Seat.h\"\n#include \"ImageCaptureSource.h\"\n#include \"ImageCopyCaptureSession.h\"\n#include \"ImageCopyCaptureCursorSession.h\"\n#include \"ImageCopyCaptureManager.h\"\n\nusing namespace wayland;\n\nstatic core::LogWriter vlog(\"WaylandImageCopyCaptureManager\");\n\nImageCopyCaptureManager::ImageCopyCaptureManager(Display* display_,\n                                                 ImageCaptureSource* source_,\n                                                 Seat* seat_,\n                                                 std::function<void(uint8_t*, core::Region, uint32_t, uint32_t)>\n                                                   bufferEventCb_,\n                                                 std::function<void(int, int, const core::Point&, uint32_t, uint32_t, const uint8_t*)>\n                                                   cursorImageCb_,\n                                                 std::function<void(const core::Point&)>\n                                                   cursorPosCb_,\n                                                 std::function<void()>\n                                                   stoppedCb_)\n  : Object(display_, \"ext_image_copy_capture_manager_v1\",\n           &ext_image_copy_capture_manager_v1_interface),\n    manager(nullptr), display(display_), source(source_),\n    session(nullptr), seat(seat_), cursorSession(nullptr),\n    bufferEventCb(bufferEventCb_), cursorImageCb(cursorImageCb_),\n    cursorPosCb(cursorPosCb_), stoppedCb(stoppedCb_)\n{\n  manager = (ext_image_copy_capture_manager_v1*)boundObject;\n}\n\nImageCopyCaptureManager::~ImageCopyCaptureManager()\n{\n  delete cursorSession;\n  delete session;\n  if (manager)\n    ext_image_copy_capture_manager_v1_destroy(manager);\n}\n\nvoid ImageCopyCaptureManager::createSession()\n{\n  ext_image_copy_capture_session_v1* sessionHandle;\n  ext_image_copy_capture_cursor_session_v1* cursorSessionHandle;\n  Pointer* pointer;\n\n  sessionHandle =\n    ext_image_copy_capture_manager_v1_create_session(manager, source->getSource(), 0);\n  if (!sessionHandle)\n    throw std::runtime_error(\"Unable to create image copy capture session\");\n\n  session = new ImageCopyCaptureSession(display, sessionHandle,\n                                        bufferEventCb, stoppedCb);\n\n  pointer = seat->getPointer();\n  // FIXME: Make it possible to re-enable this if a cursor is added in\n  // the future like we do in VirtualKeyboard\n  if (!pointer) {\n    vlog.error(\"Unable to create cursor capture session: no pointer found - cursor will be invisible\");\n    return;\n  }\n\n  cursorSessionHandle =\n    ext_image_copy_capture_manager_v1_create_pointer_cursor_session(manager,\n                                                                    source->getSource(),\n                                                                    pointer->getPointer());\n  if (!cursorSessionHandle) {\n    vlog.error(\"Unable to create image copy capture session - cursor will be invisible\");\n    return;\n  }\n\n  cursorSession = new ImageCopyCaptureCursorSession(display,\n                                                    cursorSessionHandle,\n                                                    cursorImageCb,\n                                                    cursorPosCb,\n                                                    stoppedCb);\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ImageCopyCaptureManager.h",
    "content": "/* Copyright 2026 Tobias Fahleson for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_IMAGE_COPY_CAPTURE_MANAGER_H__\n#define __WAYLAND_IMAGE_COPY_CAPTURE_MANAGER_H__\n\n#include <functional>\n\n#include \"Object.h\"\n\nstruct ext_image_copy_capture_manager_v1;\n\nnamespace core { class Region; struct Point; }\n\nnamespace wayland {\n  class Display;\n  class Seat;\n\n  class ImageCaptureSource;\n  class ImageCopyCaptureSession;\n  class ImageCopyCaptureCursorSession;\n\n  class ImageCopyCaptureManager : public Object {\n  public:\n    ImageCopyCaptureManager(Display* display,\n                            ImageCaptureSource* source,\n                            Seat* seat,\n                            std::function<void(uint8_t*, core::Region, uint32_t, uint32_t)>\n                              bufferEventCb,\n                            std::function<void(int, int, const core::Point&, uint32_t, uint32_t, const uint8_t*)>\n                              cursorImageCb,\n                            std::function<void(const core::Point&)> cursorPosCb,\n                            std::function<void()> stoppedCb);\n    ~ImageCopyCaptureManager();\n\n    void createSession();\n\n  private:\n    ext_image_copy_capture_manager_v1* manager;\n    Display* display;\n    ImageCaptureSource* source;\n    ImageCopyCaptureSession* session;\n    Seat* seat;\n    ImageCopyCaptureCursorSession* cursorSession;\n    std::function<void(uint8_t*, core::Region, uint32_t, uint32_t)> bufferEventCb;\n    std::function<void(int, int, const core::Point&, uint32_t, uint32_t, const uint8_t*)> cursorImageCb;\n    std::function<void(const core::Point&)> cursorPosCb;\n    std::function<void()> stoppedCb;\n  };\n\n};\n\n#endif // __WAYLAND_IMAGE_COPY_CAPTURE_MANAGER_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ImageCopyCaptureSession.cxx",
    "content": "/* Copyright 2026 Tobias Fahleson for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <unistd.h>\n#include <sys/mman.h>\n#include <fcntl.h>\n#include <string.h>\n\n#include <stdexcept>\n\n#include <ext-image-copy-capture-v1.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include \"Shm.h\"\n#include \"ShmPool.h\"\n\n#include \"ImageCaptureSource.h\"\n#include \"ImageCopyCaptureSession.h\"\n\nusing namespace wayland;\n\nstatic core::LogWriter vlog(\"WaylandImageCopyCaptureSession\");\n\n// Preferred pixel formats, in prioritized order\n// FIXME: We probably prefer XRGB8888 in most cases, but we should try\n//        to respect whatever the client has requested if the compositor\n//        also supports it.\nstatic std::vector<uint32_t> preferredFormats = {\n  WL_SHM_FORMAT_XRGB8888,\n  WL_SHM_FORMAT_ARGB8888,\n  WL_SHM_FORMAT_RGBX8888,\n  WL_SHM_FORMAT_RGBA8888,\n  WL_SHM_FORMAT_XBGR8888,\n  WL_SHM_FORMAT_ABGR8888,\n};\n\nconst ext_image_copy_capture_session_v1_listener ImageCopyCaptureSession::listener = {\n  .buffer_size = [](void* data, ext_image_copy_capture_session_v1*,\n                    uint32_t width, uint32_t height) {\n    ((ImageCopyCaptureSession*)data)->handleBufferSize(width, height);\n  },\n  .shm_format = [](void* data, ext_image_copy_capture_session_v1*, uint32_t format) {\n    ((ImageCopyCaptureSession*)data)->handleShmFormat(format);\n  },\n  .dmabuf_device = [](void* data, ext_image_copy_capture_session_v1*, wl_array* device) {\n    ((ImageCopyCaptureSession*)data)->handleDmabufDevice(device);\n  },\n  .dmabuf_format = [](void* data, ext_image_copy_capture_session_v1*,\n                      uint32_t format, wl_array* modifiers) {\n    ((ImageCopyCaptureSession*)data)->handleDmabufFormat(format, modifiers);\n  },\n  .done = [](void* data, ext_image_copy_capture_session_v1*) {\n    ((ImageCopyCaptureSession*)data)->handleDone();\n  },\n  .stopped = [](void* data, ext_image_copy_capture_session_v1*) {\n    ((ImageCopyCaptureSession*)data)->handleStopped();\n  },\n};\n\nconst ext_image_copy_capture_frame_v1_listener ImageCopyCaptureSession::frameListener = {\n  .transform = [](void* data, ext_image_copy_capture_frame_v1*, uint32_t transform) {\n    ((ImageCopyCaptureSession*)data)->handleFrameTransform(transform);\n  },\n  .damage = [](void* data, ext_image_copy_capture_frame_v1*,\n               int32_t x, int32_t y, int32_t width, int32_t height) {\n    ((ImageCopyCaptureSession*)data)->handleFrameDamage(x, y, width, height);\n  },\n  .presentation_time = [](void* data, ext_image_copy_capture_frame_v1*,\n                          uint32_t tvSecHi, uint32_t tvSecLo, uint32_t tvNsec) {\n    ((ImageCopyCaptureSession*)data)->handleFramePresentationTime(tvSecHi, tvSecLo, tvNsec);\n  },\n  .ready = [](void* data, ext_image_copy_capture_frame_v1*) {\n    ((ImageCopyCaptureSession*)data)->handleFrameReady();\n  },\n  .failed = [](void* data, ext_image_copy_capture_frame_v1*, uint32_t reason) {\n    ((ImageCopyCaptureSession*)data)->handleFrameFailed(reason);\n  },\n};\n\n\nImageCopyCaptureSession::ImageCopyCaptureSession(Display* display_,\n                                                 ext_image_copy_capture_session_v1* session_,\n                                                 std::function<void(uint8_t*, core::Region, uint32_t, uint32_t)>\n                                                   bufferEventCb_,\n                                                 std::function<void()>\n                                                   stoppedCb_)\n  : display(display_), bufferEventCb(bufferEventCb_), session(session_),\n    frame(nullptr), shm(nullptr), pool(nullptr), buffer(nullptr),\n    firstCapture(true), width(0), height(0), transform(0),\n    stoppedCb(stoppedCb_)\n{\n  ext_image_copy_capture_session_v1_add_listener(session, &listener, this);\n}\n\nImageCopyCaptureSession::~ImageCopyCaptureSession()\n{\n  if (frame)\n    ext_image_copy_capture_frame_v1_destroy(frame);\n  if (buffer)\n    wl_buffer_destroy(buffer);\n\n  ext_image_copy_capture_session_v1_destroy(session);\n\n  delete pool;\n  delete shm;\n}\n\nuint8_t* ImageCopyCaptureSession::getBufferData() const\n{\n  assert(pool);\n\n  return pool->getData();\n}\n\nvoid ImageCopyCaptureSession::handleBufferSize(uint32_t width_,\n                                               uint32_t height_)\n{\n  width = width_;\n  height = height_;\n}\n\nvoid ImageCopyCaptureSession::handleShmFormat(uint32_t format_)\n{\n  formatsPending.push_back((uint32_t)format_);\n\n}\n\nvoid ImageCopyCaptureSession::handleDmabufDevice(wl_array* /* device */)\n{\n}\n\nvoid ImageCopyCaptureSession::handleDmabufFormat(uint32_t /* format */,\n                                                 wl_array* /* modifiers */)\n{\n}\n\nvoid ImageCopyCaptureSession::handleDone()\n{\n  size_t size;\n  int fd;\n\n  cleanupBuffers();\n\n  assert(!shm);\n  assert(!pool);\n  assert(!buffer);\n\n  if (formatsPending.empty()) {\n    vlog.error(\"No shm formats available\");\n    stoppedCb();\n    return;\n  }\n\n  // Ensure formats doesn't change during execution\n  formats = formatsPending;\n  formatsPending.clear();\n\n  try {\n    format = preferredFormat();\n  } catch (std::exception& e) {\n    vlog.error(\"Failed to pick shm format: %s\", e.what());\n    stoppedCb();\n    return;\n  }\n\n  fd = memfd_create(\"w0vncserver-image-copy-shm\", FD_CLOEXEC);\n  if (fd < 0) {\n    vlog.error(\"Failed to allocate shm: %s\", strerror(errno));\n    stoppedCb();\n    return;\n  }\n\n  size = width * height * 4;\n  if (ftruncate(fd, size) < 0) {\n    vlog.error(\"Failed to truncate shm: %s\", strerror(errno));\n    close(fd);\n    return;\n  }\n\n  try {\n    shm = new Shm(display);\n    pool = new ShmPool(shm, fd, size);\n  } catch (std::exception& e) {\n    vlog.error(\"Failed to create shm pool: %s\", e.what());\n    close(fd);\n    stoppedCb();\n    return;\n  }\n\n  close(fd);\n\n  buffer = pool->createBuffer(0, width, height, width * 4, format);\n  if (!buffer) {\n    vlog.error(\"Failed to create buffer\");\n    stoppedCb();\n    return;\n  }\n\n  createFrame();\n}\n\nvoid ImageCopyCaptureSession::handleStopped()\n{\n  vlog.status(\"Capture session stopped\");\n\n  if (frame) {\n    ext_image_copy_capture_frame_v1_destroy(frame);\n    frame = nullptr;\n  }\n\n  ext_image_copy_capture_session_v1_destroy(session);\n  session = nullptr;\n\n  stoppedCb();\n}\n\nvoid ImageCopyCaptureSession::handleFrameTransform(uint32_t transform_)\n{\n  transform = transform_;\n}\n\nvoid ImageCopyCaptureSession::handleFrameDamage(int32_t x, int32_t y,\n                                                int32_t width_,\n                                                int32_t height_)\n{\n  core::Point tl{static_cast<int>(x), static_cast<int>(y)};\n  core::Point br{static_cast<int>(x + width_),\n                 static_cast<int>(y + height_)};\n  damage.assign_union({{tl, br}});\n}\n\nvoid ImageCopyCaptureSession::handleFramePresentationTime(uint32_t /* tvSecHi */,\n                                                          uint32_t /* tvSecLo */,\n                                                          uint32_t /* tvNsec */)\n{\n}\n\nvoid ImageCopyCaptureSession::handleFrameReady()\n{\n  assert(frame);\n\n  bufferEventCb(pool->getData(), damage, format, transform);\n\n  ext_image_copy_capture_frame_v1_destroy(frame);\n  frame = nullptr;\n\n  createFrame();\n}\n\nvoid ImageCopyCaptureSession::handleFrameFailed(uint32_t reason)\n{\n  if (frame) {\n    ext_image_copy_capture_frame_v1_destroy(frame);\n    frame = nullptr;\n  }\n\n  if (reason == EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_UNKNOWN) {\n    vlog.error(\"Could not capture frame: unknown reason - trying again\");\n    createFrame();\n  } else if (reason == EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_BUFFER_CONSTRAINTS) {\n    // FIXME: The specification says that we should re-allocate our\n    // buffers and try again. Not sure if that is the right thing to do.\n    // For now, just stop the capture.\n    vlog.error(\"Invalid buffer constraints, stopping capture session\");\n    stoppedCb();\n  } else if (reason == EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_STOPPED) {\n    vlog.error(\"Could not capture frame, stopping capture session\");\n    stoppedCb();\n  } else {\n    vlog.error(\"Could not capture frame: invalid failure reason %d\", reason);\n    stoppedCb();\n  }\n}\n\nvoid ImageCopyCaptureSession::createFrame()\n{\n  assert(frame == nullptr);\n\n  frame = ext_image_copy_capture_session_v1_create_frame(session);\n  ext_image_copy_capture_frame_v1_add_listener(frame, &frameListener, this);\n\n  damage.clear();\n\n  // The first time a buffer is captured, we need to damage the entire buffer\n  if (firstCapture) {\n    ext_image_copy_capture_frame_v1_damage_buffer(frame, 0, 0, width, height);\n    firstCapture = false;\n  }\n\n  ext_image_copy_capture_frame_v1_attach_buffer(frame, buffer);\n  ext_image_copy_capture_frame_v1_capture(frame);\n}\n\nvoid ImageCopyCaptureSession::cleanupBuffers()\n{\n  if (frame)\n    ext_image_copy_capture_frame_v1_destroy(frame);\n\n  if (buffer)\n    wl_buffer_destroy(buffer);\n\n  frame = nullptr;\n  buffer = nullptr;\n  firstCapture = true;\n\n  delete pool;\n  pool = nullptr;\n\n  delete shm;\n  shm = nullptr;\n\n  formats.clear();\n  damage.clear();\n}\n\nuint32_t ImageCopyCaptureSession::preferredFormat()\n{\n  for (uint32_t shmFormat : preferredFormats) {\n    if (std::find(formats.begin(), formats.end(), shmFormat) != formats.end())\n      return shmFormat;\n  }\n\n  throw std::runtime_error(\"No supported shm format found\");\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ImageCopyCaptureSession.h",
    "content": "/* Copyright 2026 Tobias Fahleson for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_IMAGE_COPY_CAPTURE_SESSION_H__\n#define __WAYLAND_IMAGE_COPY_CAPTURE_SESSION_H__\n\n#include <functional>\n#include <vector>\n\n#include <core/Region.h>\n\n#include \"Object.h\"\n\nstruct wl_array;\nstruct wl_buffer;\n\nstruct ext_image_copy_capture_session_v1;\nstruct ext_image_copy_capture_frame_v1;\nstruct ext_image_copy_capture_session_v1_listener;\nstruct ext_image_copy_capture_frame_v1_listener;\n\nnamespace wayland {\n  class Display;\n  class Shm;\n  class ShmPool;\n\n  class ImageCopyCaptureSession {\n  public:\n    ImageCopyCaptureSession(Display* display,\n                            ext_image_copy_capture_session_v1* session,\n                            std::function<void(uint8_t*, core::Region, uint32_t, uint32_t)>\n                              bufferEventCb,\n                            std::function<void()> stoppedCb);\n    ~ImageCopyCaptureSession();\n\n    uint8_t* getBufferData() const;\n    uint32_t getWidth() const { return width; }\n    uint32_t getHeight() const { return height; }\n    uint32_t getFormat() const { return format; }\n    uint32_t getTransform() const { return transform; }\n\n  private:\n    void handleBufferSize(uint32_t width, uint32_t height);\n    void handleShmFormat(uint32_t format);\n    void handleDmabufDevice(wl_array* device);\n    void handleDmabufFormat(uint32_t format, wl_array* modifiers);\n    void handleDone();\n    void handleStopped();\n    void handleFrameTransform(uint32_t transform);\n    void handleFrameDamage(int32_t x, int32_t y, int32_t width,\n                           int32_t height);\n    void handleFramePresentationTime(uint32_t tvSecHi, uint32_t tvSecLo,\n                                     uint32_t tvNsec);\n    void handleFrameReady();\n    void handleFrameFailed(uint32_t reason);\n\n    void createFrame();\n    void cleanupBuffers();\n\n    uint32_t preferredFormat();\n\n  private:\n    Display* display;\n    std::function<void(uint8_t*, core::Region, uint32_t, uint32_t)> bufferEventCb;\n    ext_image_copy_capture_session_v1* session;\n    ext_image_copy_capture_frame_v1* frame;\n    Shm* shm;\n    ShmPool* pool;\n    wl_buffer* buffer;\n    bool firstCapture;\n    uint32_t width;\n    uint32_t height;\n    uint32_t format;\n    uint32_t transform;\n    std::function<void()> stoppedCb;\n    std::vector<uint32_t> formatsPending;\n    std::vector<uint32_t> formats;\n    core::Region damage;\n    static const ext_image_copy_capture_session_v1_listener listener;\n    static const ext_image_copy_capture_frame_v1_listener frameListener;\n  };\n\n};\n\n#endif // __WAYLAND_IMAGE_COPY_CAPTURE_SESSION_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Keyboard.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <sys/mman.h>\n\n#include <string.h>\n\n#include <xkbcommon/xkbcommon.h>\n#include <wayland-client-protocol.h>\n\n#include <core/LogWriter.h>\n#include <rfb/ledStates.h>\n\n#include \"../../w0vncserver.h\"\n#include \"Display.h\"\n#include \"Seat.h\"\n#include \"Keyboard.h\"\n\nusing namespace wayland;\n\nextern const unsigned int code_map_xkb_to_qnum_len;\nextern const struct _code_map_xkb_to_qnum {\n  const char* from;\n  const unsigned short to;\n} code_map_xkb_to_qnum[];\n\nstatic core::LogWriter vlog(\"Keyboard\");\n\nconst wl_keyboard_listener Keyboard::listener = {\n  .keymap = [](void* data, wl_keyboard*, uint32_t format,\n               int32_t fd, uint32_t size) {\n    ((Keyboard*)data)->handleKeyMap(format, fd, size);\n  },\n  .enter = [](void*, wl_keyboard*, uint32_t, wl_surface*,\n              wl_array*) {},\n  .leave = [](void*, wl_keyboard*, uint32_t, wl_surface*) {},\n  .key = [](void*, wl_keyboard*, uint32_t, uint32_t, uint32_t,\n            uint32_t) {},\n  .modifiers = [](void* data, struct wl_keyboard*,\n                  uint32_t serial, uint32_t modsDepressed,\n                  uint32_t modsLatched, uint32_t modsLocked,\n                  uint32_t group) {\n    ((Keyboard*)data)->handleModifiers(serial, modsDepressed,\n                                       modsLatched,\n                                       modsLocked, group);\n  },\n  .repeat_info = [](void*, wl_keyboard*, int32_t, int32_t) {}\n};\n\nstruct XkbContext {\n  xkb_context* ctx;\n  xkb_state* state;\n  xkb_keymap* keymap;\n};\n\nKeyboard::Keyboard(Display* display, Seat* seat,\n                   std::function<void(unsigned int)> setLEDstate_)\n  : keyboardFormat(0), keyboardFd(0), keyboardSize(0),\n    keyboard(nullptr), keyMap(nullptr), context(nullptr),\n    setLEDstate(setLEDstate_)\n{\n  xkb_context* ctx;\n\n  ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);\n  if (ctx)  {\n    context = new XkbContext();\n    context->ctx = ctx;\n  } else {\n    // FIXME: fallback?\n    vlog.error(\"Failed to create xkb context - keyboard will not work\");\n  }\n\n  keyboard = wl_seat_get_keyboard(seat->getSeat());\n  wl_keyboard_add_listener(keyboard, &listener, this);\n  display->roundtrip();\n\n  memset(codeMapQnumToKeyCode, 0, sizeof(codeMapQnumToKeyCode));\n}\n\nKeyboard::~Keyboard()\n{\n  if (keyboard)\n    wl_keyboard_destroy(keyboard);\n  clearKeyMap();\n  delete context;\n}\n\nbool Keyboard::updateState(uint32_t keycode, bool down,\n                           uint32_t* modsDepressed,\n                           uint32_t* modsLatched, uint32_t* modsLocked,\n                           uint32_t* group)\n{\n  xkb_state_component changed;\n\n  if (!context || !context->state)\n    return false;\n\n  changed = xkb_state_update_key(context->state, keycode,\n                                 down ? XKB_KEY_DOWN : XKB_KEY_UP);\n\n  *modsDepressed = xkb_state_serialize_mods(context->state, XKB_STATE_MODS_DEPRESSED);\n  *modsLatched = xkb_state_serialize_mods(context->state, XKB_STATE_MODS_LATCHED);\n  *modsLocked = xkb_state_serialize_mods(context->state, XKB_STATE_MODS_LOCKED);\n  *group = xkb_state_serialize_mods(context->state, XKB_STATE_LAYOUT_EFFECTIVE);\n\n  if (changed)\n    setLEDstate(getLEDState());\n\n  return changed != 0;\n}\n\nvoid Keyboard::handleKeyMap(uint32_t format, int32_t fd, uint32_t size)\n{\n  if (!context || !context->ctx)\n    return;\n\n  // https://wayland.app/protocols/wayland#wl_keyboard:enum:keymap_format\n  // Format is either:\n  //  no_keymap 0, or\n  //  xkb_v1    1\n  if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {\n    xkb_keymap* map;\n    xkb_state* state;\n    char* newKeyMap;\n\n    newKeyMap = (char*)mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);\n    if (!newKeyMap) {\n      vlog.error(\"Failed to map keymap\");\n      clearKeyMap();\n      return;\n    }\n\n    if (keyMap && strcmp(keyMap, newKeyMap) == 0) {\n      // Keymap unchanged, no need to update anything.\n      // This is a workaround for where zwp_virtual_keyboard_v1_keymap()\n      // will trigger a keymap event with the same keymap as before\n      return;\n    }\n\n    if (keyMap)\n      munmap(keyMap, keyboardSize);\n\n    keyMap = newKeyMap;\n\n    map = xkb_keymap_new_from_buffer(context->ctx, keyMap,\n                                     size,\n                                     XKB_KEYMAP_FORMAT_TEXT_V1,\n                                     XKB_KEYMAP_COMPILE_NO_FLAGS);\n    if (!map) {\n      vlog.error(\"Failed to create xkb keymap\");\n      clearKeyMap();\n      return;\n    }\n\n    if (context->keymap)\n      xkb_keymap_unref(context->keymap);\n    context->keymap = map;\n\n    state = xkb_state_new(context->keymap);\n    if (!state) {\n      vlog.error(\"Failed to create xkb state\");\n      clearKeyMap();\n      return;\n    }\n\n    if (context->state)\n      xkb_state_unref(context->state);\n    context->state = state;\n\n    vlog.debug(\"Keymap updated\");\n    keyboardFormat = format;\n    keyboardFd = fd;\n    keyboardSize = size;\n    generateKeycodeMap();\n  } else {\n    vlog.error(\"Unsupported keymap format\");\n    clearKeyMap();\n  }\n}\n\nuint32_t Keyboard::keysymToKeycode(int keysym)\n{\n  xkb_keycode_t min;\n  xkb_keycode_t max;\n\n  if (!context || !context->keymap)\n    return XKB_KEYCODE_INVALID;\n\n  min = xkb_keymap_min_keycode(context->keymap);\n  max = xkb_keymap_max_keycode(context->keymap);\n\n  for (xkb_keycode_t keycode = min; keycode <= max; keycode++) {\n    xkb_keysym_t sym;\n    sym = xkb_state_key_get_one_sym(context->state, keycode);\n    if (sym == (xkb_keysym_t)keysym)\n      return keycode;\n  }\n\n  return XKB_KEYCODE_INVALID;\n}\n\nuint32_t Keyboard::rfbcodeToKeycode(uint32_t rfbcode)\n{\n  if (!context)\n    return XKB_KEYCODE_INVALID;\n  if (rfbcode >= sizeof(codeMapQnumToKeyCode))\n    return XKB_KEYCODE_INVALID;\n  if (codeMapQnumToKeyCode[rfbcode] == 0)\n    return XKB_KEYCODE_INVALID;\n  return codeMapQnumToKeyCode[rfbcode];\n}\n\nvoid Keyboard::handleModifiers(uint32_t /* serial */,\n                               uint32_t modsDepressed,\n                               uint32_t modsLatched,\n                               uint32_t modsLocked, uint32_t group)\n{\n  xkb_state_component changed;\n\n  if (!context || !context->state)\n    return;\n\n  // FIXME: What do we set the latched/locked layouts to?\n  changed = xkb_state_update_mask(context->state, modsDepressed, modsLatched,\n                        modsLocked, group, 0, 0);\n\n  if (changed & XKB_STATE_LEDS)\n    setLEDstate(getLEDState());\n}\n\nunsigned int Keyboard::getLEDState()\n{\n  unsigned int ledState;\n\n  if (!context || !context->state)\n    return 0;\n\n  ledState = 0;\n  if (xkb_state_led_name_is_active(context->state, XKB_LED_NAME_SCROLL))\n    ledState |= rfb::ledScrollLock;\n  if (xkb_state_led_name_is_active(context->state, XKB_LED_NAME_NUM))\n    ledState |= rfb::ledNumLock;\n  if (xkb_state_led_name_is_active(context->state, XKB_LED_NAME_CAPS))\n    ledState |= rfb::ledCapsLock;\n\n  return ledState;\n}\n\nvoid Keyboard::generateKeycodeMap()\n{\n  if (!context || !context->keymap)\n    return;\n\n  memset(codeMapQnumToKeyCode, 0, sizeof(codeMapQnumToKeyCode));\n\n  /* Here, we generate a mapping from qnumcode (RFB) to our keyboard's\n   * configured keycodes. We iterate through code_map_xkb_to_qnum in\n   * reverse and try to find matches between the keycodemap and our\n   * keymap.\n   *\n   * Note that we have to iterate through the xkb_to_qnum map in reverse\n   * (instead of using a qnum_to_xkb map) since the mapping between\n   * keycodes and keynames is one-to-many. This means that the same\n   * keycode may be mapped by multiple keynames (such as TLDE and AB00\n   * both mapping to 0x29).\n   *\n   * The only exception to this rule is SYRQ, which for historical\n   * reasons is mapped by both 0x54 and 0xb7.\n   */\n\n  for (unsigned int rfbcode = 1; rfbcode < 255; rfbcode++) {\n    unsigned int xkbKeyCode;\n    bool rfbFound;\n\n    xkbKeyCode = 0;\n    rfbFound = false;\n    for (unsigned int j = 0; j < code_map_xkb_to_qnum_len; j++) {\n      const char* keyName;\n\n      if (code_map_xkb_to_qnum[j].to != rfbcode)\n        continue;\n\n      rfbFound = true;\n      keyName = code_map_xkb_to_qnum[j].from;\n      assert(keyName);\n\n      xkbKeyCode = xkb_keymap_key_by_name(context->keymap, keyName);\n      if (xkbKeyCode != XKB_KEYCODE_INVALID)\n        break;\n    }\n\n    if (xkbKeyCode != 0)\n      codeMapQnumToKeyCode[rfbcode] = xkbKeyCode;\n    else if (rfbFound)\n      vlog.debug(\"No mapping found for key 0x%04x\", rfbcode);\n  }\n}\n\nvoid Keyboard::clearKeyMap()\n{\n  memset(codeMapQnumToKeyCode, 0, sizeof(codeMapQnumToKeyCode));\n\n  if (keyMap) {\n    munmap(keyMap, keyboardSize);\n    keyMap = nullptr;\n    keyboardFd = -1;\n    keyboardSize = 0;\n  }\n\n  if (context) {\n    if (context->state)\n      xkb_state_unref(context->state);\n    context->state = nullptr;\n    if (context->keymap)\n      xkb_keymap_unref(context->keymap);\n    context->keymap = nullptr;\n    if (context->ctx)\n      xkb_context_unref(context->ctx);\n    context->ctx = nullptr;\n  }\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Keyboard.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_KEYBOARD_H__\n#define __WAYLAND_KEYBOARD_H__\n\n#include <functional>\n\n#include <wayland-client-protocol.h>\n#include <xkbcommon/xkbcommon.h>\n\nstruct XkbContext;\n\nnamespace wayland {\n  class Display;\n  class Seat;\n\n  class Keyboard {\n  public:\n    Keyboard(Display* display, Seat *seat, std::function<void(unsigned int)> setLEDstate);\n    ~Keyboard();\n\n    uint32_t getFormat() const { return keyboardFormat; }\n    int32_t getFd() const { return keyboardFd; }\n    uint32_t getSize() const { return keyboardSize; }\n    bool hasKeymap() const { return keyMap != nullptr; }\n\n    // Get the current LED state\n    unsigned int getLEDState();\n\n    // Update the keyboard state according to a key event.\n    // Returns true if the modifier state changed as well as the current\n    // state\n    bool updateState(uint32_t keycode, bool down, uint32_t* modsDepressed,\n                     uint32_t* modsLatched, uint32_t* modsLocked,\n                     uint32_t* group);\n\n    uint32_t keysymToKeycode(int keycode);\n    uint32_t rfbcodeToKeycode(uint32_t rfbcode);\n\n  private:\n    void handleKeyMap(uint32_t format, int32_t fd, uint32_t size);\n    void handleModifiers(uint32_t serial, uint32_t modsDepressed,\n                         uint32_t modsLatched, uint32_t modsLocked,\n                         uint32_t group);\n    void generateKeycodeMap();\n    void clearKeyMap();\n\n  private:\n    uint32_t keyboardFormat;\n    int32_t keyboardFd;\n    uint32_t keyboardSize;\n    wl_keyboard* keyboard;\n    char* keyMap;\n    static const wl_keyboard_listener listener;\n    XkbContext* context;\n    // Called when the LED state has changed\n    std::function<void(unsigned int)> setLEDstate;\n    uint32_t codeMapQnumToKeyCode[256];\n  };\n};\n\n#endif // __WAYLAND_KEYBOARD_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Object.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#include <assert.h>\n\n#include <stdexcept>\n\n#include <wayland-client-core.h>\n#include <wayland-client-protocol.h>\n\n#include <core/string.h>\n\n#include \"../../w0vncserver.h\"\n#include \"Display.h\"\n#include \"Object.h\"\n\nusing namespace wayland;\n\nObject::Object(Display* display, const char* interfaceName,\n                 const wl_interface* interface)\n  : boundObject(nullptr)\n{\n  wl_registry* registry;\n  ObjectInfo* objectInfo;\n\n  assert(display->interfaceAvailable(interfaceName));\n\n  objectInfo = display->getObjectInfo(interfaceName);\n  registry = display->getRegistry();\n\n  boundObject = (wl_proxy*)wl_registry_bind(registry, objectInfo->name,\n                                            interface,\n                                            objectInfo->version);\n\n  if (!boundObject)\n    throw std::runtime_error(core::format(\"Failed to bind to %s \", interfaceName));\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Object.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_OBJECT_H__\n#define __WAYLAND_OBJECT_H__\n\n#include <stdint.h>\n\nstruct wl_interface;\nstruct wl_proxy;\n\nnamespace wayland {\n  class Display;\n\n  class Object {\n  protected:\n    Object(Display* display, const char* name,\n           const wl_interface* interface);\n  public:\n    virtual ~Object() {};\n  protected:\n    wl_proxy* boundObject;\n  };\n};\n\n#endif // __WAYLAND_OBJECT_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Output.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <wayland-client-protocol.h>\n\n#include <core/LogWriter.h>\n\n#include \"../../w0vncserver.h\"\n#include \"Display.h\"\n#include \"Object.h\"\n#include \"Output.h\"\n\nusing namespace wayland;\n\nconst wl_output_listener Output::listener = {\n  .geometry = [](void* data, wl_output*, int32_t x, int32_t y,\n                 int32_t physicalWidth, int32_t physicalHeight,\n                 int32_t subpixel, const char* make, const char* model,\n                 int32_t transform) {\n    ((Output*)data)->handleGeometry(x, y, physicalWidth, physicalHeight,\n                                    subpixel, make, model, transform);\n  },\n  .mode = [](void* data, wl_output*, uint32_t flags, int32_t width,\n             int32_t height, int32_t refresh) {\n    ((Output*)data)->handleMode(flags, width, height, refresh);\n  },\n  .done = [](void* data, wl_output*) {\n    ((Output*)data)->handleDone();\n  },\n  .scale = [](void* data, wl_output*, int32_t factor) {\n    ((Output*)data)->handleScale(factor);\n  },\n  .name = [](void* data, wl_output*, const char* name) {\n    ((Output*)data)->handleName(name);\n  },\n  .description = [](void* data, wl_output*, const char* description) {\n    ((Output*)data)->handleDescription(description);\n  }\n};\n\nstatic core::LogWriter vlog(\"WOutput\");\n\nOutput::Output(Display* display)\n  : Object(display, \"wl_output\", &wl_output_interface), output(nullptr),\n    mode({0, 0, 0, 0}), geometry({0, 0, 0, 0, 0, \"\", \"\", 0})\n{\n  output = (wl_output*) boundObject;\n\n  wl_output_add_listener(output, &listener, this);\n  display->roundtrip();\n}\n\nOutput::~Output()\n{\n  wl_output_destroy(output);\n}\n\nvoid Output::handleGeometry(int32_t x, int32_t y,\n                            int32_t physical_width,\n                            int32_t physical_height,\n                            int32_t subpixel, const char* make,\n                            const char* model, int32_t transform)\n{\n  geometry = {\n    .x = x,\n    .y = y,\n    .physical_width = physical_width,\n    .physical_height = physical_height,\n    .subpixel = subpixel,\n    .make = make,\n    .model = model,\n    .transform = transform\n  };\n}\n\nvoid Output::handleMode(uint32_t flags, int32_t width, int32_t height,\n                        int32_t refresh)\n{\n  if (mode.width != width || mode.height != height) {\n    vlog.debug(\"Resized from %dx%d to %dx%d\", mode.width, mode.height,\n                width, height);\n  }\n\n  // FIXME: Handle multiple screens\n  // FIXME: The flags \"describe properties of an output mode\".\n  //        possible values are 0x1 - current\n  //                            0x2 - preferred\n  //        Don't think we care?\n  mode = {\n    .flags = flags,\n    .width = width,\n    .height = height,\n    .refresh = refresh,\n  };\n}\n\nvoid Output::handleDone()\n{\n  // All properties have been sent.\n}\n\nvoid Output::handleScale(int32_t /* factor */)\n{\n  // FIXME: Handle scaling\n}\n\nvoid Output::handleName(const char* /* name */)\n{\n  // Output name, e.g. \"HDMI-1\", \"WL-1\" etc.\n}\n\nvoid Output::handleDescription(const char* /* description */)\n{\n  // Optional description, e.g. \"Dell inc. 24\"\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Output.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_OUTPUT_H__\n#define __WAYLAND_OUTPUT_H__\n\n#include <string>\n\n#include \"Object.h\"\n\nstruct wl_output;\nstruct wl_output_listener;\n\nnamespace wayland {\n  class Display;\n\n  struct Mode {\n    uint32_t flags;\n    int32_t width;\n    int32_t height;\n    int32_t refresh;\n  };\n\n  struct Geometry {\n    int32_t x;\n    int32_t y;\n    int32_t physical_width;\n    int32_t physical_height;\n    int32_t subpixel;\n    std::string make;\n    std::string model;\n    int32_t transform;\n  };\n\n  class Output : public Object {\n  public:\n    Output(Display* display);\n    ~Output();\n\n    wl_output* getOutput() const { return output; }\n    uint32_t getWidth() const { return mode.width; }\n    uint32_t getHeight() const { return mode.height; }\n    int32_t getTransform() const { return geometry.transform; }\n\n  private:\n    void handleGeometry(int32_t x, int32_t y, int32_t physical_width,\n                        int32_t physical_height, int32_t subpixel,\n                        const char* make, const char* model,\n                        int32_t transform);\n    void handleMode(uint32_t flags, int32_t width, int32_t height,\n                    int32_t refresh);\n    void handleDone();\n    void handleScale(int32_t factor);\n    void handleName(const char* name);\n    void handleDescription(const char* description);\n\n  private:\n    wl_output* output;\n    Mode mode;\n    Geometry geometry;\n    std::string name;\n    std::string description;\n    static const wl_output_listener listener;\n  };\n};\n\n#endif // __WAYLAND_OUTPUT_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Pointer.cxx",
    "content": "/* Copyright 2026 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#include <wayland-client-protocol.h>\n\n#include \"Pointer.h\"\n#include \"Seat.h\"\n#include \"Display.h\"\n\nusing namespace wayland;\n\nPointer::Pointer(Display* /* display */, Seat* seat)\n{\n  // FIXME: Implement this class properly\n  pointer = wl_seat_get_pointer(seat->getSeat());\n}\n\nPointer::~Pointer()\n{\n  if (pointer)\n    wl_pointer_destroy(pointer);\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Pointer.h",
    "content": "/* Copyright 2026 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_POINTER_H__\n#define __WAYLAND_POINTER_H__\n\nstruct wl_pointer;\n\nnamespace wayland {\n  class Display;\n  class Seat;\n\n  class Pointer  {\n  public:\n    Pointer(Display* display, Seat* seat);\n    ~Pointer();\n\n    wl_pointer* getPointer() const { return pointer; }\n\n  private:\n    wl_pointer* pointer;\n  };\n}\n\n#endif // __WAYLAND_POINTER_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ScreencopyManager.cxx",
    "content": "/* Copyright 2025-2026 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <unistd.h>\n#include <sys/mman.h>\n#include <fcntl.h>\n#include <string.h>\n\n#include <stdexcept>\n\n#include <wlr-screencopy-unstable-v1.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n#include <rfb/PixelFormat.h>\n#include <core/Rect.h>\n\n#include \"../../w0vncserver.h\"\n#include \"Display.h\"\n#include \"Object.h\"\n#include \"Output.h\"\n#include \"Shm.h\"\n#include \"ShmPool.h\"\n#include \"ScreencopyManager.h\"\n\nusing namespace wayland;\n\nstatic core::LogWriter vlog(\"WawylandScreencopyManager\");\n\nconst zwlr_screencopy_frame_v1_listener ScreencopyManager::listener = {\n  .buffer = [](void* data, zwlr_screencopy_frame_v1*, uint32_t format,\n               uint32_t width, uint32_t height, uint32_t stride) {\n    ((ScreencopyManager*)data)->handleScreencopyBuffer(format, width, height, stride);\n  },\n  .flags = [](void* data, zwlr_screencopy_frame_v1*, uint32_t flags) {\n    ((ScreencopyManager*)data)->handleScreencopyFlags(flags);\n  },\n  .ready = [](void* data, zwlr_screencopy_frame_v1*,\n              uint32_t /* tvSecHi */, uint32_t /* tvSecLo */,\n              uint32_t /* tvNsec */) {\n    ((ScreencopyManager*)data)->handleScreencopyReady();\n  },\n  .failed = [](void* data, zwlr_screencopy_frame_v1*) {\n     ((ScreencopyManager*)data)->handleScreencopyFailed();\n  },\n  .damage = [](void* data, zwlr_screencopy_frame_v1*, uint32_t x,\n               uint32_t y, uint32_t width, uint32_t height) {\n    ((ScreencopyManager*)data)->handleScreencopyDamage(x, y, width, height);\n  },\n  .linux_dmabuf = [](void* data, zwlr_screencopy_frame_v1*,\n                     uint32_t format, uint32_t width, uint32_t height) {\n    ((ScreencopyManager*)data)->handleScreencopyLinuxDmabuf(format, width, height);\n  },\n  .buffer_done = [](void* data, zwlr_screencopy_frame_v1*) {\n    ((ScreencopyManager*)data)->handleScreencopyBufferDone();\n  }\n};\n\nstruct BufferInfo {\n  uint32_t format;\n  uint32_t width;\n  uint32_t height;\n  uint32_t stride;\n};\n\nScreencopyManager::ScreencopyManager(Display* display, Output* output_,\n                                     std::function<void(uint8_t*,\n                                                        core::Region,\n                                                        uint32_t, uint32_t)>\n                                                          bufferEventCb_,\n                                     std::function<void()> stoppedCb_)\n : Object(display, \"zwlr_screencopy_manager_v1\",\n           &zwlr_screencopy_manager_v1_interface),\n   output(output_), active(true), screencopyManager(nullptr),\n   frame(nullptr), info(nullptr), shm(display), pool(nullptr),\n   buffer(nullptr), bufferEventCb(bufferEventCb_), stoppedCb(stoppedCb_)\n{\n  size_t size;\n\n  screencopyManager = (zwlr_screencopy_manager_v1*)boundObject;\n\n  display->roundtrip();\n\n  size = output_->getWidth() * output_->getHeight() * 4;\n  if (!size) {\n    throw std::runtime_error(core::format(\"Invalid output size %dx%d\",\n                                          output_->getWidth(),\n                                          output_->getHeight()));\n  }\n\n  initBuffers(size);\n\n  captureFrame();\n}\n\nScreencopyManager::~ScreencopyManager()\n{\n  if (screencopyManager)\n    zwlr_screencopy_manager_v1_destroy(screencopyManager);\n  if (frame)\n    zwlr_screencopy_frame_v1_destroy(frame);\n  if (buffer)\n    wl_buffer_destroy(buffer);\n\n  delete info;\n  delete pool;\n}\n\nuint8_t* ScreencopyManager::getBufferData()\n{\n  return pool->getData();\n}\n\nvoid ScreencopyManager::captureFrame()\n{\n  if (!active)\n    return;\n\n  assert(frame == nullptr);\n\n  accumulatedDamage.clear();\n\n  // FIXME: Handle multiple outputs\n  // FIXME: This will render the cursor as part of the stream.\n  //        Getting the cursor position requires the newer\n  //        ext-image-copy-capture-v1 protocol\n  frame = zwlr_screencopy_manager_v1_capture_output(screencopyManager,\n                                                    1, output->getOutput());\n  zwlr_screencopy_frame_v1_add_listener(frame, &listener, this);\n}\n\nvoid ScreencopyManager::captureFrameDone()\n{\n  assert(frame != nullptr);\n\n  zwlr_screencopy_frame_v1_destroy(frame);\n  frame = nullptr;\n\n  bufferEventCb(getBufferData(), accumulatedDamage, info->format,\n                output->getTransform());\n\n  captureFrame();\n}\n\nvoid ScreencopyManager::resize()\n{\n  if (frame)\n    zwlr_screencopy_frame_v1_destroy(frame);\n  frame = nullptr;\n\n  if (buffer)\n    wl_buffer_destroy(buffer);\n  buffer = nullptr;\n\n  delete pool;\n  pool = nullptr;\n\n  try {\n    initBuffers(output->getWidth() * output->getHeight() * 4);\n  } catch (std::runtime_error& e) {\n    vlog.error(\"Failed to resize: %s\", e.what());\n    stopped();\n  }\n}\n\nvoid ScreencopyManager::stopped()\n{\n  active = false;\n  stoppedCb();\n}\n\nvoid ScreencopyManager::initBuffers(size_t size)\n{\n  int fd;\n\n  fd = memfd_create(\"w0vncserver-shm\", FD_CLOEXEC);\n  if (fd < 0)\n    throw std::runtime_error(core::format(\"Failed to allocate shm: %s\", strerror(errno)));\n\n  if (ftruncate(fd, size) < 0) {\n    close(fd);\n    throw std::runtime_error(core::format(\"Failed to truncate shm: %s\", strerror(errno)));\n  }\n\n\n  pool = new ShmPool(&shm, fd, size);\n\n  close(fd);\n}\n\nvoid ScreencopyManager::handleScreencopyBuffer(uint32_t format,\n                                               uint32_t width,\n                                               uint32_t height,\n                                               uint32_t stride)\n{\n  if (output->getHeight() != height || output->getWidth() != width) {\n    vlog.debug(\"Detected resize, destroying frame\");\n    zwlr_screencopy_frame_v1_destroy(frame);\n    frame = nullptr;\n    return;\n  }\n\n  delete info;\n\n  info = new BufferInfo {\n    .format = format,\n    .width = width,\n    .height = height,\n    .stride = stride\n  };\n\n}\n\nvoid ScreencopyManager::handleScreencopyFlags(uint32_t /* flags */)\n{\n  // FIXME: This tells us if the contents are y-inverted.\n  //        Should probably handle this.\n}\n\nvoid ScreencopyManager::handleScreencopyReady()\n{\n  captureFrameDone();\n}\n\nvoid ScreencopyManager::handleScreencopyFailed()\n{\n  // We will get a failure if the output size has changed, which is\n  // expected during a resize.\n  if (output->getWidth() != info->width || output->getHeight() != info->height) {\n    captureFrameDone();\n  } else {\n    vlog.error(\"Frame could not be copied\");\n    stopped();\n  }\n}\n\nvoid ScreencopyManager::handleScreencopyDamage(uint32_t x,\n                                               uint32_t y,\n                                               uint32_t width,\n                                               uint32_t height)\n{\n  core::Point tl;\n  core::Point br;\n\n  tl = {static_cast<int>(x), static_cast<int>(y)};\n  br = {static_cast<int>(x + width), static_cast<int>(y + height)};\n\n  accumulatedDamage.assign_union({{tl, br}});\n}\n\nvoid ScreencopyManager::handleScreencopyLinuxDmabuf(uint32_t /* format */,\n                                                    uint32_t /* width */,\n                                                    uint32_t /* height */)\n{\n  // FIXME: Implement this?\n}\n\nvoid ScreencopyManager::handleScreencopyBufferDone()\n{\n  if (pool->getSize() != output->getWidth() * output->getHeight() * 4) {\n    vlog.debug(\"Detected resize, aborting capture\");\n    captureFrameDone();\n    return;\n  }\n\n  if (!buffer) {\n    // FIXME: Check if buffer paramters have changed\n    // FIXME: Sanity check with BufferInfo\n    buffer = pool->createBuffer(0, output->getWidth(), output->getHeight(),\n                                output->getWidth() * 4, info->format);\n    if (!buffer) {\n      vlog.error(\"Cannot capture frame - failed to create buffer\");\n      stopped();\n      return;\n    }\n  }\n\n  zwlr_screencopy_frame_v1_copy_with_damage(frame, buffer);\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ScreencopyManager.h",
    "content": "/* Copyright 2025-2026 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_SCREENCOPY_MANAGER_H__\n#define __WAYLAND_SCREENCOPY_MANAGER_H__\n\n#include <stddef.h>\n\n#include <functional>\n\n#include <core/Region.h>\n#include <rfb/PixelFormat.h>\n\n#include \"Shm.h\"\n#include \"Object.h\"\n\nstruct wl_buffer;\nstruct zwlr_screencopy_manager_v1;\nstruct zwlr_screencopy_frame_v1;\nstruct zwlr_screencopy_frame_v1_listener;\nstruct BufferInfo;\n\nnamespace wayland {\n  class Display;\n  class Shm;\n  class ShmPool;\n  class Output;\n\n  class ScreencopyManager : public Object {\n  public:\n    ScreencopyManager(Display* display, Output* output,\n                      std::function<void(uint8_t*, core::Region, uint32_t, uint32_t)> readyCallback,\n                      std::function<void()> stoppedCb);\n    virtual ~ScreencopyManager();\n\n    // Called when the remote output is resized\n    void resize();\n\n    uint8_t* getBufferData();\n\n  private:\n    // Capture the next frame. This function is asynchronous.\n    // Framebuffer data is available after handleScreencopyReady() has\n    // been called, in which case captureFrameDone() will be called.\n    void captureFrame();\n\n    // Called when the buffer is safe to read from, the frame is ready.\n    void captureFrameDone();\n\n    void stopped();\n\n  private:\n    void initBuffers(size_t size);\n\n    // zwlr_screencopy_frame_v1_listener handlers\n    void handleScreencopyBuffer(uint32_t format, uint32_t width, uint32_t height,\n                                uint32_t stride);\n    void handleScreencopyFlags(uint32_t flags);\n    void handleScreencopyReady();\n    void handleScreencopyFailed();\n    void handleScreencopyDamage(uint32_t x, uint32_t y, uint32_t width,\n                                uint32_t height);\n    void handleScreencopyLinuxDmabuf(uint32_t format, uint32_t width,\n                                    uint32_t height);\n    void handleScreencopyBufferDone();\n\n  protected:\n    Output* output;\n    bool active;\n\n  private:\n    zwlr_screencopy_manager_v1* screencopyManager;\n    zwlr_screencopy_frame_v1* frame;\n    BufferInfo* info;\n    Shm shm;\n    ShmPool* pool;\n    wl_buffer* buffer;\n    core::Region accumulatedDamage;\n    rfb::PixelFormat pf;\n    std::function<void(uint8_t*, core::Region, uint32_t, uint32_t)> bufferEventCb;\n    std::function<void()> stoppedCb;\n    static const zwlr_screencopy_frame_v1_listener listener;\n  };\n};\n\n#endif // __WAYLAND_SCREENCOPY_MANAGER_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Seat.cxx",
    "content": "/* Copyright 2025-2026 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n#include <wayland-client-protocol.h>\n\n#include \"Display.h\"\n#include \"Keyboard.h\"\n#include \"Pointer.h\"\n#include \"Seat.h\"\n\nusing namespace wayland;\n\nstatic core::LogWriter vlog(\"WSeat\");\n\nconst wl_seat_listener Seat::listener = {\n  .capabilities = [](void* data, wl_seat*,\n                     uint32_t capabilities) {\n    ((Seat*)data)->seatCapabilities(capabilities);\n  },\n  .name = [](void*, wl_seat*, const char*) {},\n};\n\nSeat::Seat(Display* display_, std::function<void(unsigned int)> setLEDstate_)\n  : Object(display_, \"wl_seat\", &wl_seat_interface),\n    seat(nullptr), display(display_), keyboard(nullptr),\n    pointer(nullptr), setLEDstate(setLEDstate_)\n{\n  seat = (wl_seat*)boundObject;\n\n  wl_seat_add_listener(seat, &listener, this);\n  display->roundtrip();\n}\n\nSeat::~Seat()\n{\n  if (seat)\n    wl_seat_destroy(seat);\n\n  delete keyboard;\n  delete pointer;\n}\n\nvoid Seat::seatCapabilities(uint32_t capabilities)\n{\n  if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {\n    vlog.debug(\"Keyboard detected\");\n    delete keyboard;\n    keyboard = new Keyboard(display, this, setLEDstate);\n  }\n\n  if (capabilities & WL_SEAT_CAPABILITY_POINTER) {\n      delete pointer;\n      pointer = new Pointer(display, this);\n  }\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Seat.h",
    "content": "/* Copyright 2025-2026 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_SEAT_H__\n#define __WAYLAND_SEAT_H__\n\n#include <functional>\n\n#include \"Object.h\"\n\nstruct wl_seat;\nstruct wl_seat_listener;\n\nnamespace wayland {\n  class Display;\n  class Keyboard;\n  class Pointer;\n\n  class Seat : public Object {\n  public:\n    Seat(Display* display, std::function<void(unsigned int)> setLEDstate);\n    ~Seat();\n\n    wl_seat* getSeat() const { return seat; }\n    Keyboard* getKeyboard() const { return keyboard; }\n    Pointer* getPointer() const { return pointer; }\n\n  private:\n    void seatCapabilities(uint32_t capabilities);\n\n  private:\n    wl_seat* seat;\n    Display* display;\n    Keyboard* keyboard;\n    Pointer* pointer;\n    static const wl_seat_listener listener;\n    std::function<void(unsigned int)> setLEDstate;\n  };\n};\n\n#endif // __WAYLAND_SEAT_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Shm.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <wayland-client-protocol.h>\n\n#include \"Display.h\"\n#include \"Shm.h\"\n\nusing namespace wayland;\n\nShm::Shm(Display* display)\n  : Object(display, \"wl_shm\", &wl_shm_interface), shm(nullptr)\n{\n  shm = (wl_shm*) boundObject;\n}\n\nShm::~Shm()\n{\n  wl_shm_destroy(shm);\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/Shm.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_SHM_H__\n#define __WAYLAND_SHM_H__\n\n#include \"Object.h\"\n\nstruct wl_shm_listener;\nstruct wl_shm;\n\nnamespace wayland {\n  class Display;\n\n  class Shm : public Object {\n  public:\n    Shm(Display* display);\n    ~Shm();\n\n    wl_shm* getShm() { return shm; }\n\n  private:\n    static const wl_shm_listener listener;\n    wl_shm* shm;\n  };\n};\n\n#endif // __WAYLAND_SHM_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ShmPool.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <sys/mman.h>\n\n#include <stdexcept>\n\n#include <wayland-client-protocol.h>\n\n#include <core/LogWriter.h>\n\n#include \"../../w0vncserver.h\"\n#include \"Shm.h\"\n#include \"ShmPool.h\"\n\nusing namespace wayland;\n\nstatic core::LogWriter vlog(\"WShmPool\");\n\nShmPool::ShmPool(Shm* shm, int fd, size_t size_)\n  : pool(nullptr), data(nullptr), size(size_)\n{\n  data = (uint8_t*)mmap(nullptr, size, PROT_READ | PROT_WRITE,\n                        MAP_SHARED, fd, 0);\n  if (data == MAP_FAILED)\n    throw std::runtime_error(\"Failed to mmap shm\");\n\n  pool = wl_shm_create_pool(shm->getShm(), fd, size);\n}\n\nShmPool::~ShmPool()\n{\n  if (munmap(data, size) < 0) {\n    // FIXME: fatal_error?\n    vlog.error(\"Failed to munmap shm\");\n  }\n  wl_shm_pool_destroy(pool);\n}\n\nwl_buffer* ShmPool::createBuffer(int32_t offset, int32_t width,\n                                 int32_t height, int32_t stride,\n                                 uint32_t format)\n{\n  return wl_shm_pool_create_buffer(pool, offset, width, height, stride, format);\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/ShmPool.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_SHM_POOL_H__\n#define __WAYLAND_SHM_POOL_H__\n\n#include <stddef.h>\n#include <stdint.h>\n\nstruct wl_shm_pool;\nstruct wl_buffer;\n\nnamespace wayland {\n  class Shm;\n\n  class ShmPool {\n  public:\n    ShmPool(Shm* shm, int fd, size_t size);\n    ~ShmPool();\n\n    wl_shm_pool* getShmPool() { return pool; }\n    uint8_t* getData() { return data; }\n    size_t getSize() { return size; }\n\n    wl_buffer* createBuffer(int32_t offset, int32_t width, int32_t height,\n                            int32_t stride, uint32_t format);\n\n  private:\n    wl_shm_pool* pool;\n    uint8_t* data;\n    size_t size;\n  };\n};\n\n#endif // __WAYLAND_SHM_POOL_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/VirtualKeyboard.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <time.h>\n#include <assert.h>\n\n#include <stdexcept>\n\n#include <virtual-keyboard-unstable-v1.h>\n#include <xkbcommon/xkbcommon-keysyms.h>\n\n#include <core/LogWriter.h>\n#include <rfb/KeysymStr.h>\n#include <rfb/ledStates.h>\n\n#include \"../../w0vncserver.h\"\n#include \"../../parameters.h\"\n#include \"Display.h\"\n#include \"Seat.h\"\n#include \"Keyboard.h\"\n#include \"VirtualKeyboard.h\"\n\nusing namespace wayland;\n\nstatic core::LogWriter vlog(\"WaylandVirtualKeyboard\");\n\nVirtualKeyboard::VirtualKeyboard(Display* display, Seat* seat_)\n  : Object(display, \"zwp_virtual_keyboard_manager_v1\",\n           &zwp_virtual_keyboard_manager_v1_interface),\n    manager(nullptr), keyboard(nullptr), seat(seat_),\n    keyboardFd(0)\n{\n  manager = (zwp_virtual_keyboard_manager_v1*) boundObject;\n\n  keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(manager,\n                                                                     seat->getSeat());\n  if (!keyboard)\n    throw std::runtime_error(\"Failed to create virtual keyboard\");\n\n  if (seat->getKeyboard() && seat->getKeyboard()->hasKeymap())\n    setupKeyboard();\n  else\n    vlog.debug(\"Keyboard keymap is not set - keyboard will not work until it is set\");\n}\n\nVirtualKeyboard::~VirtualKeyboard()\n{\n  if (manager)\n    zwp_virtual_keyboard_manager_v1_destroy(manager);\n  if (keyboard)\n    zwp_virtual_keyboard_v1_destroy(keyboard);\n}\n\nunsigned int VirtualKeyboard::getLEDState()\n{\n  if (!keyboardFd)\n    return rfb::ledUnknown;\n\n  if (keymapUpdated())\n    setupKeyboard();\n\n  return seat->getKeyboard()->getLEDState();\n}\n\nvoid VirtualKeyboard::key(uint32_t keysym, uint32_t keycode, bool down)\n{\n  timespec ts;\n  uint32_t time;\n  bool updated;\n  uint32_t key;\n  Keyboard* wKeyboard;\n  uint32_t modsDepressed;\n  uint32_t modsLatched;\n  uint32_t modsLocked;\n  uint32_t group;\n\n  if (keymapUpdated())\n    setupKeyboard();\n\n  if (!keyboardFd)\n    return;\n\n  wKeyboard = seat->getKeyboard();\n\n  key = XKB_KEYCODE_INVALID;\n\n  if (rawKeyboard)\n    key = wKeyboard->rfbcodeToKeycode(keycode);\n\n  if (key == XKB_KEYCODE_INVALID) {\n    key = wKeyboard->keysymToKeycode(keysym);\n    if ((unsigned int)key == XKB_KEYCODE_INVALID) {\n      vlog.debug(\"Unable to map keysym XK_%s (0x%04x), ignoring key press\",\n                 KeySymName(keysym), keysym);\n      return;\n    }\n  }\n\n  clock_gettime(CLOCK_MONOTONIC, &ts);\n  time = (static_cast<uint64_t>(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000) &\n         0xFFFFFFFF;\n\n  // The Wayland documentation states that:\n  //   \"clients must add 8 to the key event keycode\"\n  // when format xkb_v1 is used. Subtract 8 to get the correct keycode.\n  if (wKeyboard->getFormat() == XKB_KEYMAP_FORMAT_TEXT_V1)\n    zwp_virtual_keyboard_v1_key(keyboard, time, key - 8, down);\n  else\n    zwp_virtual_keyboard_v1_key(keyboard, time, key, down);\n\n  updated = wKeyboard->updateState(key, down, &modsDepressed,\n                                   &modsLatched, &modsLocked, &group);\n  if (updated) {\n    zwp_virtual_keyboard_v1_modifiers(keyboard, modsDepressed,\n                                      modsLatched, modsLocked, group);\n  }\n}\n\nbool VirtualKeyboard::keymapUpdated()\n{\n  if (!seat->getKeyboard())\n    return false;\n\n  return keyboardFd != seat->getKeyboard()->getFd();\n}\n\nvoid VirtualKeyboard::setupKeyboard()\n{\n  assert(seat->getKeyboard());\n\n  if (!keyboardFd)\n    vlog.debug(\"Keymap set - keyboard will now work\");\n\n  zwp_virtual_keyboard_v1_keymap(keyboard,\n                                 seat->getKeyboard()->getFormat(),\n                                 seat->getKeyboard()->getFd(),\n                                 seat->getKeyboard()->getSize());\n\n  keyboardFd = seat->getKeyboard()->getFd();\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/VirtualKeyboard.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_VIRTUAL_KEYBOARD_H__\n#define __WAYLAND_VIRTUAL_KEYBOARD_H__\n\n#include <stdint.h>\n\n#include \"Object.h\"\n\nstruct zwp_virtual_keyboard_v1;\nstruct zwp_virtual_keyboard_manager_v1;\n\nnamespace wayland {\n  class Display;\n  class Seat;\n\n  class VirtualKeyboard : public Object {\n  public:\n    VirtualKeyboard(Display* display, Seat* seat);\n    ~VirtualKeyboard();\n\n    unsigned int getLEDState();\n\n    void key(uint32_t keysym, uint32_t keycode, bool down);\n\n  private:\n    bool keymapUpdated();\n    void setupKeyboard();\n\n  private:\n    zwp_virtual_keyboard_manager_v1* manager;\n    zwp_virtual_keyboard_v1* keyboard;\n    Seat* seat;\n    int keyboardFd;\n  };\n};\n\n#endif // __WAYLAND_VIRTUAL_KEYBOARD_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/VirtualPointer.cxx",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <time.h>\n#include <linux/input-event-codes.h>\n\n#include <stdexcept>\n\n#include <wlr-virtual-pointer-unstable-v1.h>\n\n#include <core/Rect.h>\n\n#include \"Seat.h\"\n#include \"Display.h\"\n#include \"VirtualPointer.h\"\n\nusing namespace wayland;\n\n// Scroll wheel events\n#define WHEEL_VERTICAL_DOWN    3\n#define WHEEL_VERTICAL_UP      4\n#define WHEEL_HORIZONTAL_LEFT  5\n#define WHEEL_HORIZONTAL_RIGHT 6\n\nstatic int getInputCode(uint32_t button)\n{\n  switch (button) {\n  case 0x0:\n    return BTN_LEFT;\n  case 0x1:\n    return BTN_MIDDLE;\n  case 0x2:\n    return BTN_RIGHT;\n  case 0x7:\n    return BTN_SIDE;\n  case 0x8:\n    return BTN_EXTRA;\n  default:\n    throw std::runtime_error(\"Unknown mouse button\");\n  }\n}\n\nVirtualPointer::VirtualPointer(Display* display, Seat* seat)\n: Object(display, \"zwlr_virtual_pointer_manager_v1\",\n         &zwlr_virtual_pointer_manager_v1_interface)\n{\n  manager = (zwlr_virtual_pointer_manager_v1*) boundObject;\n\n  cursor = zwlr_virtual_pointer_manager_v1_create_virtual_pointer(manager,\n                                                                  seat->getSeat());\n  if (!cursor)\n    throw std::runtime_error(\"Failed to create virtual pointer\");\n\n  zwlr_virtual_pointer_v1_axis_source(cursor, WL_POINTER_AXIS_SOURCE_WHEEL);\n}\n\nVirtualPointer::~VirtualPointer()\n{\n  if (manager)\n    zwlr_virtual_pointer_manager_v1_destroy(manager);\n  if (cursor)\n    zwlr_virtual_pointer_v1_destroy(cursor);\n}\n\nvoid VirtualPointer::motionAbsolute(uint32_t x, uint32_t y,\n                                    uint32_t xExetent, uint32_t yExtent)\n{\n  timespec ts;\n  uint32_t time;\n\n  clock_gettime(CLOCK_MONOTONIC, &ts);\n  // Avoid overflow\n  time = (static_cast<uint64_t>(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000)\n          & 0xFFFFFFFF;\n\n  zwlr_virtual_pointer_v1_motion_absolute(cursor, time, x, y, xExetent, yExtent);\n  frame();\n}\n\nvoid VirtualPointer::button(uint16_t button, bool down)\n{\n  timespec ts;\n  uint32_t time;\n\n  clock_gettime(CLOCK_MONOTONIC, &ts);\n  // Avoid overflow\n  time = (static_cast<uint64_t>(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000)\n          & 0xFFFFFFFF;\n\n  zwlr_virtual_pointer_v1_button(cursor, time, getInputCode(button),\n                                 down);\n  frame();\n}\n\nvoid VirtualPointer::axisDiscrete(int16_t button)\n{\n  int32_t axis;\n  int value;\n  int discrete;\n  timespec ts;\n  uint32_t time;\n\n  assert(button > 2 && button < 7);\n\n  clock_gettime(CLOCK_MONOTONIC, &ts);\n  // Avoid overflow\n  time = (static_cast<uint64_t>(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000)\n          & 0xFFFFFFFF;\n\n  // FIXME: Not sure what this is supposed to be.\n  value = 1;\n\n  switch (button) {\n  case WHEEL_VERTICAL_DOWN:\n    axis = WL_POINTER_AXIS_VERTICAL_SCROLL;\n    discrete = -1;\n    break;\n    case WHEEL_VERTICAL_UP:\n    axis = WL_POINTER_AXIS_VERTICAL_SCROLL;\n    discrete = 1;\n    break;\n  case WHEEL_HORIZONTAL_LEFT:\n    axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;\n    discrete = -1;\n    break;\n  case WHEEL_HORIZONTAL_RIGHT:\n    axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;\n    discrete = -1;\n    break;\n  default:\n    assert(false);\n  }\n\n  zwlr_virtual_pointer_v1_axis_discrete(cursor, time, axis, value,\n                                        discrete);\n}\n\nvoid VirtualPointer::frame()\n{\n  zwlr_virtual_pointer_v1_frame(cursor);\n}\n"
  },
  {
    "path": "unix/w0vncserver/wayland/objects/VirtualPointer.h",
    "content": "/* Copyright 2025 Adam Halim for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WAYLAND_VIRTUAL_POINTER_H__\n#define __WAYLAND_VIRTUAL_POINTER_H__\n\n#include \"Object.h\"\n\nnamespace core { struct Point; }\n\nstruct zwlr_virtual_pointer_manager_v1;\nstruct zwlr_virtual_pointer_v1;\n\nnamespace wayland {\n  class Display;\n  class Seat;\n\n  class VirtualPointer : public Object {\n  public:\n    VirtualPointer(Display* display, Seat* seat);\n    ~VirtualPointer();\n\n    void motionAbsolute(uint32_t x, uint32_t y, uint32_t xExetent, uint32_t yExtent);\n    void button(uint16_t button, bool down);\n    void axisDiscrete(int16_t button);\n\n  private:\n    void frame();\n\n  private:\n    zwlr_virtual_pointer_manager_v1* manager;\n    zwlr_virtual_pointer_v1* cursor;\n  };\n};\n\n#endif // __WAYLAND_VIRTUAL_POINTER_H__\n"
  },
  {
    "path": "unix/w0vncserver/wayland/protocols/ext-data-control-v1.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<protocol name=\"ext_data_control_v1\">\n  <copyright>\n    Copyright © 2018 Simon Ser\n    Copyright © 2019 Ivan Molodetskikh\n    Copyright © 2024 Neal Gompa\n\n    Permission to use, copy, modify, distribute, and sell this\n    software and its documentation for any purpose is hereby granted\n    without fee, provided that the above copyright notice appear in\n    all copies and that both that copyright notice and this permission\n    notice appear in supporting documentation, and that the name of\n    the copyright holders not be used in advertising or publicity\n    pertaining to distribution of the software without specific,\n    written prior permission.  The copyright holders make no\n    representations about the suitability of this software for any\n    purpose.  It is provided \"as is\" without express or implied\n    warranty.\n\n    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS\n    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\n    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\n    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN\n    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\n    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\n    THIS SOFTWARE.\n  </copyright>\n\n  <description summary=\"control data devices\">\n    This protocol allows a privileged client to control data devices. In\n    particular, the client will be able to manage the current selection and take\n    the role of a clipboard manager.\n\n    Warning! The protocol described in this file is currently in the testing\n    phase. Backward compatible changes may be added together with the\n    corresponding interface version bump. Backward incompatible changes can\n    only be done by creating a new major version of the extension.\n  </description>\n\n  <interface name=\"ext_data_control_manager_v1\" version=\"1\">\n    <description summary=\"manager to control data devices\">\n      This interface is a manager that allows creating per-seat data device\n      controls.\n    </description>\n\n    <request name=\"create_data_source\">\n      <description summary=\"create a new data source\">\n        Create a new data source.\n      </description>\n      <arg name=\"id\" type=\"new_id\" interface=\"ext_data_control_source_v1\"\n        summary=\"data source to create\"/>\n    </request>\n\n    <request name=\"get_data_device\">\n      <description summary=\"get a data device for a seat\">\n        Create a data device that can be used to manage a seat's selection.\n      </description>\n      <arg name=\"id\" type=\"new_id\" interface=\"ext_data_control_device_v1\"/>\n      <arg name=\"seat\" type=\"object\" interface=\"wl_seat\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"destroy the manager\">\n        All objects created by the manager will still remain valid, until their\n        appropriate destroy request has been called.\n      </description>\n    </request>\n  </interface>\n\n  <interface name=\"ext_data_control_device_v1\" version=\"1\">\n    <description summary=\"manage a data device for a seat\">\n      This interface allows a client to manage a seat's selection.\n\n      When the seat is destroyed, this object becomes inert.\n    </description>\n\n    <request name=\"set_selection\">\n      <description summary=\"copy data to the selection\">\n        This request asks the compositor to set the selection to the data from\n        the source on behalf of the client.\n\n        The given source may not be used in any further set_selection or\n        set_primary_selection requests. Attempting to use a previously used\n        source triggers the used_source protocol error.\n\n        To unset the selection, set the source to NULL.\n      </description>\n      <arg name=\"source\" type=\"object\" interface=\"ext_data_control_source_v1\"\n        allow-null=\"true\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"destroy this data device\">\n        Destroys the data device object.\n      </description>\n    </request>\n\n    <event name=\"data_offer\">\n      <description summary=\"introduce a new ext_data_control_offer\">\n        The data_offer event introduces a new ext_data_control_offer object,\n        which will subsequently be used in either the\n        ext_data_control_device.selection event (for the regular clipboard\n        selections) or the ext_data_control_device.primary_selection event (for\n        the primary clipboard selections). Immediately following the\n        ext_data_control_device.data_offer event, the new data_offer object\n        will send out ext_data_control_offer.offer events to describe the MIME\n        types it offers.\n      </description>\n      <arg name=\"id\" type=\"new_id\" interface=\"ext_data_control_offer_v1\"/>\n    </event>\n\n    <event name=\"selection\">\n      <description summary=\"advertise new selection\">\n        The selection event is sent out to notify the client of a new\n        ext_data_control_offer for the selection for this device. The\n        ext_data_control_device.data_offer and the ext_data_control_offer.offer\n        events are sent out immediately before this event to introduce the data\n        offer object. The selection event is sent to a client when a new\n        selection is set. The ext_data_control_offer is valid until a new\n        ext_data_control_offer or NULL is received. The client must destroy the\n        previous selection ext_data_control_offer, if any, upon receiving this\n        event. Regardless, the previous selection will be ignored once a new\n        selection ext_data_control_offer is received.\n\n        The first selection event is sent upon binding the\n        ext_data_control_device object.\n      </description>\n      <arg name=\"id\" type=\"object\" interface=\"ext_data_control_offer_v1\"\n        allow-null=\"true\"/>\n    </event>\n\n    <event name=\"finished\">\n      <description summary=\"this data control is no longer valid\">\n        This data control object is no longer valid and should be destroyed by\n        the client.\n      </description>\n    </event>\n\n    <event name=\"primary_selection\">\n      <description summary=\"advertise new primary selection\">\n        The primary_selection event is sent out to notify the client of a new\n        ext_data_control_offer for the primary selection for this device. The\n        ext_data_control_device.data_offer and the ext_data_control_offer.offer\n        events are sent out immediately before this event to introduce the data\n        offer object. The primary_selection event is sent to a client when a\n        new primary selection is set. The ext_data_control_offer is valid until\n        a new ext_data_control_offer or NULL is received. The client must\n        destroy the previous primary selection ext_data_control_offer, if any,\n        upon receiving this event. Regardless, the previous primary selection\n        will be ignored once a new primary selection ext_data_control_offer is\n        received.\n\n        If the compositor supports primary selection, the first\n        primary_selection event is sent upon binding the\n        ext_data_control_device object.\n      </description>\n      <arg name=\"id\" type=\"object\" interface=\"ext_data_control_offer_v1\"\n        allow-null=\"true\"/>\n    </event>\n\n    <request name=\"set_primary_selection\">\n      <description summary=\"copy data to the primary selection\">\n        This request asks the compositor to set the primary selection to the\n        data from the source on behalf of the client.\n\n        The given source may not be used in any further set_selection or\n        set_primary_selection requests. Attempting to use a previously used\n        source triggers the used_source protocol error.\n\n        To unset the primary selection, set the source to NULL.\n\n        The compositor will ignore this request if it does not support primary\n        selection.\n      </description>\n      <arg name=\"source\" type=\"object\" interface=\"ext_data_control_source_v1\"\n        allow-null=\"true\"/>\n    </request>\n\n    <enum name=\"error\">\n      <entry name=\"used_source\" value=\"1\"\n        summary=\"source given to set_selection or set_primary_selection was already used before\"/>\n    </enum>\n  </interface>\n\n  <interface name=\"ext_data_control_source_v1\" version=\"1\">\n    <description summary=\"offer to transfer data\">\n      The ext_data_control_source object is the source side of a\n      ext_data_control_offer. It is created by the source client in a data\n      transfer and provides a way to describe the offered data and a way to\n      respond to requests to transfer the data.\n    </description>\n\n    <enum name=\"error\">\n      <entry name=\"invalid_offer\" value=\"1\"\n        summary=\"offer sent after ext_data_control_device.set_selection\"/>\n    </enum>\n\n    <request name=\"offer\">\n      <description summary=\"add an offered MIME type\">\n        This request adds a MIME type to the set of MIME types advertised to\n        targets. Can be called several times to offer multiple types.\n\n        Calling this after ext_data_control_device.set_selection is a protocol\n        error.\n      </description>\n      <arg name=\"mime_type\" type=\"string\"\n        summary=\"MIME type offered by the data source\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"destroy this source\">\n        Destroys the data source object.\n      </description>\n    </request>\n\n    <event name=\"send\">\n      <description summary=\"send the data\">\n        Request for data from the client. Send the data as the specified MIME\n        type over the passed file descriptor, then close it.\n      </description>\n      <arg name=\"mime_type\" type=\"string\" summary=\"MIME type for the data\"/>\n      <arg name=\"fd\" type=\"fd\" summary=\"file descriptor for the data\"/>\n    </event>\n\n    <event name=\"cancelled\">\n      <description summary=\"selection was cancelled\">\n        This data source is no longer valid. The data source has been replaced\n        by another data source.\n\n        The client should clean up and destroy this data source.\n      </description>\n    </event>\n  </interface>\n\n  <interface name=\"ext_data_control_offer_v1\" version=\"1\">\n    <description summary=\"offer to transfer data\">\n      A ext_data_control_offer represents a piece of data offered for transfer\n      by another client (the source client). The offer describes the different\n      MIME types that the data can be converted to and provides the mechanism\n      for transferring the data directly from the source client.\n    </description>\n\n    <request name=\"receive\">\n      <description summary=\"request that the data is transferred\">\n        To transfer the offered data, the client issues this request and\n        indicates the MIME type it wants to receive. The transfer happens\n        through the passed file descriptor (typically created with the pipe\n        system call). The source client writes the data in the MIME type\n        representation requested and then closes the file descriptor.\n\n        The receiving client reads from the read end of the pipe until EOF and\n        then closes its end, at which point the transfer is complete.\n\n        This request may happen multiple times for different MIME types.\n      </description>\n      <arg name=\"mime_type\" type=\"string\"\n        summary=\"MIME type desired by receiver\"/>\n      <arg name=\"fd\" type=\"fd\" summary=\"file descriptor for data transfer\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"destroy this offer\">\n        Destroys the data offer object.\n      </description>\n    </request>\n\n    <event name=\"offer\">\n      <description summary=\"advertise offered MIME type\">\n        Sent immediately after creating the ext_data_control_offer object.\n        One event per offered MIME type.\n      </description>\n      <arg name=\"mime_type\" type=\"string\" summary=\"offered MIME type\"/>\n    </event>\n  </interface>\n</protocol>\n"
  },
  {
    "path": "unix/w0vncserver/wayland/protocols/ext-foreign-toplevel-list-v1.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<protocol name=\"ext_foreign_toplevel_list_v1\">\n  <copyright>\n    Copyright © 2018 Ilia Bozhinov\n    Copyright © 2020 Isaac Freund\n    Copyright © 2022 wb9688\n    Copyright © 2023 i509VCB\n\n    Permission to use, copy, modify, distribute, and sell this\n    software and its documentation for any purpose is hereby granted\n    without fee, provided that the above copyright notice appear in\n    all copies and that both that copyright notice and this permission\n    notice appear in supporting documentation, and that the name of\n    the copyright holders not be used in advertising or publicity\n    pertaining to distribution of the software without specific,\n    written prior permission.  The copyright holders make no\n    representations about the suitability of this software for any\n    purpose.  It is provided \"as is\" without express or implied\n    warranty.\n\n    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS\n    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\n    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\n    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN\n    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\n    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\n    THIS SOFTWARE.\n  </copyright>\n\n  <description summary=\"list toplevels\">\n    The purpose of this protocol is to provide protocol object handles for\n    toplevels, possibly originating from another client.\n\n    This protocol is intentionally minimalistic and expects additional\n    functionality (e.g. creating a screencopy source from a toplevel handle,\n    getting information about the state of the toplevel) to be implemented\n    in extension protocols.\n\n    The compositor may choose to restrict this protocol to a special client\n    launched by the compositor itself or expose it to all clients,\n    this is compositor policy.\n\n    The key words \"must\", \"must not\", \"required\", \"shall\", \"shall not\",\n    \"should\", \"should not\", \"recommended\",  \"may\", and \"optional\" in this\n    document are to be interpreted as described in IETF RFC 2119.\n\n    Warning! The protocol described in this file is currently in the testing\n    phase. Backward compatible changes may be added together with the\n    corresponding interface version bump. Backward incompatible changes can\n    only be done by creating a new major version of the extension.\n  </description>\n\n  <interface name=\"ext_foreign_toplevel_list_v1\" version=\"1\">\n    <description summary=\"list toplevels\">\n      A toplevel is defined as a surface with a role similar to xdg_toplevel.\n      XWayland surfaces may be treated like toplevels in this protocol.\n\n      After a client binds the ext_foreign_toplevel_list_v1, each mapped\n      toplevel window will be sent using the ext_foreign_toplevel_list_v1.toplevel\n      event.\n\n      Clients which only care about the current state can perform a roundtrip after\n      binding this global.\n\n      For each instance of ext_foreign_toplevel_list_v1, the compositor must\n      create a new ext_foreign_toplevel_handle_v1 object for each mapped toplevel.\n\n      If a compositor implementation sends the ext_foreign_toplevel_list_v1.finished\n      event after the global is bound, the compositor must not send any\n      ext_foreign_toplevel_list_v1.toplevel events.\n    </description>\n\n    <event name=\"toplevel\">\n      <description summary=\"a toplevel has been created\">\n        This event is emitted whenever a new toplevel window is created. It is\n        emitted for all toplevels, regardless of the app that has created them.\n\n        All initial properties of the toplevel (identifier, title, app_id) will be sent\n        immediately after this event using the corresponding events for\n        ext_foreign_toplevel_handle_v1. The compositor will use the\n        ext_foreign_toplevel_handle_v1.done event to indicate when all data has\n        been sent.\n      </description>\n      <arg name=\"toplevel\" type=\"new_id\" interface=\"ext_foreign_toplevel_handle_v1\"/>\n    </event>\n\n    <event name=\"finished\">\n      <description summary=\"the compositor has finished with the toplevel manager\">\n        This event indicates that the compositor is done sending events\n        to this object. The client should destroy the object.\n        See ext_foreign_toplevel_list_v1.destroy for more information.\n\n        The compositor must not send any more toplevel events after this event.\n      </description>\n    </event>\n\n    <request name=\"stop\">\n      <description summary=\"stop sending events\">\n        This request indicates that the client no longer wishes to receive\n        events for new toplevels.\n\n        The Wayland protocol is asynchronous, meaning the compositor may send\n        further toplevel events until the stop request is processed.\n        The client should wait for a ext_foreign_toplevel_list_v1.finished\n        event before destroying this object.\n      </description>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"destroy the ext_foreign_toplevel_list_v1 object\">\n        This request should be called either when the client will no longer\n        use the ext_foreign_toplevel_list_v1 or after the finished event\n        has been received to allow destruction of the object.\n\n        If a client wishes to destroy this object it should send a\n        ext_foreign_toplevel_list_v1.stop request and wait for a ext_foreign_toplevel_list_v1.finished\n        event, then destroy the handles and then this object.\n      </description>\n    </request>\n  </interface>\n\n  <interface name=\"ext_foreign_toplevel_handle_v1\" version=\"1\">\n    <description summary=\"a mapped toplevel\">\n      A ext_foreign_toplevel_handle_v1 object represents a mapped toplevel\n      window. A single app may have multiple mapped toplevels.\n    </description>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"destroy the ext_foreign_toplevel_handle_v1 object\">\n        This request should be used when the client will no longer use the handle\n        or after the closed event has been received to allow destruction of the\n        object.\n\n        When a handle is destroyed, a new handle may not be created by the server\n        until the toplevel is unmapped and then remapped. Destroying a toplevel handle\n        is not recommended unless the client is cleaning up child objects\n        before destroying the ext_foreign_toplevel_list_v1 object, the toplevel\n        was closed or the toplevel handle will not be used in the future.\n\n        Other protocols which extend the ext_foreign_toplevel_handle_v1\n        interface should require destructors for extension interfaces be\n        called before allowing the toplevel handle to be destroyed.\n      </description>\n    </request>\n\n    <event name=\"closed\">\n      <description summary=\"the toplevel has been closed\">\n        The server will emit no further events on the ext_foreign_toplevel_handle_v1\n        after this event. Any requests received aside from the destroy request must\n        be ignored. Upon receiving this event, the client should destroy the handle.\n\n        Other protocols which extend the ext_foreign_toplevel_handle_v1\n        interface must also ignore requests other than destructors.\n      </description>\n    </event>\n\n    <event name=\"done\">\n      <description summary=\"all information about the toplevel has been sent\">\n        This event is sent after all changes in the toplevel state have\n        been sent.\n\n        This allows changes to the ext_foreign_toplevel_handle_v1 properties\n        to be atomically applied. Other protocols which extend the\n        ext_foreign_toplevel_handle_v1 interface may use this event to also\n        atomically apply any pending state.\n\n        This event must not be sent after the ext_foreign_toplevel_handle_v1.closed\n        event.\n      </description>\n    </event>\n\n    <event name=\"title\">\n      <description summary=\"title change\">\n        The title of the toplevel has changed.\n\n        The configured state must not be applied immediately. See\n        ext_foreign_toplevel_handle_v1.done for details.\n      </description>\n      <arg name=\"title\" type=\"string\"/>\n    </event>\n\n    <event name=\"app_id\">\n      <description summary=\"app_id change\">\n        The app id of the toplevel has changed.\n\n        The configured state must not be applied immediately. See\n        ext_foreign_toplevel_handle_v1.done for details.\n      </description>\n      <arg name=\"app_id\" type=\"string\"/>\n    </event>\n\n    <event name=\"identifier\">\n      <description summary=\"a stable identifier for a toplevel\">\n        This identifier is used to check if two or more toplevel handles belong\n        to the same toplevel.\n\n        The identifier is useful for command line tools or privileged clients\n        which may need to reference an exact toplevel across processes or\n        instances of the ext_foreign_toplevel_list_v1 global.\n\n        The compositor must only send this event when the handle is created.\n\n        The identifier must be unique per toplevel and it's handles. Two different\n        toplevels must not have the same identifier. The identifier is only valid\n        as long as the toplevel is mapped. If the toplevel is unmapped the identifier\n        must not be reused. An identifier must not be reused by the compositor to\n        ensure there are no races when sharing identifiers between processes.\n\n        An identifier is a string that contains up to 32 printable ASCII bytes.\n        An identifier must not be an empty string. It is recommended that a\n        compositor includes an opaque generation value in identifiers. How the\n        generation value is used when generating the identifier is implementation\n        dependent.\n      </description>\n      <arg name=\"identifier\" type=\"string\"/>\n    </event>\n  </interface>\n</protocol>\n"
  },
  {
    "path": "unix/w0vncserver/wayland/protocols/ext-image-capture-source-v1.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<protocol name=\"ext_image_capture_source_v1\">\n  <copyright>\n    Copyright © 2022 Andri Yngvason\n    Copyright © 2024 Simon Ser\n\n    Permission is hereby granted, free of charge, to any person obtaining a\n    copy of this software and associated documentation files (the \"Software\"),\n    to deal in the Software without restriction, including without limitation\n    the rights to use, copy, modify, merge, publish, distribute, sublicense,\n    and/or sell copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice (including the next\n    paragraph) shall be included in all copies or substantial portions of the\n    Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n  </copyright>\n\n  <description summary=\"opaque image capture source objects\">\n    This protocol serves as an intermediary between capturing protocols and\n    potential image capture sources such as outputs and toplevels.\n\n    This protocol may be extended to support more image capture sources in the\n    future, thereby adding those image capture sources to other protocols that\n    use the image capture source object without having to modify those\n    protocols.\n\n    Warning! The protocol described in this file is currently in the testing\n    phase. Backward compatible changes may be added together with the\n    corresponding interface version bump. Backward incompatible changes can\n    only be done by creating a new major version of the extension.\n  </description>\n\n  <interface name=\"ext_image_capture_source_v1\" version=\"1\">\n    <description summary=\"opaque image capture source object\">\n      The image capture source object is an opaque descriptor for a capturable\n      resource.  This resource may be any sort of entity from which an image\n      may be derived.\n\n      Note, because ext_image_capture_source_v1 objects are created from multiple\n      independent factory interfaces, the ext_image_capture_source_v1 interface is\n      frozen at version 1.\n    </description>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"delete this object\">\n        Destroys the image capture source. This request may be sent at any time\n        by the client.\n      </description>\n    </request>\n  </interface>\n\n  <interface name=\"ext_output_image_capture_source_manager_v1\" version=\"1\">\n    <description summary=\"image capture source manager for outputs\">\n      A manager for creating image capture source objects for wl_output objects.\n    </description>\n\n    <request name=\"create_source\">\n      <description summary=\"create source object for output\">\n        Creates a source object for an output. Images captured from this source\n        will show the same content as the output. Some elements may be omitted,\n        such as cursors and overlays that have been marked as transparent to\n        capturing.\n      </description>\n      <arg name=\"source\" type=\"new_id\" interface=\"ext_image_capture_source_v1\"/>\n      <arg name=\"output\" type=\"object\" interface=\"wl_output\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"delete this object\">\n        Destroys the manager. This request may be sent at any time by the client\n        and objects created by the manager will remain valid after its\n        destruction.\n      </description>\n    </request>\n  </interface>\n\n  <interface name=\"ext_foreign_toplevel_image_capture_source_manager_v1\" version=\"1\">\n    <description summary=\"image capture source manager for foreign toplevels\">\n      A manager for creating image capture source objects for\n      ext_foreign_toplevel_handle_v1 objects.\n    </description>\n\n    <request name=\"create_source\">\n      <description summary=\"create source object for foreign toplevel\">\n        Creates a source object for a foreign toplevel handle. Images captured\n        from this source will show the same content as the toplevel.\n      </description>\n      <arg name=\"source\" type=\"new_id\" interface=\"ext_image_capture_source_v1\"/>\n      <arg name=\"toplevel_handle\" type=\"object\" interface=\"ext_foreign_toplevel_handle_v1\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"delete this object\">\n        Destroys the manager. This request may be sent at any time by the client\n        and objects created by the manager will remain valid after its\n        destruction.\n      </description>\n    </request>\n  </interface>\n</protocol>\n"
  },
  {
    "path": "unix/w0vncserver/wayland/protocols/ext-image-copy-capture-v1.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<protocol name=\"ext_image_copy_capture_v1\">\n  <copyright>\n    Copyright © 2021-2023 Andri Yngvason\n    Copyright © 2024 Simon Ser\n\n    Permission is hereby granted, free of charge, to any person obtaining a\n    copy of this software and associated documentation files (the \"Software\"),\n    to deal in the Software without restriction, including without limitation\n    the rights to use, copy, modify, merge, publish, distribute, sublicense,\n    and/or sell copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice (including the next\n    paragraph) shall be included in all copies or substantial portions of the\n    Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n  </copyright>\n\n  <description summary=\"image capturing into client buffers\">\n    This protocol allows clients to ask the compositor to capture image sources\n    such as outputs and toplevels into user submitted buffers.\n\n    Warning! The protocol described in this file is currently in the testing\n    phase. Backward compatible changes may be added together with the\n    corresponding interface version bump. Backward incompatible changes can\n    only be done by creating a new major version of the extension.\n  </description>\n\n  <interface name=\"ext_image_copy_capture_manager_v1\" version=\"1\">\n    <description summary=\"manager to inform clients and begin capturing\">\n      This object is a manager which offers requests to start capturing from a\n      source.\n    </description>\n\n    <enum name=\"error\">\n      <entry name=\"invalid_option\" value=\"1\" summary=\"invalid option flag\"/>\n    </enum>\n\n    <enum name=\"options\" bitfield=\"true\">\n      <entry name=\"paint_cursors\" value=\"1\" summary=\"paint cursors onto captured frames\"/>\n    </enum>\n\n    <request name=\"create_session\">\n      <description summary=\"capture an image capture source\">\n        Create a capturing session for an image capture source.\n\n        If the paint_cursors option is set, cursors shall be composited onto\n        the captured frame. The cursor must not be composited onto the frame\n        if this flag is not set.\n\n        If the options bitfield is invalid, the invalid_option protocol error\n        is sent.\n      </description>\n      <arg name=\"session\" type=\"new_id\" interface=\"ext_image_copy_capture_session_v1\"/>\n      <arg name=\"source\" type=\"object\" interface=\"ext_image_capture_source_v1\"/>\n      <arg name=\"options\" type=\"uint\" enum=\"options\"/>\n    </request>\n\n    <request name=\"create_pointer_cursor_session\">\n      <description summary=\"capture the pointer cursor of an image capture source\">\n        Create a cursor capturing session for the pointer of an image capture\n        source.\n      </description>\n      <arg name=\"session\" type=\"new_id\" interface=\"ext_image_copy_capture_cursor_session_v1\"/>\n      <arg name=\"source\" type=\"object\" interface=\"ext_image_capture_source_v1\"/>\n      <arg name=\"pointer\" type=\"object\" interface=\"wl_pointer\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"destroy the manager\">\n        Destroy the manager object.\n\n        Other objects created via this interface are unaffected.\n      </description>\n    </request>\n  </interface>\n\n  <interface name=\"ext_image_copy_capture_session_v1\" version=\"1\">\n    <description summary=\"image copy capture session\">\n      This object represents an active image copy capture session.\n\n      After a capture session is created, buffer constraint events will be\n      emitted from the compositor to tell the client which buffer types and\n      formats are supported for reading from the session. The compositor may\n      re-send buffer constraint events whenever they change.\n\n      To advertise buffer constraints, the compositor must send in no\n      particular order: zero or more shm_format and dmabuf_format events, zero\n      or one dmabuf_device event, and exactly one buffer_size event. Then the\n      compositor must send a done event.\n\n      When the client has received all the buffer constraints, it can create a\n      buffer accordingly, attach it to the capture session using the\n      attach_buffer request, set the buffer damage using the damage_buffer\n      request and then send the capture request.\n    </description>\n\n    <enum name=\"error\">\n      <entry name=\"duplicate_frame\" value=\"1\"\n        summary=\"create_frame sent before destroying previous frame\"/>\n    </enum>\n\n    <event name=\"buffer_size\">\n      <description summary=\"image capture source dimensions\">\n        Provides the dimensions of the source image in buffer pixel coordinates.\n\n        The client must attach buffers that match this size.\n      </description>\n      <arg name=\"width\" type=\"uint\" summary=\"buffer width\"/>\n      <arg name=\"height\" type=\"uint\" summary=\"buffer height\"/>\n    </event>\n\n    <event name=\"shm_format\">\n      <description summary=\"shm buffer format\">\n        Provides the format that must be used for shared-memory buffers.\n\n        This event may be emitted multiple times, in which case the client may\n        choose any given format.\n      </description>\n      <arg name=\"format\" type=\"uint\" enum=\"wl_shm.format\" summary=\"shm format\"/>\n    </event>\n\n    <event name=\"dmabuf_device\">\n      <description summary=\"dma-buf device\">\n        This event advertises the device buffers must be allocated on for\n        dma-buf buffers.\n\n        In general the device is a DRM node. The DRM node type (primary vs.\n        render) is unspecified. Clients must not rely on the compositor sending\n        a particular node type. Clients cannot check two devices for equality\n        by comparing the dev_t value.\n      </description>\n      <arg name=\"device\" type=\"array\" summary=\"device dev_t value\"/>\n    </event>\n\n    <event name=\"dmabuf_format\">\n      <description summary=\"dma-buf format\">\n        Provides the format that must be used for dma-buf buffers.\n\n        The client may choose any of the modifiers advertised in the array of\n        64-bit unsigned integers.\n\n        This event may be emitted multiple times, in which case the client may\n        choose any given format.\n      </description>\n      <arg name=\"format\" type=\"uint\" summary=\"drm format code\"/>\n      <arg name=\"modifiers\" type=\"array\" summary=\"drm format modifiers\"/>\n    </event>\n\n    <event name=\"done\">\n      <description summary=\"all constraints have been sent\">\n        This event is sent once when all buffer constraint events have been\n        sent.\n\n        The compositor must always end a batch of buffer constraint events with\n        this event, regardless of whether it sends the initial constraints or\n        an update.\n      </description>\n    </event>\n\n    <event name=\"stopped\">\n      <description summary=\"session is no longer available\">\n        This event indicates that the capture session has stopped and is no\n        longer available. This can happen in a number of cases, e.g. when the\n        underlying source is destroyed, if the user decides to end the image\n        capture, or if an unrecoverable runtime error has occurred.\n\n        The client should destroy the session after receiving this event.\n      </description>\n    </event>\n\n    <request name=\"create_frame\">\n      <description summary=\"create a frame\">\n        Create a capture frame for this session.\n\n        At most one frame object can exist for a given session at any time. If\n        a client sends a create_frame request before a previous frame object\n        has been destroyed, the duplicate_frame protocol error is raised.\n      </description>\n      <arg name=\"frame\" type=\"new_id\" interface=\"ext_image_copy_capture_frame_v1\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"delete this object\">\n        Destroys the session. This request can be sent at any time by the\n        client.\n\n        This request doesn't affect ext_image_copy_capture_frame_v1 objects created by\n        this object.\n      </description>\n    </request>\n  </interface>\n\n  <interface name=\"ext_image_copy_capture_frame_v1\" version=\"1\">\n    <description summary=\"image capture frame\">\n      This object represents an image capture frame.\n\n      The client should attach a buffer, damage the buffer, and then send a\n      capture request.\n\n      If the capture is successful, the compositor must send the frame metadata\n      (transform, damage, presentation_time in any order) followed by the ready\n      event.\n\n      If the capture fails, the compositor must send the failed event.\n    </description>\n\n    <enum name=\"error\">\n      <entry name=\"no_buffer\" value=\"1\" summary=\"capture sent without attach_buffer\"/>\n      <entry name=\"invalid_buffer_damage\" value=\"2\" summary=\"invalid buffer damage\"/>\n      <entry name=\"already_captured\" value=\"3\" summary=\"capture request has been sent\"/>\n    </enum>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"destroy this object\">\n        Destroys the frame. This request can be sent at any time by the\n        client.\n      </description>\n    </request>\n\n    <request name=\"attach_buffer\">\n      <description summary=\"attach buffer to session\">\n        Attach a buffer to the session.\n\n        The wl_buffer.release request is unused.\n\n        The new buffer replaces any previously attached buffer.\n\n        This request must not be sent after capture, or else the\n        already_captured protocol error is raised.\n      </description>\n      <arg name=\"buffer\" type=\"object\" interface=\"wl_buffer\"/>\n    </request>\n\n    <request name=\"damage_buffer\">\n      <description summary=\"damage buffer\">\n        Apply damage to the buffer which is to be captured next. This request\n        may be sent multiple times to describe a region.\n\n        The client indicates the accumulated damage since this wl_buffer was\n        last captured. During capture, the compositor will update the buffer\n        with at least the union of the region passed by the client and the\n        region advertised by ext_image_copy_capture_frame_v1.damage.\n\n        When a wl_buffer is captured for the first time, or when the client\n        doesn't track damage, the client must damage the whole buffer.\n\n        This is for optimisation purposes. The compositor may use this\n        information to reduce copying.\n\n        These coordinates originate from the upper left corner of the buffer.\n\n        If x or y are strictly negative, or if width or height are negative or\n        zero, the invalid_buffer_damage protocol error is raised.\n\n        This request must not be sent after capture, or else the\n        already_captured protocol error is raised.\n      </description>\n      <arg name=\"x\" type=\"int\" summary=\"region x coordinate\"/>\n      <arg name=\"y\" type=\"int\" summary=\"region y coordinate\"/>\n      <arg name=\"width\" type=\"int\" summary=\"region width\"/>\n      <arg name=\"height\" type=\"int\" summary=\"region height\"/>\n    </request>\n\n    <request name=\"capture\">\n      <description summary=\"capture a frame\">\n        Capture a frame.\n\n        Unless this is the first successful captured frame performed in this\n        session, the compositor may wait an indefinite amount of time for the\n        source content to change before performing the copy.\n\n        This request may only be sent once, or else the already_captured\n        protocol error is raised. A buffer must be attached before this request\n        is sent, or else the no_buffer protocol error is raised.\n      </description>\n    </request>\n\n    <event name=\"transform\">\n      <description summary=\"buffer transform\">\n        This event is sent before the ready event and holds the transform that\n        the compositor has applied to the buffer contents.\n      </description>\n      <arg name=\"transform\" type=\"uint\" enum=\"wl_output.transform\"/>\n    </event>\n\n    <event name=\"damage\">\n      <description summary=\"buffer damaged region\">\n        This event is sent before the ready event. It may be generated multiple\n        times to describe a region.\n\n        The first captured frame in a session will always carry full damage.\n        Subsequent frames' damaged regions describe which parts of the buffer\n        have changed since the last ready event.\n\n        These coordinates originate in the upper left corner of the buffer.\n      </description>\n      <arg name=\"x\" type=\"int\" summary=\"damage x coordinate\"/>\n      <arg name=\"y\" type=\"int\" summary=\"damage y coordinate\"/>\n      <arg name=\"width\" type=\"int\" summary=\"damage width\"/>\n      <arg name=\"height\" type=\"int\" summary=\"damage height\"/>\n    </event>\n\n    <event name=\"presentation_time\">\n      <description summary=\"presentation time of the frame\">\n        This event indicates the time at which the frame is presented to the\n        output in system monotonic time. This event is sent before the ready\n        event.\n\n        The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples,\n        each component being an unsigned 32-bit value. Whole seconds are in\n        tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo,\n        and the additional fractional part in tv_nsec as nanoseconds. Hence,\n        for valid timestamps tv_nsec must be in [0, 999999999].\n      </description>\n      <arg name=\"tv_sec_hi\" type=\"uint\"\n           summary=\"high 32 bits of the seconds part of the timestamp\"/>\n      <arg name=\"tv_sec_lo\" type=\"uint\"\n           summary=\"low 32 bits of the seconds part of the timestamp\"/>\n      <arg name=\"tv_nsec\" type=\"uint\"\n           summary=\"nanoseconds part of the timestamp\"/>\n    </event>\n\n    <event name=\"ready\">\n      <description summary=\"frame is available for reading\">\n        Called as soon as the frame is copied, indicating it is available\n        for reading.\n\n        The buffer may be re-used by the client after this event.\n\n        After receiving this event, the client must destroy the object.\n      </description>\n    </event>\n\n    <enum name=\"failure_reason\">\n      <entry name=\"unknown\" value=\"0\">\n        <description summary=\"unknown runtime error\">\n          An unspecified runtime error has occurred. The client may retry.\n        </description>\n      </entry>\n      <entry name=\"buffer_constraints\" value=\"1\">\n        <description summary=\"buffer constraints mismatch\">\n          The buffer submitted by the client doesn't match the latest session\n          constraints. The client should re-allocate its buffers and retry.\n        </description>\n      </entry>\n      <entry name=\"stopped\" value=\"2\">\n        <description summary=\"session is no longer available\">\n          The session has stopped. See ext_image_copy_capture_session_v1.stopped.\n        </description>\n      </entry>\n    </enum>\n\n    <event name=\"failed\">\n      <description summary=\"capture failed\">\n        This event indicates that the attempted frame copy has failed.\n\n        After receiving this event, the client must destroy the object.\n      </description>\n      <arg name=\"reason\" type=\"uint\" enum=\"failure_reason\"/>\n    </event>\n  </interface>\n\n  <interface name=\"ext_image_copy_capture_cursor_session_v1\" version=\"1\">\n    <description summary=\"cursor capture session\">\n      This object represents a cursor capture session. It extends the base\n      capture session with cursor-specific metadata.\n    </description>\n\n    <enum name=\"error\">\n      <entry name=\"duplicate_session\" value=\"1\" summary=\"get_capture_session sent twice\"/>\n    </enum>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"delete this object\">\n        Destroys the session. This request can be sent at any time by the\n        client.\n\n        This request doesn't affect ext_image_copy_capture_frame_v1 objects created by\n        this object.\n      </description>\n    </request>\n\n    <request name=\"get_capture_session\">\n      <description summary=\"get image copy capturer session\">\n        Gets the image copy capture session for this cursor session.\n\n        The session will produce frames of the cursor image. The compositor may\n        pause the session when the cursor leaves the captured area.\n\n        This request must not be sent more than once, or else the\n        duplicate_session protocol error is raised.\n      </description>\n      <arg name=\"session\" type=\"new_id\" interface=\"ext_image_copy_capture_session_v1\"/>\n    </request>\n\n    <event name=\"enter\">\n      <description summary=\"cursor entered captured area\">\n        Sent when a cursor enters the captured area. It shall be generated\n        before the \"position\" and \"hotspot\" events when and only when a cursor\n        enters the area.\n\n        The cursor enters the captured area when the cursor image intersects\n        with the captured area. Note, this is different from e.g.\n        wl_pointer.enter.\n      </description>\n    </event>\n\n    <event name=\"leave\">\n      <description summary=\"cursor left captured area\">\n        Sent when a cursor leaves the captured area. No \"position\" or \"hotspot\"\n        event is generated for the cursor until the cursor enters the captured\n        area again.\n      </description>\n    </event>\n\n    <event name=\"position\">\n      <description summary=\"position changed\">\n        Cursors outside the image capture source do not get captured and no\n        event will be generated for them.\n\n        The given position is the position of the cursor's hotspot and it is\n        relative to the main buffer's top left corner in transformed buffer\n        pixel coordinates. The coordinates may be negative or greater than the\n        main buffer size.\n      </description>\n      <arg name=\"x\" type=\"int\" summary=\"position x coordinates\"/>\n      <arg name=\"y\" type=\"int\" summary=\"position y coordinates\"/>\n    </event>\n\n    <event name=\"hotspot\">\n      <description summary=\"hotspot changed\">\n        The hotspot describes the offset between the cursor image and the\n        position of the input device.\n\n        The given coordinates are the hotspot's offset from the origin in\n        buffer coordinates.\n\n        Clients should not apply the hotspot immediately: the hotspot becomes\n        effective when the next ext_image_copy_capture_frame_v1.ready event is received.\n\n        Compositors may delay this event until the client captures a new frame.\n      </description>\n      <arg name=\"x\" type=\"int\" summary=\"hotspot x coordinates\"/>\n      <arg name=\"y\" type=\"int\" summary=\"hotspot y coordinates\"/>\n    </event>\n  </interface>\n</protocol>\n"
  },
  {
    "path": "unix/w0vncserver/wayland/protocols/virtual-keyboard-unstable-v1.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<protocol name=\"virtual_keyboard_unstable_v1\">\n  <copyright>\n    Copyright © 2008-2011  Kristian Høgsberg\n    Copyright © 2010-2013  Intel Corporation\n    Copyright © 2012-2013  Collabora, Ltd.\n    Copyright © 2018       Purism SPC\n\n    Permission is hereby granted, free of charge, to any person obtaining a\n    copy of this software and associated documentation files (the \"Software\"),\n    to deal in the Software without restriction, including without limitation\n    the rights to use, copy, modify, merge, publish, distribute, sublicense,\n    and/or sell copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice (including the next\n    paragraph) shall be included in all copies or substantial portions of the\n    Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n  </copyright>\n\n  <interface name=\"zwp_virtual_keyboard_v1\" version=\"1\">\n    <description summary=\"virtual keyboard\">\n      The virtual keyboard provides an application with requests which emulate\n      the behaviour of a physical keyboard.\n\n      This interface can be used by clients on its own to provide raw input\n      events, or it can accompany the input method protocol.\n    </description>\n\n    <request name=\"keymap\">\n      <description summary=\"keyboard mapping\">\n        Provide a file descriptor to the compositor which can be\n        memory-mapped to provide a keyboard mapping description.\n\n        Format carries a value from the keymap_format enumeration.\n      </description>\n      <arg name=\"format\" type=\"uint\" summary=\"keymap format\"/>\n      <arg name=\"fd\" type=\"fd\" summary=\"keymap file descriptor\"/>\n      <arg name=\"size\" type=\"uint\" summary=\"keymap size, in bytes\"/>\n    </request>\n\n    <enum name=\"error\">\n      <entry name=\"no_keymap\" value=\"0\" summary=\"No keymap was set\"/>\n    </enum>\n\n    <request name=\"key\">\n      <description summary=\"key event\">\n        A key was pressed or released.\n        The time argument is a timestamp with millisecond granularity, with an\n        undefined base. All requests regarding a single object must share the\n        same clock.\n\n        Keymap must be set before issuing this request.\n\n        State carries a value from the key_state enumeration.\n      </description>\n      <arg name=\"time\" type=\"uint\" summary=\"timestamp with millisecond granularity\"/>\n      <arg name=\"key\" type=\"uint\" summary=\"key that produced the event\"/>\n      <arg name=\"state\" type=\"uint\" summary=\"physical state of the key\"/>\n    </request>\n\n    <request name=\"modifiers\">\n      <description summary=\"modifier and group state\">\n        Notifies the compositor that the modifier and/or group state has\n        changed, and it should update state.\n\n        The client should use wl_keyboard.modifiers event to synchronize its\n        internal state with seat state.\n\n        Keymap must be set before issuing this request.\n      </description>\n      <arg name=\"mods_depressed\" type=\"uint\" summary=\"depressed modifiers\"/>\n      <arg name=\"mods_latched\" type=\"uint\" summary=\"latched modifiers\"/>\n      <arg name=\"mods_locked\" type=\"uint\" summary=\"locked modifiers\"/>\n      <arg name=\"group\" type=\"uint\" summary=\"keyboard layout\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\" since=\"1\">\n      <description summary=\"destroy the virtual keyboard keyboard object\"/>\n    </request>\n  </interface>\n\n  <interface name=\"zwp_virtual_keyboard_manager_v1\" version=\"1\">\n    <description summary=\"virtual keyboard manager\">\n      A virtual keyboard manager allows an application to provide keyboard\n      input events as if they came from a physical keyboard.\n    </description>\n\n    <enum name=\"error\">\n      <entry name=\"unauthorized\" value=\"0\" summary=\"client not authorized to use the interface\"/>\n    </enum>\n\n    <request name=\"create_virtual_keyboard\">\n      <description summary=\"Create a new virtual keyboard\">\n        Creates a new virtual keyboard associated to a seat.\n\n        If the compositor enables a keyboard to perform arbitrary actions, it\n        should present an error when an untrusted client requests a new\n        keyboard.\n      </description>\n      <arg name=\"seat\" type=\"object\" interface=\"wl_seat\"/>\n      <arg name=\"id\" type=\"new_id\" interface=\"zwp_virtual_keyboard_v1\"/>\n    </request>\n  </interface>\n</protocol>\n"
  },
  {
    "path": "unix/w0vncserver/wayland/protocols/wlr-screencopy-unstable-v1.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<protocol name=\"wlr_screencopy_unstable_v1\">\n  <copyright>\n    Copyright © 2018 Simon Ser\n    Copyright © 2019 Andri Yngvason\n\n    Permission is hereby granted, free of charge, to any person obtaining a\n    copy of this software and associated documentation files (the \"Software\"),\n    to deal in the Software without restriction, including without limitation\n    the rights to use, copy, modify, merge, publish, distribute, sublicense,\n    and/or sell copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice (including the next\n    paragraph) shall be included in all copies or substantial portions of the\n    Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n  </copyright>\n\n  <description summary=\"screen content capturing on client buffers\">\n    This protocol allows clients to ask the compositor to copy part of the\n    screen content to a client buffer.\n\n    Warning! The protocol described in this file is experimental and\n    backward incompatible changes may be made. Backward compatible changes\n    may be added together with the corresponding interface version bump.\n    Backward incompatible changes are done by bumping the version number in\n    the protocol and interface names and resetting the interface version.\n    Once the protocol is to be declared stable, the 'z' prefix and the\n    version number in the protocol and interface names are removed and the\n    interface version number is reset.\n  </description>\n\n  <interface name=\"zwlr_screencopy_manager_v1\" version=\"3\">\n    <description summary=\"manager to inform clients and begin capturing\">\n      This object is a manager which offers requests to start capturing from a\n      source.\n    </description>\n\n    <request name=\"capture_output\">\n      <description summary=\"capture an output\">\n        Capture the next frame of an entire output.\n      </description>\n      <arg name=\"frame\" type=\"new_id\" interface=\"zwlr_screencopy_frame_v1\"/>\n      <arg name=\"overlay_cursor\" type=\"int\"\n        summary=\"composite cursor onto the frame\"/>\n      <arg name=\"output\" type=\"object\" interface=\"wl_output\"/>\n    </request>\n\n    <request name=\"capture_output_region\">\n      <description summary=\"capture an output's region\">\n        Capture the next frame of an output's region.\n\n        The region is given in output logical coordinates, see\n        xdg_output.logical_size. The region will be clipped to the output's\n        extents.\n      </description>\n      <arg name=\"frame\" type=\"new_id\" interface=\"zwlr_screencopy_frame_v1\"/>\n      <arg name=\"overlay_cursor\" type=\"int\"\n        summary=\"composite cursor onto the frame\"/>\n      <arg name=\"output\" type=\"object\" interface=\"wl_output\"/>\n      <arg name=\"x\" type=\"int\"/>\n      <arg name=\"y\" type=\"int\"/>\n      <arg name=\"width\" type=\"int\"/>\n      <arg name=\"height\" type=\"int\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"destroy the manager\">\n        All objects created by the manager will still remain valid, until their\n        appropriate destroy request has been called.\n      </description>\n    </request>\n  </interface>\n\n  <interface name=\"zwlr_screencopy_frame_v1\" version=\"3\">\n    <description summary=\"a frame ready for copy\">\n      This object represents a single frame.\n\n      When created, a series of buffer events will be sent, each representing a\n      supported buffer type. The \"buffer_done\" event is sent afterwards to\n      indicate that all supported buffer types have been enumerated. The client\n      will then be able to send a \"copy\" request. If the capture is successful,\n      the compositor will send a \"flags\" event followed by a \"ready\" event.\n\n      For objects version 2 or lower, wl_shm buffers are always supported, ie.\n      the \"buffer\" event is guaranteed to be sent.\n\n      If the capture failed, the \"failed\" event is sent. This can happen anytime\n      before the \"ready\" event.\n\n      Once either a \"ready\" or a \"failed\" event is received, the client should\n      destroy the frame.\n    </description>\n\n    <event name=\"buffer\">\n      <description summary=\"wl_shm buffer information\">\n        Provides information about wl_shm buffer parameters that need to be\n        used for this frame. This event is sent once after the frame is created\n        if wl_shm buffers are supported.\n      </description>\n      <arg name=\"format\" type=\"uint\" enum=\"wl_shm.format\" summary=\"buffer format\"/>\n      <arg name=\"width\" type=\"uint\" summary=\"buffer width\"/>\n      <arg name=\"height\" type=\"uint\" summary=\"buffer height\"/>\n      <arg name=\"stride\" type=\"uint\" summary=\"buffer stride\"/>\n    </event>\n\n    <request name=\"copy\">\n      <description summary=\"copy the frame\">\n        Copy the frame to the supplied buffer. The buffer must have the\n        correct size, see zwlr_screencopy_frame_v1.buffer and\n        zwlr_screencopy_frame_v1.linux_dmabuf. The buffer needs to have a\n        supported format.\n\n        If the frame is successfully copied, \"flags\" and \"ready\" events are\n        sent. Otherwise, a \"failed\" event is sent.\n      </description>\n      <arg name=\"buffer\" type=\"object\" interface=\"wl_buffer\"/>\n    </request>\n\n    <enum name=\"error\">\n      <entry name=\"already_used\" value=\"0\"\n        summary=\"the object has already been used to copy a wl_buffer\"/>\n      <entry name=\"invalid_buffer\" value=\"1\"\n        summary=\"buffer attributes are invalid\"/>\n    </enum>\n\n    <enum name=\"flags\" bitfield=\"true\">\n      <entry name=\"y_invert\" value=\"1\" summary=\"contents are y-inverted\"/>\n    </enum>\n\n    <event name=\"flags\">\n      <description summary=\"frame flags\">\n        Provides flags about the frame. This event is sent once before the\n        \"ready\" event.\n      </description>\n      <arg name=\"flags\" type=\"uint\" enum=\"flags\" summary=\"frame flags\"/>\n    </event>\n\n    <event name=\"ready\">\n      <description summary=\"indicates frame is available for reading\">\n        Called as soon as the frame is copied, indicating it is available\n        for reading. This event includes the time at which the presentation took place.\n\n        The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples,\n        each component being an unsigned 32-bit value. Whole seconds are in\n        tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo,\n        and the additional fractional part in tv_nsec as nanoseconds. Hence,\n        for valid timestamps tv_nsec must be in [0, 999999999]. The seconds part\n        may have an arbitrary offset at start.\n\n        After receiving this event, the client should destroy the object.\n      </description>\n      <arg name=\"tv_sec_hi\" type=\"uint\"\n           summary=\"high 32 bits of the seconds part of the timestamp\"/>\n      <arg name=\"tv_sec_lo\" type=\"uint\"\n           summary=\"low 32 bits of the seconds part of the timestamp\"/>\n      <arg name=\"tv_nsec\" type=\"uint\"\n           summary=\"nanoseconds part of the timestamp\"/>\n    </event>\n\n    <event name=\"failed\">\n      <description summary=\"frame copy failed\">\n        This event indicates that the attempted frame copy has failed.\n\n        After receiving this event, the client should destroy the object.\n      </description>\n    </event>\n\n    <request name=\"destroy\" type=\"destructor\">\n      <description summary=\"delete this object, used or not\">\n        Destroys the frame. This request can be sent at any time by the client.\n      </description>\n    </request>\n\n    <!-- Version 2 additions -->\n    <request name=\"copy_with_damage\" since=\"2\">\n      <description summary=\"copy the frame when it's damaged\">\n        Same as copy, except it waits until there is damage to copy.\n      </description>\n      <arg name=\"buffer\" type=\"object\" interface=\"wl_buffer\"/>\n    </request>\n\n    <event name=\"damage\" since=\"2\">\n      <description summary=\"carries the coordinates of the damaged region\">\n        This event is sent right before the ready event when copy_with_damage is\n        requested. It may be generated multiple times for each copy_with_damage\n        request.\n\n        The arguments describe a box around an area that has changed since the\n        last copy request that was derived from the current screencopy manager\n        instance.\n\n        The union of all regions received between the call to copy_with_damage\n        and a ready event is the total damage since the prior ready event.\n      </description>\n      <arg name=\"x\" type=\"uint\" summary=\"damaged x coordinates\"/>\n      <arg name=\"y\" type=\"uint\" summary=\"damaged y coordinates\"/>\n      <arg name=\"width\" type=\"uint\" summary=\"current width\"/>\n      <arg name=\"height\" type=\"uint\" summary=\"current height\"/>\n    </event>\n\n    <!-- Version 3 additions -->\n    <event name=\"linux_dmabuf\" since=\"3\">\n      <description summary=\"linux-dmabuf buffer information\">\n        Provides information about linux-dmabuf buffer parameters that need to\n        be used for this frame. This event is sent once after the frame is\n        created if linux-dmabuf buffers are supported.\n      </description>\n      <arg name=\"format\" type=\"uint\" summary=\"fourcc pixel format\"/>\n      <arg name=\"width\" type=\"uint\" summary=\"buffer width\"/>\n      <arg name=\"height\" type=\"uint\" summary=\"buffer height\"/>\n    </event>\n\n    <event name=\"buffer_done\" since=\"3\">\n      <description summary=\"all buffer types reported\">\n        This event is sent once after all buffer events have been sent.\n\n        The client should proceed to create a buffer of one of the supported\n        types, and send a \"copy\" request.\n      </description>\n    </event>\n  </interface>\n</protocol>\n"
  },
  {
    "path": "unix/w0vncserver/wayland/protocols/wlr-virtual-pointer-unstable-v1.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<protocol name=\"wlr_virtual_pointer_unstable_v1\">\n  <copyright>\n    Copyright © 2019 Josef Gajdusek\n\n    Permission is hereby granted, free of charge, to any person obtaining a\n    copy of this software and associated documentation files (the \"Software\"),\n    to deal in the Software without restriction, including without limitation\n    the rights to use, copy, modify, merge, publish, distribute, sublicense,\n    and/or sell copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice (including the next\n    paragraph) shall be included in all copies or substantial portions of the\n    Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n  </copyright>\n\n  <interface name=\"zwlr_virtual_pointer_v1\" version=\"2\">\n    <description summary=\"virtual pointer\">\n      This protocol allows clients to emulate a physical pointer device. The\n      requests are mostly mirror opposites of those specified in wl_pointer.\n    </description>\n\n    <enum name=\"error\">\n      <entry name=\"invalid_axis\" value=\"0\"\n        summary=\"client sent invalid axis enumeration value\" />\n      <entry name=\"invalid_axis_source\" value=\"1\"\n        summary=\"client sent invalid axis source enumeration value\" />\n    </enum>\n\n    <request name=\"motion\">\n      <description summary=\"pointer relative motion event\">\n        The pointer has moved by a relative amount to the previous request.\n\n        Values are in the global compositor space.\n      </description>\n      <arg name=\"time\" type=\"uint\" summary=\"timestamp with millisecond granularity\"/>\n      <arg name=\"dx\" type=\"fixed\" summary=\"displacement on the x-axis\"/>\n      <arg name=\"dy\" type=\"fixed\" summary=\"displacement on the y-axis\"/>\n    </request>\n\n    <request name=\"motion_absolute\">\n      <description summary=\"pointer absolute motion event\">\n        The pointer has moved in an absolute coordinate frame.\n\n        Value of x can range from 0 to x_extent, value of y can range from 0\n        to y_extent.\n      </description>\n      <arg name=\"time\" type=\"uint\" summary=\"timestamp with millisecond granularity\"/>\n      <arg name=\"x\" type=\"uint\" summary=\"position on the x-axis\"/>\n      <arg name=\"y\" type=\"uint\" summary=\"position on the y-axis\"/>\n      <arg name=\"x_extent\" type=\"uint\" summary=\"extent of the x-axis\"/>\n      <arg name=\"y_extent\" type=\"uint\" summary=\"extent of the y-axis\"/>\n    </request>\n\n    <request name=\"button\">\n      <description summary=\"button event\">\n        A button was pressed or released.\n      </description>\n      <arg name=\"time\" type=\"uint\" summary=\"timestamp with millisecond granularity\"/>\n      <arg name=\"button\" type=\"uint\" summary=\"button that produced the event\"/>\n      <arg name=\"state\" type=\"uint\" enum=\"wl_pointer.button_state\" summary=\"physical state of the button\"/>\n    </request>\n\n    <request name=\"axis\">\n      <description summary=\"axis event\">\n        Scroll and other axis requests.\n      </description>\n      <arg name=\"time\" type=\"uint\" summary=\"timestamp with millisecond granularity\"/>\n      <arg name=\"axis\" type=\"uint\" enum=\"wl_pointer.axis\" summary=\"axis type\"/>\n      <arg name=\"value\" type=\"fixed\" summary=\"length of vector in touchpad coordinates\"/>\n    </request>\n\n    <request name=\"frame\">\n      <description summary=\"end of a pointer event sequence\">\n        Indicates the set of events that logically belong together.\n      </description>\n    </request>\n\n    <request name=\"axis_source\">\n      <description summary=\"axis source event\">\n        Source information for scroll and other axis.\n      </description>\n      <arg name=\"axis_source\" type=\"uint\" enum=\"wl_pointer.axis_source\" summary=\"source of the axis event\"/>\n    </request>\n\n    <request name=\"axis_stop\">\n      <description summary=\"axis stop event\">\n        Stop notification for scroll and other axes.\n      </description>\n      <arg name=\"time\" type=\"uint\" summary=\"timestamp with millisecond granularity\"/>\n      <arg name=\"axis\" type=\"uint\" enum=\"wl_pointer.axis\" summary=\"the axis stopped with this event\"/>\n    </request>\n\n    <request name=\"axis_discrete\">\n      <description summary=\"axis click event\">\n        Discrete step information for scroll and other axes.\n\n        This event allows the client to extend data normally sent using the axis\n        event with discrete value.\n      </description>\n      <arg name=\"time\" type=\"uint\" summary=\"timestamp with millisecond granularity\"/>\n      <arg name=\"axis\" type=\"uint\" enum=\"wl_pointer.axis\" summary=\"axis type\"/>\n      <arg name=\"value\" type=\"fixed\" summary=\"length of vector in touchpad coordinates\"/>\n      <arg name=\"discrete\" type=\"int\" summary=\"number of steps\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\" since=\"1\">\n      <description summary=\"destroy the virtual pointer object\"/>\n    </request>\n  </interface>\n\n  <interface name=\"zwlr_virtual_pointer_manager_v1\" version=\"2\">\n    <description summary=\"virtual pointer manager\">\n      This object allows clients to create individual virtual pointer objects.\n    </description>\n\n    <request name=\"create_virtual_pointer\">\n      <description summary=\"Create a new virtual pointer\">\n        Creates a new virtual pointer. The optional seat is a suggestion to the\n        compositor.\n      </description>\n      <arg name=\"seat\" type=\"object\" interface=\"wl_seat\" allow-null=\"true\"/>\n      <arg name=\"id\" type=\"new_id\" interface=\"zwlr_virtual_pointer_v1\"/>\n    </request>\n\n    <request name=\"destroy\" type=\"destructor\" since=\"1\">\n      <description summary=\"destroy the virtual pointer manager\"/>\n    </request>\n\n    <!-- Version 2 additions -->\n    <request name=\"create_virtual_pointer_with_output\" since=\"2\">\n      <description summary=\"Create a new virtual pointer\">\n        Creates a new virtual pointer. The seat and the output arguments are\n        optional. If the seat argument is set, the compositor should assign the\n        input device to the requested seat. If the output argument is set, the\n        compositor should map the input device to the requested output.\n      </description>\n      <arg name=\"seat\" type=\"object\" interface=\"wl_seat\" allow-null=\"true\"/>\n      <arg name=\"output\" type=\"object\" interface=\"wl_output\" allow-null=\"true\"/>\n      <arg name=\"id\" type=\"new_id\" interface=\"zwlr_virtual_pointer_v1\"/>\n    </request>\n  </interface>\n</protocol>\n"
  },
  {
    "path": "unix/w0vncserver/xkb_to_qnum.c",
    "content": "/*\n * This file is auto-generated from keymaps.csv\n * Database checksum sha256(527727ef96d7103a8d7725a6ed9738812660b5a3f4aec086dd7b587b1ba9fcca)\n * To re-generate, run:\n *   keymap-gen code-map --lang=stdc keymaps.csv xkb qnum\n*/\nconst struct _code_map_xkb_to_qnum {\n  const char * from;\n  const unsigned short to;\n} code_map_xkb_to_qnum[] = {\n  {\"AB00\", 0x29}, /* xkb:AB00 (AB00) -> linux:41 (KEY_GRAVE) -> qnum:41 */\n  {\"AB01\", 0x2c}, /* xkb:AB01 (AB01) -> linux:44 (KEY_Z) -> qnum:44 */\n  {\"AB02\", 0x2d}, /* xkb:AB02 (AB02) -> linux:45 (KEY_X) -> qnum:45 */\n  {\"AB03\", 0x2e}, /* xkb:AB03 (AB03) -> linux:46 (KEY_C) -> qnum:46 */\n  {\"AB04\", 0x2f}, /* xkb:AB04 (AB04) -> linux:47 (KEY_V) -> qnum:47 */\n  {\"AB05\", 0x30}, /* xkb:AB05 (AB05) -> linux:48 (KEY_B) -> qnum:48 */\n  {\"AB06\", 0x31}, /* xkb:AB06 (AB06) -> linux:49 (KEY_N) -> qnum:49 */\n  {\"AB07\", 0x32}, /* xkb:AB07 (AB07) -> linux:50 (KEY_M) -> qnum:50 */\n  {\"AB08\", 0x33}, /* xkb:AB08 (AB08) -> linux:51 (KEY_COMMA) -> qnum:51 */\n  {\"AB09\", 0x34}, /* xkb:AB09 (AB09) -> linux:52 (KEY_DOT) -> qnum:52 */\n  {\"AB10\", 0x35}, /* xkb:AB10 (AB10) -> linux:53 (KEY_SLASH) -> qnum:53 */\n  {\"AB11\", 0x73}, /* xkb:AB11 (AB11) -> linux:89 (KEY_RO) -> qnum:115 */\n  {\"AC01\", 0x1e}, /* xkb:AC01 (AC01) -> linux:30 (KEY_A) -> qnum:30 */\n  {\"AC02\", 0x1f}, /* xkb:AC02 (AC02) -> linux:31 (KEY_S) -> qnum:31 */\n  {\"AC03\", 0x20}, /* xkb:AC03 (AC03) -> linux:32 (KEY_D) -> qnum:32 */\n  {\"AC04\", 0x21}, /* xkb:AC04 (AC04) -> linux:33 (KEY_F) -> qnum:33 */\n  {\"AC05\", 0x22}, /* xkb:AC05 (AC05) -> linux:34 (KEY_G) -> qnum:34 */\n  {\"AC06\", 0x23}, /* xkb:AC06 (AC06) -> linux:35 (KEY_H) -> qnum:35 */\n  {\"AC07\", 0x24}, /* xkb:AC07 (AC07) -> linux:36 (KEY_J) -> qnum:36 */\n  {\"AC08\", 0x25}, /* xkb:AC08 (AC08) -> linux:37 (KEY_K) -> qnum:37 */\n  {\"AC09\", 0x26}, /* xkb:AC09 (AC09) -> linux:38 (KEY_L) -> qnum:38 */\n  {\"AC10\", 0x27}, /* xkb:AC10 (AC10) -> linux:39 (KEY_SEMICOLON) -> qnum:39 */\n  {\"AC11\", 0x28}, /* xkb:AC11 (AC11) -> linux:40 (KEY_APOSTROPHE) -> qnum:40 */\n  {\"AC12\", 0x2b}, /* xkb:AC12 (AC12) -> linux:43 (KEY_BACKSLASH) -> qnum:43 */\n  {\"AD01\", 0x10}, /* xkb:AD01 (AD01) -> linux:16 (KEY_Q) -> qnum:16 */\n  {\"AD02\", 0x11}, /* xkb:AD02 (AD02) -> linux:17 (KEY_W) -> qnum:17 */\n  {\"AD03\", 0x12}, /* xkb:AD03 (AD03) -> linux:18 (KEY_E) -> qnum:18 */\n  {\"AD04\", 0x13}, /* xkb:AD04 (AD04) -> linux:19 (KEY_R) -> qnum:19 */\n  {\"AD05\", 0x14}, /* xkb:AD05 (AD05) -> linux:20 (KEY_T) -> qnum:20 */\n  {\"AD06\", 0x15}, /* xkb:AD06 (AD06) -> linux:21 (KEY_Y) -> qnum:21 */\n  {\"AD07\", 0x16}, /* xkb:AD07 (AD07) -> linux:22 (KEY_U) -> qnum:22 */\n  {\"AD08\", 0x17}, /* xkb:AD08 (AD08) -> linux:23 (KEY_I) -> qnum:23 */\n  {\"AD09\", 0x18}, /* xkb:AD09 (AD09) -> linux:24 (KEY_O) -> qnum:24 */\n  {\"AD10\", 0x19}, /* xkb:AD10 (AD10) -> linux:25 (KEY_P) -> qnum:25 */\n  {\"AD11\", 0x1a}, /* xkb:AD11 (AD11) -> linux:26 (KEY_LEFTBRACE) -> qnum:26 */\n  {\"AD12\", 0x1b}, /* xkb:AD12 (AD12) -> linux:27 (KEY_RIGHTBRACE) -> qnum:27 */\n  {\"AE01\", 0x2}, /* xkb:AE01 (AE01) -> linux:2 (KEY_1) -> qnum:2 */\n  {\"AE02\", 0x3}, /* xkb:AE02 (AE02) -> linux:3 (KEY_2) -> qnum:3 */\n  {\"AE03\", 0x4}, /* xkb:AE03 (AE03) -> linux:4 (KEY_3) -> qnum:4 */\n  {\"AE04\", 0x5}, /* xkb:AE04 (AE04) -> linux:5 (KEY_4) -> qnum:5 */\n  {\"AE05\", 0x6}, /* xkb:AE05 (AE05) -> linux:6 (KEY_5) -> qnum:6 */\n  {\"AE06\", 0x7}, /* xkb:AE06 (AE06) -> linux:7 (KEY_6) -> qnum:7 */\n  {\"AE07\", 0x8}, /* xkb:AE07 (AE07) -> linux:8 (KEY_7) -> qnum:8 */\n  {\"AE08\", 0x9}, /* xkb:AE08 (AE08) -> linux:9 (KEY_8) -> qnum:9 */\n  {\"AE09\", 0xa}, /* xkb:AE09 (AE09) -> linux:10 (KEY_9) -> qnum:10 */\n  {\"AE10\", 0xb}, /* xkb:AE10 (AE10) -> linux:11 (KEY_0) -> qnum:11 */\n  {\"AE11\", 0xc}, /* xkb:AE11 (AE11) -> linux:12 (KEY_MINUS) -> qnum:12 */\n  {\"AE12\", 0xd}, /* xkb:AE12 (AE12) -> linux:13 (KEY_EQUAL) -> qnum:13 */\n  {\"AE13\", 0x7d}, /* xkb:AE13 (AE13) -> linux:124 (KEY_YEN) -> qnum:125 */\n  {\"AGAI\", 0x85}, /* xkb:AGAI (AGAI) -> linux:129 (KEY_AGAIN) -> qnum:133 */\n  {\"ALGR\", 0xb8}, /* xkb:ALGR (RALT) -> linux:100 (KEY_RIGHTALT) -> qnum:184 */\n  {\"BKSL\", 0x2b}, /* xkb:BKSL (AC12) -> linux:43 (KEY_BACKSLASH) -> qnum:43 */\n  {\"BKSP\", 0xe}, /* xkb:BKSP (BKSP) -> linux:14 (KEY_BACKSPACE) -> qnum:14 */\n  {\"CAPS\", 0x3a}, /* xkb:CAPS (CAPS) -> linux:58 (KEY_CAPSLOCK) -> qnum:58 */\n  {\"COMP\", 0xdd}, /* xkb:COMP (COMP) -> linux:127 (KEY_COMPOSE) -> qnum:221 */\n  {\"COPY\", 0xf8}, /* xkb:COPY (COPY) -> linux:133 (KEY_COPY) -> qnum:248 */\n  {\"CUT\", 0xbc}, /* xkb:CUT (CUT) -> linux:137 (KEY_CUT) -> qnum:188 */\n  {\"DEL\", 0xd3}, /* xkb:DEL (DELE) -> linux:111 (KEY_DELETE) -> qnum:211 */\n  {\"DELE\", 0xd3}, /* xkb:DELE (DELE) -> linux:111 (KEY_DELETE) -> qnum:211 */\n  {\"DOWN\", 0xd0}, /* xkb:DOWN (DOWN) -> linux:108 (KEY_DOWN) -> qnum:208 */\n  {\"END\", 0xcf}, /* xkb:END (END) -> linux:107 (KEY_END) -> qnum:207 */\n  {\"ESC\", 0x1}, /* xkb:ESC (ESC) -> linux:1 (KEY_ESC) -> qnum:1 */\n  {\"FIND\", 0xc1}, /* xkb:FIND (FIND) -> linux:136 (KEY_FIND) -> qnum:193 */\n  {\"FK01\", 0x3b}, /* xkb:FK01 (FK01) -> linux:59 (KEY_F1) -> qnum:59 */\n  {\"FK02\", 0x3c}, /* xkb:FK02 (FK02) -> linux:60 (KEY_F2) -> qnum:60 */\n  {\"FK03\", 0x3d}, /* xkb:FK03 (FK03) -> linux:61 (KEY_F3) -> qnum:61 */\n  {\"FK04\", 0x3e}, /* xkb:FK04 (FK04) -> linux:62 (KEY_F4) -> qnum:62 */\n  {\"FK05\", 0x3f}, /* xkb:FK05 (FK05) -> linux:63 (KEY_F5) -> qnum:63 */\n  {\"FK06\", 0x40}, /* xkb:FK06 (FK06) -> linux:64 (KEY_F6) -> qnum:64 */\n  {\"FK07\", 0x41}, /* xkb:FK07 (FK07) -> linux:65 (KEY_F7) -> qnum:65 */\n  {\"FK08\", 0x42}, /* xkb:FK08 (FK08) -> linux:66 (KEY_F8) -> qnum:66 */\n  {\"FK09\", 0x43}, /* xkb:FK09 (FK09) -> linux:67 (KEY_F9) -> qnum:67 */\n  {\"FK10\", 0x44}, /* xkb:FK10 (FK10) -> linux:68 (KEY_F10) -> qnum:68 */\n  {\"FK11\", 0x57}, /* xkb:FK11 (FK11) -> linux:87 (KEY_F11) -> qnum:87 */\n  {\"FK12\", 0x58}, /* xkb:FK12 (FK12) -> linux:88 (KEY_F12) -> qnum:88 */\n  {\"FK13\", 0x5d}, /* xkb:FK13 (FK13) -> linux:183 (KEY_F13) -> qnum:93 */\n  {\"FK14\", 0x5e}, /* xkb:FK14 (FK14) -> linux:184 (KEY_F14) -> qnum:94 */\n  {\"FK15\", 0x5f}, /* xkb:FK15 (FK15) -> linux:185 (KEY_F15) -> qnum:95 */\n  {\"FK16\", 0x55}, /* xkb:FK16 (FK16) -> linux:186 (KEY_F16) -> qnum:85 */\n  {\"FK17\", 0x83}, /* xkb:FK17 (FK17) -> linux:187 (KEY_F17) -> qnum:131 */\n  {\"FK18\", 0xf7}, /* xkb:FK18 (FK18) -> linux:188 (KEY_F18) -> qnum:247 */\n  {\"FK19\", 0x84}, /* xkb:FK19 (FK19) -> linux:189 (KEY_F19) -> qnum:132 */\n  {\"FK20\", 0x5a}, /* xkb:FK20 (FK20) -> linux:190 (KEY_F20) -> qnum:90 */\n  {\"FK21\", 0x74}, /* xkb:FK21 (FK21) -> linux:191 (KEY_F21) -> qnum:116 */\n  {\"FK22\", 0xf9}, /* xkb:FK22 (FK22) -> linux:192 (KEY_F22) -> qnum:249 */\n  {\"FK23\", 0x6d}, /* xkb:FK23 (FK23) -> linux:193 (KEY_F23) -> qnum:109 */\n  {\"FK24\", 0x6f}, /* xkb:FK24 (FK24) -> linux:194 (KEY_F24) -> qnum:111 */\n  {\"FRNT\", 0x8c}, /* xkb:FRNT (FRNT) -> linux:132 (KEY_FRONT) -> qnum:140 */\n  {\"HELP\", 0xf5}, /* xkb:HELP (HELP) -> linux:138 (KEY_HELP) -> qnum:245 */\n  {\"HENK\", 0x79}, /* xkb:HENK (HENK) -> linux:92 (KEY_HENKAN) -> qnum:121 */\n  {\"HIRA\", 0x77}, /* xkb:HIRA (HIRA) -> linux:91 (KEY_HIRAGANA) -> qnum:119 */\n  {\"HJCV\", 0x71}, /* xkb:HJCV (HJCV) -> linux:123 (KEY_HANJA) -> qnum:113 */\n  {\"HKTG\", 0x70}, /* xkb:HKTG (HKTG) -> linux:93 (KEY_KATAKANAHIRAGANA) -> qnum:112 */\n  {\"HNGL\", 0x72}, /* xkb:HNGL (HNGL) -> linux:122 (KEY_HANGEUL) -> qnum:114 */\n  {\"HOME\", 0xc7}, /* xkb:HOME (HOME) -> linux:102 (KEY_HOME) -> qnum:199 */\n  {\"HZTG\", 0x76}, /* xkb:HZTG (HZTG) -> linux:85 (KEY_ZENKAKUHANKAKU) -> qnum:118 */\n  {\"I120\", 0xef}, /* xkb:I120 (I120) -> linux:112 (KEY_MACRO) -> qnum:239 */\n  {\"I126\", 0xce}, /* xkb:I126 (I126) -> linux:118 (KEY_KPPLUSMINUS) -> qnum:206 */\n  {\"I128\", 0x8b}, /* xkb:I128 (I128) -> linux:120 (KEY_SCALE) -> qnum:139 */\n  {\"I129\", 0x7e}, /* xkb:I129 (I129) -> linux:121 (KEY_KPCOMMA) -> qnum:126 */\n  {\"I147\", 0x9e}, /* xkb:I147 (I147) -> linux:139 (KEY_MENU) -> qnum:158 */\n  {\"I148\", 0xa1}, /* xkb:I148 (I148) -> linux:140 (KEY_CALC) -> qnum:161 */\n  {\"I149\", 0x66}, /* xkb:I149 (I149) -> linux:141 (KEY_SETUP) -> qnum:102 */\n  {\"I150\", 0xdf}, /* xkb:I150 (I150) -> linux:142 (KEY_SLEEP) -> qnum:223 */\n  {\"I151\", 0xe3}, /* xkb:I151 (I151) -> linux:143 (KEY_WAKEUP) -> qnum:227 */\n  {\"I152\", 0x67}, /* xkb:I152 (I152) -> linux:144 (KEY_FILE) -> qnum:103 */\n  {\"I153\", 0x68}, /* xkb:I153 (I153) -> linux:145 (KEY_SENDFILE) -> qnum:104 */\n  {\"I154\", 0x69}, /* xkb:I154 (I154) -> linux:146 (KEY_DELETEFILE) -> qnum:105 */\n  {\"I155\", 0x93}, /* xkb:I155 (I155) -> linux:147 (KEY_XFER) -> qnum:147 */\n  {\"I156\", 0x9f}, /* xkb:I156 (I156) -> linux:148 (KEY_PROG1) -> qnum:159 */\n  {\"I157\", 0x97}, /* xkb:I157 (I157) -> linux:149 (KEY_PROG2) -> qnum:151 */\n  {\"I158\", 0x82}, /* xkb:I158 (I158) -> linux:150 (KEY_WWW) -> qnum:130 */\n  {\"I159\", 0x6a}, /* xkb:I159 (I159) -> linux:151 (KEY_MSDOS) -> qnum:106 */\n  {\"I160\", 0x92}, /* xkb:I160 (I160) -> linux:152 (KEY_SCREENLOCK) -> qnum:146 */\n  {\"I161\", 0x6b}, /* xkb:I161 (I161) -> linux:153 (KEY_DIRECTION) -> qnum:107 */\n  {\"I162\", 0xa6}, /* xkb:I162 (I162) -> linux:154 (KEY_CYCLEWINDOWS) -> qnum:166 */\n  {\"I163\", 0xec}, /* xkb:I163 (I163) -> linux:155 (KEY_MAIL) -> qnum:236 */\n  {\"I164\", 0xe6}, /* xkb:I164 (I164) -> linux:156 (KEY_BOOKMARKS) -> qnum:230 */\n  {\"I165\", 0xeb}, /* xkb:I165 (I165) -> linux:157 (KEY_COMPUTER) -> qnum:235 */\n  {\"I166\", 0xea}, /* xkb:I166 (I166) -> linux:158 (KEY_BACK) -> qnum:234 */\n  {\"I167\", 0xe9}, /* xkb:I167 (I167) -> linux:159 (KEY_FORWARD) -> qnum:233 */\n  {\"I168\", 0xa3}, /* xkb:I168 (I168) -> linux:160 (KEY_CLOSECD) -> qnum:163 */\n  {\"I169\", 0x6c}, /* xkb:I169 (I169) -> linux:161 (KEY_EJECTCD) -> qnum:108 */\n  {\"I170\", 0xfd}, /* xkb:I170 (I170) -> linux:162 (KEY_EJECTCLOSECD) -> qnum:253 */\n  {\"I171\", 0x99}, /* xkb:I171 (I171) -> linux:163 (KEY_NEXTSONG) -> qnum:153 */\n  {\"I172\", 0xa2}, /* xkb:I172 (I172) -> linux:164 (KEY_PLAYPAUSE) -> qnum:162 */\n  {\"I173\", 0x90}, /* xkb:I173 (I173) -> linux:165 (KEY_PREVIOUSSONG) -> qnum:144 */\n  {\"I174\", 0xa4}, /* xkb:I174 (I174) -> linux:166 (KEY_STOPCD) -> qnum:164 */\n  {\"I175\", 0xb1}, /* xkb:I175 (I175) -> linux:167 (KEY_RECORD) -> qnum:177 */\n  {\"I176\", 0x98}, /* xkb:I176 (I176) -> linux:168 (KEY_REWIND) -> qnum:152 */\n  {\"I177\", 0x63}, /* xkb:I177 (I177) -> linux:169 (KEY_PHONE) -> qnum:99 */\n  {\"I179\", 0x81}, /* xkb:I179 (I179) -> linux:171 (KEY_CONFIG) -> qnum:129 */\n  {\"I180\", 0xb2}, /* xkb:I180 (I180) -> linux:172 (KEY_HOMEPAGE) -> qnum:178 */\n  {\"I181\", 0xe7}, /* xkb:I181 (I181) -> linux:173 (KEY_REFRESH) -> qnum:231 */\n  {\"I184\", 0x88}, /* xkb:I184 (I184) -> linux:176 (KEY_EDIT) -> qnum:136 */\n  {\"I185\", 0x75}, /* xkb:I185 (I185) -> linux:177 (KEY_SCROLLUP) -> qnum:117 */\n  {\"I186\", 0x8f}, /* xkb:I186 (I186) -> linux:178 (KEY_SCROLLDOWN) -> qnum:143 */\n  {\"I187\", 0xf6}, /* xkb:I187 (I187) -> linux:179 (KEY_KPLEFTPAREN) -> qnum:246 */\n  {\"I188\", 0xfb}, /* xkb:I188 (I188) -> linux:180 (KEY_KPRIGHTPAREN) -> qnum:251 */\n  {\"I189\", 0x89}, /* xkb:I189 (I189) -> linux:181 (KEY_NEW) -> qnum:137 */\n  {\"I190\", 0x8a}, /* xkb:I190 (I190) -> linux:182 (KEY_REDO) -> qnum:138 */\n  {\"I208\", 0xa8}, /* xkb:I208 (I208) -> linux:200 (KEY_PLAYCD) -> qnum:168 */\n  {\"I209\", 0xa9}, /* xkb:I209 (I209) -> linux:201 (KEY_PAUSECD) -> qnum:169 */\n  {\"I210\", 0xab}, /* xkb:I210 (I210) -> linux:202 (KEY_PROG3) -> qnum:171 */\n  {\"I211\", 0xac}, /* xkb:I211 (I211) -> linux:203 (KEY_PROG4) -> qnum:172 */\n  {\"I212\", 0xad}, /* xkb:I212 (I212) -> linux:204 (KEY_DASHBOARD) -> qnum:173 */\n  {\"I213\", 0xa5}, /* xkb:I213 (I213) -> linux:205 (KEY_SUSPEND) -> qnum:165 */\n  {\"I214\", 0xaf}, /* xkb:I214 (I214) -> linux:206 (KEY_CLOSE) -> qnum:175 */\n  {\"I215\", 0xb3}, /* xkb:I215 (I215) -> linux:207 (KEY_PLAY) -> qnum:179 */\n  {\"I216\", 0xb4}, /* xkb:I216 (I216) -> linux:208 (KEY_FASTFORWARD) -> qnum:180 */\n  {\"I217\", 0xb6}, /* xkb:I217 (I217) -> linux:209 (KEY_BASSBOOST) -> qnum:182 */\n  {\"I218\", 0xb9}, /* xkb:I218 (I218) -> linux:210 (KEY_PRINT) -> qnum:185 */\n  {\"I219\", 0xba}, /* xkb:I219 (I219) -> linux:211 (KEY_HP) -> qnum:186 */\n  {\"I220\", 0xbb}, /* xkb:I220 (I220) -> linux:212 (KEY_CAMERA) -> qnum:187 */\n  {\"I221\", 0xbd}, /* xkb:I221 (I221) -> linux:213 (KEY_SOUND) -> qnum:189 */\n  {\"I222\", 0xbe}, /* xkb:I222 (I222) -> linux:214 (KEY_QUESTION) -> qnum:190 */\n  {\"I223\", 0xbf}, /* xkb:I223 (I223) -> linux:215 (KEY_EMAIL) -> qnum:191 */\n  {\"I224\", 0xc0}, /* xkb:I224 (I224) -> linux:216 (KEY_CHAT) -> qnum:192 */\n  {\"I225\", 0xe5}, /* xkb:I225 (I225) -> linux:217 (KEY_SEARCH) -> qnum:229 */\n  {\"I226\", 0xc2}, /* xkb:I226 (I226) -> linux:218 (KEY_CONNECT) -> qnum:194 */\n  {\"I227\", 0xc3}, /* xkb:I227 (I227) -> linux:219 (KEY_FINANCE) -> qnum:195 */\n  {\"I228\", 0xc4}, /* xkb:I228 (I228) -> linux:220 (KEY_SPORT) -> qnum:196 */\n  {\"I229\", 0xc5}, /* xkb:I229 (I229) -> linux:221 (KEY_SHOP) -> qnum:197 */\n  {\"I230\", 0x94}, /* xkb:I230 (I230) -> linux:222 (KEY_ALTERASE) -> qnum:148 */\n  {\"I231\", 0xca}, /* xkb:I231 (I231) -> linux:223 (KEY_CANCEL) -> qnum:202 */\n  {\"I232\", 0xcc}, /* xkb:I232 (I232) -> linux:224 (KEY_BRIGHTNESSDOWN) -> qnum:204 */\n  {\"I233\", 0xd4}, /* xkb:I233 (I233) -> linux:225 (KEY_BRIGHTNESSUP) -> qnum:212 */\n  {\"I234\", 0xed}, /* xkb:I234 (I234) -> linux:226 (KEY_MEDIA) -> qnum:237 */\n  {\"I235\", 0xd6}, /* xkb:I235 (I235) -> linux:227 (KEY_SWITCHVIDEOMODE) -> qnum:214 */\n  {\"I236\", 0xd7}, /* xkb:I236 (I236) -> linux:228 (KEY_KBDILLUMTOGGLE) -> qnum:215 */\n  {\"I237\", 0xd8}, /* xkb:I237 (I237) -> linux:229 (KEY_KBDILLUMDOWN) -> qnum:216 */\n  {\"I238\", 0xd9}, /* xkb:I238 (I238) -> linux:230 (KEY_KBDILLUMUP) -> qnum:217 */\n  {\"I239\", 0xda}, /* xkb:I239 (I239) -> linux:231 (KEY_SEND) -> qnum:218 */\n  {\"I240\", 0xe4}, /* xkb:I240 (I240) -> linux:232 (KEY_REPLY) -> qnum:228 */\n  {\"I241\", 0x8e}, /* xkb:I241 (I241) -> linux:233 (KEY_FORWARDMAIL) -> qnum:142 */\n  {\"I242\", 0xd5}, /* xkb:I242 (I242) -> linux:234 (KEY_SAVE) -> qnum:213 */\n  {\"I243\", 0xf0}, /* xkb:I243 (I243) -> linux:235 (KEY_DOCUMENTS) -> qnum:240 */\n  {\"I244\", 0xf1}, /* xkb:I244 (I244) -> linux:236 (KEY_BATTERY) -> qnum:241 */\n  {\"I245\", 0xf2}, /* xkb:I245 (I245) -> linux:237 (KEY_BLUETOOTH) -> qnum:242 */\n  {\"I246\", 0xf3}, /* xkb:I246 (I246) -> linux:238 (KEY_WLAN) -> qnum:243 */\n  {\"I247\", 0xf4}, /* xkb:I247 (I247) -> linux:239 (KEY_UWB) -> qnum:244 */\n  {\"INS\", 0xd2}, /* xkb:INS (INS) -> linux:110 (KEY_INSERT) -> qnum:210 */\n  {\"JPCM\", 0x5c}, /* xkb:JPCM (JPCM) -> linux:95 (KEY_KPJPCOMMA) -> qnum:92 */\n  {\"KATA\", 0x78}, /* xkb:KATA (KATA) -> linux:90 (KEY_KATAKANA) -> qnum:120 */\n  {\"KP0\", 0x52}, /* xkb:KP0 (KP0) -> linux:82 (KEY_KP0) -> qnum:82 */\n  {\"KP1\", 0x4f}, /* xkb:KP1 (KP1) -> linux:79 (KEY_KP1) -> qnum:79 */\n  {\"KP2\", 0x50}, /* xkb:KP2 (KP2) -> linux:80 (KEY_KP2) -> qnum:80 */\n  {\"KP3\", 0x51}, /* xkb:KP3 (KP3) -> linux:81 (KEY_KP3) -> qnum:81 */\n  {\"KP4\", 0x4b}, /* xkb:KP4 (KP4) -> linux:75 (KEY_KP4) -> qnum:75 */\n  {\"KP5\", 0x4c}, /* xkb:KP5 (KP5) -> linux:76 (KEY_KP5) -> qnum:76 */\n  {\"KP6\", 0x4d}, /* xkb:KP6 (KP6) -> linux:77 (KEY_KP6) -> qnum:77 */\n  {\"KP7\", 0x47}, /* xkb:KP7 (KP7) -> linux:71 (KEY_KP7) -> qnum:71 */\n  {\"KP8\", 0x48}, /* xkb:KP8 (KP8) -> linux:72 (KEY_KP8) -> qnum:72 */\n  {\"KP9\", 0x49}, /* xkb:KP9 (KP9) -> linux:73 (KEY_KP9) -> qnum:73 */\n  {\"KPAD\", 0x4e}, /* xkb:KPAD (KPAD) -> linux:78 (KEY_KPPLUS) -> qnum:78 */\n  {\"KPCO\", 0x7e}, /* xkb:KPCO (I129) -> linux:121 (KEY_KPCOMMA) -> qnum:126 */\n  {\"KPDC\", 0x53}, /* xkb:KPDC (KPDC) -> linux:83 (KEY_KPDOT) -> qnum:83 */\n  {\"KPDL\", 0x53}, /* xkb:KPDL (KPDC) -> linux:83 (KEY_KPDOT) -> qnum:83 */\n  {\"KPDV\", 0xb5}, /* xkb:KPDV (KPDV) -> linux:98 (KEY_KPSLASH) -> qnum:181 */\n  {\"KPEN\", 0x9c}, /* xkb:KPEN (KPEN) -> linux:96 (KEY_KPENTER) -> qnum:156 */\n  {\"KPEQ\", 0x59}, /* xkb:KPEQ (KPEQ) -> linux:117 (KEY_KPEQUAL) -> qnum:89 */\n  {\"KPMU\", 0x37}, /* xkb:KPMU (KPMU) -> linux:55 (KEY_KPASTERISK) -> qnum:55 */\n  {\"KPSP\", 0x5c}, /* xkb:KPSP (JPCM) -> linux:95 (KEY_KPJPCOMMA) -> qnum:92 */\n  {\"KPSU\", 0x4a}, /* xkb:KPSU (KPSU) -> linux:74 (KEY_KPMINUS) -> qnum:74 */\n  {\"LALT\", 0x38}, /* xkb:LALT (LALT) -> linux:56 (KEY_LEFTALT) -> qnum:56 */\n  {\"LCTL\", 0x1d}, /* xkb:LCTL (LCTL) -> linux:29 (KEY_LEFTCTRL) -> qnum:29 */\n  {\"LEFT\", 0xcb}, /* xkb:LEFT (LEFT) -> linux:105 (KEY_LEFT) -> qnum:203 */\n  {\"LFSH\", 0x2a}, /* xkb:LFSH (LFSH) -> linux:42 (KEY_LEFTSHIFT) -> qnum:42 */\n  {\"LMTA\", 0xdb}, /* xkb:LMTA (LWIN) -> linux:125 (KEY_LEFTMETA) -> qnum:219 */\n  {\"LNFD\", 0x5b}, /* xkb:LNFD (LNFD) -> linux:101 (KEY_LINEFEED) -> qnum:91 */\n  {\"LSGT\", 0x56}, /* xkb:LSGT (LSGT) -> linux:86 (KEY_102ND) -> qnum:86 */\n  {\"LWIN\", 0xdb}, /* xkb:LWIN (LWIN) -> linux:125 (KEY_LEFTMETA) -> qnum:219 */\n  {\"MENU\", 0xdd}, /* xkb:MENU (COMP) -> linux:127 (KEY_COMPOSE) -> qnum:221 */\n  {\"MUHE\", 0x7b}, /* xkb:MUHE (MUHE) -> linux:94 (KEY_MUHENKAN) -> qnum:123 */\n  {\"MUTE\", 0xa0}, /* xkb:MUTE (MUTE) -> linux:113 (KEY_MUTE) -> qnum:160 */\n  {\"NFER\", 0x7b}, /* xkb:NFER (MUHE) -> linux:94 (KEY_MUHENKAN) -> qnum:123 */\n  {\"NMLK\", 0x45}, /* xkb:NMLK (NMLK) -> linux:69 (KEY_NUMLOCK) -> qnum:69 */\n  {\"OPEN\", 0x64}, /* xkb:OPEN (OPEN) -> linux:134 (KEY_OPEN) -> qnum:100 */\n  {\"PAST\", 0x65}, /* xkb:PAST (PAST) -> linux:135 (KEY_PASTE) -> qnum:101 */\n  {\"PAUS\", 0xc6}, /* xkb:PAUS (PAUS) -> linux:119 (KEY_PAUSE) -> qnum:198 */\n  {\"PGDN\", 0xd1}, /* xkb:PGDN (PGDN) -> linux:109 (KEY_PAGEDOWN) -> qnum:209 */\n  {\"PGUP\", 0xc9}, /* xkb:PGUP (PGUP) -> linux:104 (KEY_PAGEUP) -> qnum:201 */\n  {\"POWR\", 0xde}, /* xkb:POWR (POWR) -> linux:116 (KEY_POWER) -> qnum:222 */\n  {\"PROP\", 0x86}, /* xkb:PROP (PROP) -> linux:130 (KEY_PROPS) -> qnum:134 */\n  {\"PRSC\", 0x54}, /* xkb:PRSC (SYRQ) -> linux:99 (KEY_SYSRQ) -> qnum:84 */\n  {\"RALT\", 0xb8}, /* xkb:RALT (RALT) -> linux:100 (KEY_RIGHTALT) -> qnum:184 */\n  {\"RCTL\", 0x9d}, /* xkb:RCTL (RCTL) -> linux:97 (KEY_RIGHTCTRL) -> qnum:157 */\n  {\"RGHT\", 0xcd}, /* xkb:RGHT (RGHT) -> linux:106 (KEY_RIGHT) -> qnum:205 */\n  {\"RMTA\", 0xdc}, /* xkb:RMTA (RWIN) -> linux:126 (KEY_RIGHTMETA) -> qnum:220 */\n  {\"RTRN\", 0x1c}, /* xkb:RTRN (RTRN) -> linux:28 (KEY_ENTER) -> qnum:28 */\n  {\"RTSH\", 0x36}, /* xkb:RTSH (RTSH) -> linux:54 (KEY_RIGHTSHIFT) -> qnum:54 */\n  {\"RWIN\", 0xdc}, /* xkb:RWIN (RWIN) -> linux:126 (KEY_RIGHTMETA) -> qnum:220 */\n  {\"SCLK\", 0x46}, /* xkb:SCLK (SCLK) -> linux:70 (KEY_SCROLLLOCK) -> qnum:70 */\n  {\"SPCE\", 0x39}, /* xkb:SPCE (SPCE) -> linux:57 (KEY_SPACE) -> qnum:57 */\n  {\"STOP\", 0xe8}, /* xkb:STOP (STOP) -> linux:128 (KEY_STOP) -> qnum:232 */\n  {\"SYRQ\", 0x54}, /* xkb:SYRQ (SYRQ) -> linux:99 (KEY_SYSRQ) -> qnum:84 */\n  {\"TAB\", 0xf}, /* xkb:TAB (TAB) -> linux:15 (KEY_TAB) -> qnum:15 */\n  {\"TLDE\", 0x29}, /* xkb:TLDE (AB00) -> linux:41 (KEY_GRAVE) -> qnum:41 */\n  {\"UNDO\", 0x87}, /* xkb:UNDO (UNDO) -> linux:131 (KEY_UNDO) -> qnum:135 */\n  {\"UP\", 0xc8}, /* xkb:UP (UP) -> linux:103 (KEY_UP) -> qnum:200 */\n  {\"VOL+\", 0xb0}, /* xkb:VOL+ (VOL+) -> linux:115 (KEY_VOLUMEUP) -> qnum:176 */\n  {\"VOL-\", 0xae}, /* xkb:VOL- (VOL-) -> linux:114 (KEY_VOLUMEDOWN) -> qnum:174 */\n  {\"XFER\", 0x93}, /* xkb:XFER (I155) -> linux:147 (KEY_XFER) -> qnum:147 */\n};\nconst unsigned int code_map_xkb_to_qnum_len = sizeof(code_map_xkb_to_qnum)/sizeof(code_map_xkb_to_qnum[0]);\n"
  },
  {
    "path": "unix/xserver/.gitignore",
    "content": "/*\n!/hw\n/hw/*\n!/hw/vnc\n"
  },
  {
    "path": "unix/xserver/hw/vnc/.gitignore",
    "content": "Xvnc\n"
  },
  {
    "path": "unix/xserver/hw/vnc/Makefile.am",
    "content": "TIGERVNC_SRCDIR=$(abspath ${top_srcdir}/../..)\nTIGERVNC_BUILDDIR=$(abspath ${top_builddir}/../..)\n\nRFB_LIB=$(TIGERVNC_BUILDDIR)/common/rfb/librfb.la\nRDR_LIB=$(TIGERVNC_BUILDDIR)/common/rdr/librdr.la\nOS_LIB=$(TIGERVNC_BUILDDIR)/common/os/libos.la\nNETWORK_LIB=$(TIGERVNC_BUILDDIR)/common/network/libnetwork.la\nUNIXCOMMON_LIB=$(TIGERVNC_BUILDDIR)/unix/common/libunixcommon.la\nCOMMON_LIBS=$(UNIXCOMMON_LIB) $(RFB_LIB) $(NETWORK_LIB) $(RDR_LIB) $(CORE_LIB)\n\nAM_CPPFLAGS = \\\n\t-I$(TIGERVNC_BUILDDIR) \\\n\t-I$(TIGERVNC_SRCDIR)/common \\\n\t-I$(TIGERVNC_SRCDIR)/unix/common \\\n\t$(DIX_CFLAGS) $(LIBXCVT_CFLAGS)\n\nAM_CXXFLAGS = -std=gnu++11\n\nnoinst_LTLIBRARIES = libvnccommon.la\n\nHDRS = vncExtInit.h vncHooks.h \\\n\tvncBlockHandler.h vncPresent.h vncSelection.h \\\n\tXorgGlue.h XserverDesktop.h xorg-version.h \\\n\tvncInput.h RFBGlue.h\n\nlibvnccommon_la_SOURCES = $(HDRS) \\\n\tvncExt.c vncExtInit.cc vncHooks.c vncPresent.c vncSelection.c \\\n\tvncBlockHandler.c XorgGlue.c RandrGlue.c RFBGlue.cc XserverDesktop.cc \\\n\tvncInput.c vncInputXKB.c qnum_to_xorgevdev.c qnum_to_xorgkbd.c\n\nlibvnccommon_la_CPPFLAGS = $(AM_CPPFLAGS) \\\n\t-I$(TIGERVNC_SRCDIR)/unix/vncconfig\n\nbin_PROGRAMS = Xvnc\n\nman1_MANS = Xvnc.man\n\nXvnc_SOURCES = xvnc.c \\\n\t$(top_srcdir)/Xi/stubs.c $(top_srcdir)/mi/miinitext.c \\\n\tbuildtime.c\n\n# Xvnc contains no C++ sources so automake doesn't understand that we\n# need to use the C++ compiler to link things. This is the upstream\n# recommendation for coaxing automake.\nnodist_EXTRA_Xvnc_SOURCES = dummy.cxx\n\nXvnc_CPPFLAGS = $(AM_CPPFLAGS)\n\nLOCAL_LIBS = \\\n\t$(XVNC_LIBS) \\\n\t$(XSERVER_LIBS) \\\n\tlibvnccommon.la \\\n\t$(COMMON_LIBS)\n\nXvnc_DEPENDENCIES = $(LOCAL_LIBS)\nXvnc_LDADD = \\\n\t$(LOCAL_LIBS) \\\n\t$(XSERVER_SYS_LIBS) \\\n\t$(XVNC_SYS_LIBS) \\\n\t$(LIBXCVT_LIBS)\n\nXvnc_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)\n\nif DRI3\nXvnc_SOURCES += vncDRI3.h vncDRI3.c vncDRI3Draw.c\nXvnc_CPPFLAGS += \\\n\t-I$(top_srcdir)/dri3 \\\n\t$(GBM_CFLAGS)\nXvnc_LDADD += $(GBM_LIBS)\nendif\n\nlibvnc_la_LTLIBRARIES = libvnc.la\nlibvnc_ladir = $(moduledir)/extensions\n\nlibvnc_la_SOURCES = vncModule.c\n\n# See Xvnc magic above\nnodist_EXTRA_libvnc_la_SOURCES = dummy.cxx\n\nlibvnc_la_CPPFLAGS = $(AM_CPPFLAGS) \\\n\t-I$(top_srcdir)/hw/xfree86/common \\\n\t-I$(top_srcdir)/hw/xfree86/os-support \\\n\t-I$(top_srcdir)/hw/xfree86/os-support/bus\n\nlibvnc_la_LDFLAGS = -module -avoid-version -Wl,-z,now\n\nlibvnc_la_LIBADD = libvnccommon.la $(COMMON_LIBS)\n\nEXTRA_DIST = Xvnc.man\n"
  },
  {
    "path": "unix/xserver/hw/vnc/RFBGlue.cc",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <core/Configuration.h>\n#include <core/Logger_stdio.h>\n#include <core/Logger_syslog.h>\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <network/TcpSocket.h>\n\n#include <rfb/UnixPasswordValidator.h>\n\n#include \"RFBGlue.h\"\n\n// Loggers used by C code must be created here\nstatic core::LogWriter inputLog(\"Input\");\nstatic core::LogWriter selectionLog(\"Selection\");\n\nvoid vncInitRFB(void)\n{\n  core::initStdIOLoggers();\n  core::initSyslogLogger();\n  core::LogWriter::setLogParams(\"*:stderr:30\");\n}\n\nvoid vncLogError(const char *name, const char *format, ...)\n{\n  core::LogWriter* vlog;\n  va_list ap;\n  vlog = core::LogWriter::getLogWriter(name);\n  if (vlog == nullptr)\n    return;\n  va_start(ap, format);\n  vlog->verror(format, ap);\n  va_end(ap);\n}\n\nvoid vncLogStatus(const char *name, const char *format, ...)\n{\n  core::LogWriter* vlog;\n  va_list ap;\n  vlog = core::LogWriter::getLogWriter(name);\n  if (vlog == nullptr)\n    return;\n  va_start(ap, format);\n  vlog->vstatus(format, ap);\n  va_end(ap);\n}\n\nvoid vncLogInfo(const char *name, const char *format, ...)\n{\n  core::LogWriter* vlog;\n  va_list ap;\n  vlog = core::LogWriter::getLogWriter(name);\n  if (vlog == nullptr)\n    return;\n  va_start(ap, format);\n  vlog->vinfo(format, ap);\n  va_end(ap);\n}\n\nvoid vncLogDebug(const char *name, const char *format, ...)\n{\n  core::LogWriter* vlog;\n  va_list ap;\n  vlog = core::LogWriter::getLogWriter(name);\n  if (vlog == nullptr)\n    return;\n  va_start(ap, format);\n  vlog->vdebug(format, ap);\n  va_end(ap);\n}\n\nint vncSetParam(const char *name, const char *value)\n{\n  if (value != nullptr)\n    return core::Configuration::setParam(name, value);\n  else {\n    core::VoidParameter* param;\n    param = core::Configuration::getParam(name);\n    if (param == nullptr)\n      return false;\n    return param->setParam();\n  }\n}\n\nchar* vncGetParam(const char *name)\n{\n  core::VoidParameter* param;\n\n  // Hack to avoid exposing password!\n  if (strcasecmp(name, \"Password\") == 0)\n    return nullptr;\n\n  param = core::Configuration::getParam(name);\n  if (param == nullptr)\n    return nullptr;\n\n  return strdup(param->getValueStr().c_str());\n}\n\nconst char* vncGetParamDesc(const char *name)\n{\n  core::VoidParameter* param;\n\n  param = core::Configuration::getParam(name);\n  if (param == nullptr)\n    return nullptr;\n\n  return param->getDescription();\n}\n\nint vncGetParamCount(void)\n{\n  return core::Configuration::global()->size();\n}\n\nchar *vncGetParamList(void)\n{\n  int len;\n  char *data, *ptr;\n\n  len = 0;\n\n  for (core::VoidParameter *param: *core::Configuration::global()) {\n    int l = strlen(param->getName());\n    if (l <= 255)\n      len += l + 1;\n  }\n\n  data = (char*)malloc(len + 1);\n  if (data == nullptr)\n    return nullptr;\n\n  ptr = data;\n  for (core::VoidParameter *param: *core::Configuration::global()) {\n    int l = strlen(param->getName());\n    if (l <= 255) {\n      *ptr++ = l;\n      memcpy(ptr, param->getName(), l);\n      ptr += l;\n    }\n  }\n  *ptr = '\\0';\n\n  return data;\n}\n\nvoid vncListParams(int width, int nameWidth)\n{\n  core::Configuration::listParams(width, nameWidth);\n}\n\nint vncHandleParamArg(int argc, char* argv[], int index)\n{\n  return core::Configuration::handleParamArg(argc, argv, index);\n}\n\nint vncGetSocketPort(int fd)\n{\n  return network::getSockPort(fd);\n}\n\nint vncIsTCPPortUsed(int port)\n{\n  try {\n    // Attempt to create TCPListeners on that port.\n    std::list<network::SocketListener*> dummy;\n    network::createTcpListeners (&dummy, 0, port);\n    while (!dummy.empty()) {\n      delete dummy.back();\n      dummy.pop_back();\n    }\n  } catch (std::exception& e) {\n    return 1;\n  }\n  return 0;\n}\n\nchar* vncConvertLF(const char* src, size_t bytes)\n{\n  try {\n    return strdup(core::convertLF(src, bytes).c_str());\n  } catch (...) {\n    return nullptr;\n  }\n}\n\nchar* vncLatin1ToUTF8(const char* src, size_t bytes)\n{\n  try {\n    return strdup(core::latin1ToUTF8(src, bytes).c_str());\n  } catch (...) {\n    return nullptr;\n  }\n}\n\nchar* vncUTF8ToLatin1(const char* src, size_t bytes)\n{\n  try {\n    return strdup(core::utf8ToLatin1(src, bytes).c_str());\n  } catch (...) {\n    return nullptr;\n  }\n}\n\nint vncIsValidUTF8(const char* str, size_t bytes)\n{\n  try {\n    return core::isValidUTF8(str, bytes);\n  } catch (...) {\n    return 0;\n  }\n}\n\nvoid vncSetDisplayName(const char *displayNumStr)\n{\n  std::string displayName(\":\");\n  displayName += displayNumStr;\n  rfb::UnixPasswordValidator::setDisplayName(displayName);\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/RFBGlue.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef RFB_GLUE_H\n#define RFB_GLUE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid vncInitRFB(void);\n\nvoid vncLogError(const char *name, const char *format, ...)\n        __attribute__((__format__ (__printf__, 2, 3)));\nvoid vncLogStatus(const char *name, const char *format, ...)\n        __attribute__((__format__ (__printf__, 2, 3)));\nvoid vncLogInfo(const char *name, const char *format, ...)\n        __attribute__((__format__ (__printf__, 2, 3)));\nvoid vncLogDebug(const char *name, const char *format, ...)\n        __attribute__((__format__ (__printf__, 2, 3)));\n\nint vncSetParam(const char *name, const char *value);\nchar* vncGetParam(const char *name);\nconst char* vncGetParamDesc(const char *name);\n\nint vncGetParamCount(void);\nchar *vncGetParamList(void);\nvoid vncListParams(int width, int nameWidth);\n\nint vncHandleParamArg(int argc, char* argv[], int index);\n\nint vncGetSocketPort(int fd);\nint vncIsTCPPortUsed(int port);\n\nchar* vncConvertLF(const char* src, size_t bytes);\n\nchar* vncLatin1ToUTF8(const char* src, size_t bytes);\nchar* vncUTF8ToLatin1(const char* src, size_t bytes);\n\nint vncIsValidUTF8(const char* str, size_t bytes);\n\nvoid vncSetDisplayName(const char *displayNumStr);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/RandrGlue.c",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2015 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include <assert.h>\n#include <string.h>\n\n#include \"scrnintstr.h\"\n#include \"randrstr.h\"\n\n#include \"RandrGlue.h\"\n#include \"XorgGlue.h\"\n\nstatic int scrIdx;\n\nvoid vncSetGlueContext(int screenIndex);\n\nvoid vncSetGlueContext(int screenIndex)\n{\n  scrIdx = screenIndex;\n}\n\nint vncGetScreenWidth(void)\n{\n  return screenInfo.screens[scrIdx]->width;\n}\n\nint vncGetScreenHeight(void)\n{\n  return screenInfo.screens[scrIdx]->height;\n}\n\nint vncRandRIsValidScreenSize(int width, int height)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n\n  if (width < rp->minWidth || rp->maxWidth < width)\n    return 0;\n  if (height < rp->minHeight || rp->maxHeight < height)\n    return 0;\n\n  return 1;\n}\n\nint vncRandRResizeScreen(int width, int height)\n{\n  ScreenPtr pScreen = screenInfo.screens[scrIdx];\n  int dpi, mwidth, mheight;\n\n  /* Keep the DPI specified at start */\n  dpi = monitorResolution ? monitorResolution : 96;\n  mwidth = width * 254 / dpi / 10;\n  mheight = height * 254 / dpi / 10;\n\n  return RRScreenSizeSet(pScreen, width, height, mwidth, mheight);\n}\n\nvoid vncRandRUpdateSetTime(void)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n  rp->lastSetTime = currentTime;\n}\n\nint vncRandRHasOutputClones(void)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n  for (int i = 0;i < rp->numCrtcs;i++) {\n    if (rp->crtcs[i]->numOutputs > 1)\n      return 1;\n  }\n  return 0;\n}\n\nint vncRandRGetOutputCount(void)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n  return rp->numOutputs;\n}\n\nint vncRandRGetAvailableOutputs(void)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n\n  int availableOutputs;\n  RRCrtcPtr *usedCrtcs;\n  int numUsed;\n\n  int i, j, k;\n\n  usedCrtcs = malloc(sizeof(RRCrtcPtr) * rp->numCrtcs);\n  if (usedCrtcs == NULL)\n    return 0;\n\n  /*\n   * This gets slightly complicated because we might need to hook a CRTC\n   * up to the output, but also check that we don't try to use the same\n   * CRTC for multiple outputs.\n   */\n  availableOutputs = 0;\n  numUsed = 0;\n  for (i = 0;i < rp->numOutputs;i++) {\n    RROutputPtr output;\n\n    output = rp->outputs[i];\n\n    if (output->crtc != NULL)\n      availableOutputs++;\n    else {\n      for (j = 0;j < output->numCrtcs;j++) {\n        if (output->crtcs[j]->numOutputs != 0)\n          continue;\n\n        for (k = 0;k < numUsed;k++) {\n          if (usedCrtcs[k] == output->crtcs[j])\n            break;\n        }\n        if (k != numUsed)\n          continue;\n\n        availableOutputs++;\n\n        usedCrtcs[numUsed] = output->crtcs[j];\n        numUsed++;\n\n        break;\n      }\n    }\n  }\n\n  free(usedCrtcs);\n\n  return availableOutputs;\n}\n\nchar *vncRandRGetOutputName(int outputIdx)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n  return strdup(rp->outputs[outputIdx]->name);\n}\n\nint vncRandRIsOutputEnabled(int outputIdx)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n\n  if (rp->outputs[outputIdx]->crtc == NULL)\n    return 0;\n  if (rp->outputs[outputIdx]->crtc->mode == NULL)\n    return 0;\n\n  return 1;\n}\n\nint vncRandRIsOutputUsable(int outputIdx)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n\n  RROutputPtr output;\n  int i;\n\n  output = rp->outputs[outputIdx];\n  if (output->crtc != NULL)\n    return 1;\n\n  /* Any unused CRTCs? */\n  for (i = 0;i < output->numCrtcs;i++) {\n    if (output->crtcs[i]->numOutputs == 0)\n      return 1;\n  }\n\n  return 0;\n}\n\nint vncRandRIsOutputConnected(int outputIdx)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n\n  RROutputPtr output;\n\n  output = rp->outputs[outputIdx];\n  return (output->connection == RR_Connected);\n}\n\nstatic RRModePtr vncRandRGetMatchingMode(int outputIdx, int width, int height)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n\n  RROutputPtr output;\n\n  output = rp->outputs[outputIdx];\n\n  if (output->crtc != NULL) {\n    unsigned int swap;\n    switch (output->crtc->rotation) {\n    case RR_Rotate_90:\n    case RR_Rotate_270:\n      swap = width;\n      width = height;\n      height = swap;\n      break;\n    }\n  }\n\n  for (int i = 0; i < output->numModes; i++) {\n    if ((output->modes[i]->mode.width == width) &&\n        (output->modes[i]->mode.height == height))\n      return output->modes[i];\n  }\n\n  return NULL;\n}\n\nint vncRandRCheckOutputMode(int outputIdx, int width, int height)\n{\n  if (vncRandRGetMatchingMode(outputIdx, width, height) != NULL)\n    return 1;\n  if (vncRandRCanCreateModes())\n    return 1;\n  return 0;\n}\n\nint vncRandRDisableOutput(int outputIdx)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n  RRCrtcPtr crtc;\n  int i;\n  RROutputPtr *outputs;\n  int numOutputs = 0;\n  RRModePtr mode;\n  int ret;\n\n  crtc = rp->outputs[outputIdx]->crtc;\n  if (crtc == NULL)\n    return 1;\n\n  /* Remove this output from the CRTC configuration */\n  outputs = malloc(crtc->numOutputs * sizeof(RROutputPtr));\n  if (!outputs) {\n    return 0;\n  }\n\n  for (i = 0; i < crtc->numOutputs; i++) {\n    if (rp->outputs[outputIdx] != crtc->outputs[i]) {\n      outputs[numOutputs++] = crtc->outputs[i];\n    }\n  }\n\n  if (numOutputs == 0) {\n    mode = NULL;\n  } else {\n    mode = crtc->mode;\n  }\n\n  ret = RRCrtcSet(crtc, mode, crtc->x, crtc->y, crtc->rotation, numOutputs, outputs);\n  free(outputs);\n  return ret;\n}\n\nunsigned int vncRandRGetOutputId(int outputIdx)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n  return rp->outputs[outputIdx]->id;\n}\n\nint vncRandRGetOutputDimensions(int outputIdx,\n                            int *x, int *y, int *width, int *height)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n  RRCrtcPtr crtc;\n  int swap;\n  *x = *y = *width = *height = 0;\n\n  crtc = rp->outputs[outputIdx]->crtc;\n  if (crtc == NULL || !crtc->mode)\n    return 1;\n\n  *x = crtc->x;\n  *y = crtc->y;\n  *width = crtc->mode->mode.width;\n  *height = crtc->mode->mode.height;\n\n  switch (crtc->rotation & 0xf) {\n  case RR_Rotate_90:\n  case RR_Rotate_270:\n    swap = *width;\n    *width = *height;\n    *height = swap;\n    break;\n  }\n  return 0;\n}\n\nint vncRandRReconfigureOutput(int outputIdx, int x, int y,\n                              int width, int height)\n{\n  rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);\n\n  RROutputPtr output;\n  RRCrtcPtr crtc;\n  RRModePtr mode;\n\n  int i;\n\n  output = rp->outputs[outputIdx];\n  crtc = output->crtc;\n\n  /* Need a CRTC? */\n  if (crtc == NULL) {\n    for (i = 0;i < output->numCrtcs;i++) {\n      if (output->crtcs[i]->numOutputs != 0)\n        continue;\n\n      crtc = output->crtcs[i];\n      break;\n    }\n\n    /* Couldn't find one... */\n    if (crtc == NULL)\n      return 0;\n  }\n\n  /* Make sure we have the mode we want */\n  mode = vncRandRGetMatchingMode(outputIdx, width, height);\n  if (mode == NULL) {\n    mode = vncRandRCreateMode(output, width, height);\n    if (mode == NULL)\n      return 0;\n  }\n  mode = vncRandRSetPreferredMode(output, mode);\n  if (mode == NULL)\n    return 0;\n\n  /* Reconfigure new mode and position */\n  return RRCrtcSet(crtc, mode, x, y, crtc->rotation, 1, &output);\n}\n\nint vncRandRCanCreateOutputs(int extraOutputs)\n{\n  return vncRandRCanCreateScreenOutputs(scrIdx, extraOutputs);\n}\n\nint vncRandRCreateOutputs(int extraOutputs)\n{\n  return vncRandRCreateScreenOutputs(scrIdx, extraOutputs);\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/XorgGlue.c",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2015 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include <assert.h>\n\n#include \"scrnintstr.h\"\n#ifdef RANDR\n#include \"randrstr.h\"\n#endif\n\n#include \"XorgGlue.h\"\n\nconst char *vncGetDisplay(void)\n{\n  return display;\n}\n\nunsigned long vncGetServerGeneration(void)\n{\n  return serverGeneration;\n}\n\nvoid vncFatalError(const char *format, ...)\n{\n  va_list args;\n  char buffer[4096];\n\n  va_start(args, format);\n  vsnprintf(buffer, sizeof(buffer), format, args);\n  va_end(args);\n\n  FatalError(\"%s\", buffer);\n}\n\nint vncGetScreenCount(void)\n{\n  return screenInfo.numScreens;\n}\n\nvoid vncGetScreenFormat(int scrIdx, int *depth, int *bpp,\n                        int *trueColour, int *bigEndian,\n                        int *redMask, int *greenMask, int *blueMask)\n{\n  int i;\n  VisualPtr vis = NULL;\n\n  assert(depth);\n  assert(bpp);\n  assert(trueColour);\n  assert(bigEndian);\n  assert(redMask);\n  assert(greenMask);\n  assert(blueMask);\n\n  *depth = screenInfo.screens[scrIdx]->rootDepth;\n\n  for (i = 0; i < screenInfo.numPixmapFormats; i++) {\n    if (screenInfo.formats[i].depth == *depth) {\n      *bpp = screenInfo.formats[i].bitsPerPixel;\n      break;\n    }\n  }\n\n  if (i == screenInfo.numPixmapFormats)\n    FatalError(\"No pixmap format for root depth\\n\");\n\n  *bigEndian = (screenInfo.imageByteOrder == MSBFirst);\n\n  for (i = 0; i < screenInfo.screens[scrIdx]->numVisuals; i++) {\n    if (screenInfo.screens[scrIdx]->visuals[i].vid == \n        screenInfo.screens[scrIdx]->rootVisual) {\n      vis = &screenInfo.screens[scrIdx]->visuals[i];\n      break;\n    }\n  }\n\n  if (i == screenInfo.screens[scrIdx]->numVisuals)\n    FatalError(\"No visual record for root visual\\n\");\n\n  *trueColour = (vis->class == TrueColor);\n\n  *redMask = vis->redMask;\n  *greenMask = vis->greenMask;\n  *blueMask = vis->blueMask;\n}\n\nint vncGetScreenX(int scrIdx)\n{\n  return screenInfo.screens[scrIdx]->x;\n}\n\nint vncGetScreenY(int scrIdx)\n{\n  return screenInfo.screens[scrIdx]->y;\n}\n\n"
  },
  {
    "path": "unix/xserver/hw/vnc/XorgGlue.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2015 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef XORG_GLUE_H\n#define XORG_GLUE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nconst char *vncGetDisplay(void);\nunsigned long vncGetServerGeneration(void);\n\nvoid vncFatalError(const char *format, ...)\n  __attribute__((__format__ (__printf__, 1, 2)))\n  __attribute__((noreturn));\n\nint vncGetScreenCount(void);\n\nvoid vncGetScreenFormat(int scrIdx, int *depth, int *bpp,\n                        int *trueColour, int *bigEndian,\n                        int *redMask, int *greenMask, int *blueMask);\n\nint vncGetScreenX(int scrIdx);\nint vncGetScreenY(int scrIdx);\n\n// These hide in xvnc.c or vncModule.c\nvoid vncClientGone(int fd);\nint vncRandRCanCreateScreenOutputs(int scrIdx, int extraOutputs);\nint vncRandRCreateScreenOutputs(int scrIdx, int extraOutputs);\nint vncRandRCanCreateModes(void);\nvoid* vncRandRCreateMode(void* output, int width, int height);\nvoid* vncRandRSetPreferredMode(void* output, void* mode);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/XserverDesktop.cc",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2024 Pierre Ossman for Cendio AB\n * Copyright 2014 Brian P. Hinz\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// XserverDesktop.cxx\n//\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <strings.h>\n#include <unistd.h>\n#include <pwd.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <sys/utsname.h>\n\n#include <core/Configuration.h>\n#include <core/LogWriter.h>\n\n#include <rdr/FdInStream.h>\n#include <rdr/FdOutStream.h>\n\n#include <network/Socket.h>\n\n#include <rfb/VNCServerST.h>\n#include <rfb/ServerCore.h>\n\n#include \"XserverDesktop.h\"\n#include \"vncBlockHandler.h\"\n#include \"vncExtInit.h\"\n#include \"vncHooks.h\"\n#include \"vncSelection.h\"\n#include \"XorgGlue.h\"\n#include \"vncInput.h\"\n\nextern \"C\" {\nvoid vncSetGlueContext(int screenIndex);\nvoid vncPresentMscEvent(uint64_t id, uint64_t msc);\n}\n\nstatic core::LogWriter vlog(\"XserverDesktop\");\n\ncore::BoolParameter\n  rawKeyboard(\"RawKeyboard\",\n              \"Send keyboard events straight through and avoid mapping \"\n              \"them to the current keyboard layout\", false);\ncore::IntParameter\n  queryConnectTimeout(\"QueryConnectTimeout\",\n                      \"Number of seconds to show the 'Accept \"\n                      \"connection' dialog before rejecting the \"\n                      \"connection\", 10, 0, INT_MAX);\n\n\nXserverDesktop::XserverDesktop(int screenIndex_,\n                               std::list<network::SocketListener*> listeners_,\n                               const char* name, const rfb::PixelFormat &pf,\n                               int width, int height,\n                               void* fbptr, int stride_)\n  : screenIndex(screenIndex_),\n    server(0), listeners(listeners_),\n    shadowFramebuffer(nullptr),\n    queryConnectId(0), queryConnectTimer(this)\n{\n  format = pf;\n\n  server = new rfb::VNCServerST(name, this);\n  setFramebuffer(width, height, fbptr, stride_);\n\n  for (network::SocketListener* listener : listeners)\n    vncSetNotifyFd(listener->getFd(), screenIndex, true, false);\n}\n\nXserverDesktop::~XserverDesktop()\n{\n  while (!listeners.empty()) {\n    vncRemoveNotifyFd(listeners.back()->getFd());\n    delete listeners.back();\n    listeners.pop_back();\n  }\n  if (shadowFramebuffer)\n    delete [] shadowFramebuffer;\n  delete server;\n}\n\nvoid XserverDesktop::blockUpdates()\n{\n  server->blockUpdates();\n}\n\nvoid XserverDesktop::unblockUpdates()\n{\n  server->unblockUpdates();\n}\n\nvoid XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride_)\n{\n  rfb::ScreenSet layout;\n\n  if (shadowFramebuffer) {\n    delete [] shadowFramebuffer;\n    shadowFramebuffer = nullptr;\n  }\n\n  if (!fbptr) {\n    shadowFramebuffer = new uint8_t[w * h * (format.bpp/8)];\n    fbptr = shadowFramebuffer;\n    stride_ = w;\n  }\n\n  setBuffer(w, h, (uint8_t*)fbptr, stride_);\n\n  vncSetGlueContext(screenIndex);\n  layout = ::computeScreenLayout(&outputIdMap);\n\n  server->setPixelBuffer(this, layout);\n}\n\nvoid XserverDesktop::refreshScreenLayout()\n{\n  vncSetGlueContext(screenIndex);\n  server->setScreenLayout(::computeScreenLayout(&outputIdMap));\n}\n\nuint64_t XserverDesktop::getMsc()\n{\n  return server->getMsc();\n}\n\nvoid XserverDesktop::queueMsc(uint64_t id, uint64_t msc)\n{\n  pendingMsc[id] = msc;\n  server->queueMsc(msc);\n}\n\nvoid XserverDesktop::abortMsc(uint64_t id)\n{\n  pendingMsc.erase(id);\n}\n\nvoid XserverDesktop::init(rfb::VNCServer* vs)\n{\n  // We already own the server object, and we always keep it in a\n  // ready state\n}\n\nvoid XserverDesktop::queryConnection(network::Socket* sock,\n                                     const char* userName)\n{\n  int count;\n\n  if (queryConnectTimer.isStarted()) {\n    server->approveConnection(sock, false, \"Another connection is currently being queried.\");\n    return;\n  }\n\n  count = vncNotifyQueryConnect();\n  if (count == 0) {\n    server->approveConnection(sock, false, \"Unable to query the local user to accept the connection.\");\n    return;\n  }\n\n  queryConnectAddress = sock->getPeerAddress();\n  if (!userName)\n    userName = \"(anonymous)\";\n  queryConnectUsername = userName;\n  queryConnectId = (uint32_t)(intptr_t)sock;\n  queryConnectSocket = sock;\n\n  queryConnectTimer.start(queryConnectTimeout * 1000);\n}\n\nvoid XserverDesktop::requestClipboard()\n{\n  try {\n    server->requestClipboard();\n  } catch (std::exception& e) {\n    vlog.error(\"XserverDesktop::requestClipboard: %s\",e.what());\n  }\n}\n\nvoid XserverDesktop::announceClipboard(bool available)\n{\n  try {\n    server->announceClipboard(available);\n  } catch (std::exception& e) {\n    vlog.error(\"XserverDesktop::announceClipboard: %s\",e.what());\n  }\n}\n\nvoid XserverDesktop::sendClipboardData(const char* data_)\n{\n  try {\n    server->sendClipboardData(data_);\n  } catch (std::exception& e) {\n    vlog.error(\"XserverDesktop::sendClipboardData: %s\",e.what());\n  }\n}\n\nvoid XserverDesktop::bell()\n{\n  server->bell();\n}\n\nvoid XserverDesktop::setLEDState(unsigned int state)\n{\n  server->setLEDState(state);\n}\n\nvoid XserverDesktop::setDesktopName(const char* name)\n{\n  try {\n    server->setName(name);\n  } catch (std::exception& e) {\n    vlog.error(\"XserverDesktop::setDesktopName: %s\",e.what());\n  }\n}\n\nvoid XserverDesktop::setCursor(int width, int height, int hotX, int hotY,\n                               const unsigned char *rgbaData)\n{\n  uint8_t* cursorData;\n\n  uint8_t *out;\n  const unsigned char *in;\n\n  cursorData = new uint8_t[width * height * 4];\n\n  // Un-premultiply alpha\n  in = rgbaData;\n  out = cursorData;\n  for (int y = 0; y < height; y++) {\n    for (int x = 0; x < width; x++) {\n      uint8_t alpha;\n\n      alpha = in[3];\n      if (alpha == 0)\n        alpha = 1; // Avoid division by zero\n\n      *out++ = (unsigned)*in++ * 255/alpha;\n      *out++ = (unsigned)*in++ * 255/alpha;\n      *out++ = (unsigned)*in++ * 255/alpha;\n      *out++ = *in++;\n    }\n  }\n\n  try {\n    server->setCursor(width, height, {hotX, hotY}, cursorData);\n  } catch (std::exception& e) {\n    vlog.error(\"XserverDesktop::setCursor: %s\",e.what());\n  }\n\n  delete [] cursorData;\n}\n\nvoid XserverDesktop::setCursorPos(int x, int y, bool warped)\n{\n  try {\n    server->setCursorPos({x, y}, warped);\n  } catch (std::exception& e) {\n    vlog.error(\"XserverDesktop::setCursorPos: %s\",e.what());\n  }\n}\n\nvoid XserverDesktop::add_changed(const core::Region& region)\n{\n  try {\n    server->add_changed(region);\n  } catch (std::exception& e) {\n    vlog.error(\"XserverDesktop::add_changed: %s\",e.what());\n  }\n}\n\nvoid XserverDesktop::add_copied(const core::Region& dest,\n                                const core::Point& delta)\n{\n  try {\n    server->add_copied(dest, delta);\n  } catch (std::exception& e) {\n    vlog.error(\"XserverDesktop::add_copied: %s\",e.what());\n  }\n}\n\nvoid XserverDesktop::handleSocketEvent(int fd, bool read, bool write)\n{\n  try {\n    if (read) {\n      if (handleListenerEvent(fd))\n        return;\n    }\n\n    if (handleSocketReadWrite(fd, read, write))\n      return;\n\n    vlog.error(\"Cannot find file descriptor for socket event\");\n  } catch (std::exception& e) {\n    vlog.error(\"XserverDesktop::handleSocketEvent: %s\",e.what());\n  }\n}\n\nbool XserverDesktop::handleListenerEvent(int fd)\n{\n  std::list<network::SocketListener*>::iterator i;\n\n  for (i = listeners.begin(); i != listeners.end(); i++) {\n    if ((*i)->getFd() == fd)\n      break;\n  }\n\n  if (i == listeners.end())\n    return false;\n\n  network::Socket* sock = (*i)->accept();\n  vlog.debug(\"New client, sock %d\", sock->getFd());\n  if (!server->addSocket(sock)) {\n    delete sock;\n    return true;\n  }\n  vncSetNotifyFd(sock->getFd(), screenIndex, true, false);\n\n  return true;\n}\n\nbool XserverDesktop::handleSocketReadWrite(int fd, bool read, bool write)\n{\n  std::list<network::Socket*> sockets;\n  std::list<network::Socket*>::iterator i;\n\n  server->getSockets(&sockets);\n  for (i = sockets.begin(); i != sockets.end(); i++) {\n    if ((*i)->getFd() == fd)\n      break;\n  }\n\n  if (i == sockets.end())\n    return false;\n\n  if (read)\n    server->processSocketReadEvent(*i);\n\n  if (write)\n    server->processSocketWriteEvent(*i);\n\n  return true;\n}\n\nvoid XserverDesktop::blockHandler(int* timeout)\n{\n  // We don't have a good callback for when we can init input devices[1],\n  // so we abuse the fact that this routine will be called first thing\n  // once the dix is done initialising.\n  // [1] Technically Xvnc has InitInput(), but libvnc.so has nothing.\n  vncInitInputDevice();\n\n  try {\n    std::list<network::Socket*> sockets;\n    std::list<network::Socket*>::iterator i;\n    server->getSockets(&sockets);\n    for (i = sockets.begin(); i != sockets.end(); i++) {\n      int fd = (*i)->getFd();\n\n      if ((*i)->isShutdownRead()) {\n        vlog.debug(\"Client gone, sock %d\",fd);\n        vncRemoveNotifyFd(fd);\n        server->removeSocket(*i);\n        vncClientGone(fd);\n        delete (*i);\n      }\n\n      /* Update existing NotifyFD to listen for write (or not) */\n      vncSetNotifyFd(fd, screenIndex, true, (*i)->outStream().hasBufferedData());\n    }\n\n    // We are responsible for propagating mouse movement between clients\n    int cursorX, cursorY;\n    vncGetPointerPos(&cursorX, &cursorY);\n    cursorX -= vncGetScreenX(screenIndex);\n    cursorY -= vncGetScreenY(screenIndex);\n    if (oldCursorPos.x != cursorX || oldCursorPos.y != cursorY) {\n      oldCursorPos.x = cursorX;\n      oldCursorPos.y = cursorY;\n      server->setCursorPos(oldCursorPos, false);\n    }\n\n    // Trigger timers and check when the next will expire\n    int nextTimeout = core::Timer::checkTimeouts();\n    if (nextTimeout >= 0 && (*timeout == -1 || nextTimeout < *timeout))\n      *timeout = nextTimeout;\n  } catch (std::exception& e) {\n    vlog.error(\"XserverDesktop::blockHandler: %s\", e.what());\n  }\n}\n\nbool XserverDesktop::addClient(network::Socket* sock,\n                               bool reverse, bool viewOnly)\n{\n  rfb::AccessRights rights;\n\n  vlog.debug(\"New client, sock %d reverse %d\",sock->getFd(),reverse);\n\n  rights = viewOnly ? rfb::AccessView : rfb::AccessDefault;\n  if (!server->addSocket(sock, reverse, rights))\n    return false;\n\n  vncSetNotifyFd(sock->getFd(), screenIndex, true, false);\n\n  return true;\n}\n\nvoid XserverDesktop::disconnectClients()\n{\n  vlog.debug(\"Disconnecting all clients\");\n  return server->closeClients(\"Disconnection from server end\");\n}\n\n\nvoid XserverDesktop::getQueryConnect(uint32_t* opaqueId,\n                                     const char** address,\n                                     const char** username,\n                                     int *timeout)\n{\n  *opaqueId = queryConnectId;\n\n  if (!queryConnectTimer.isStarted()) {\n    *address = \"\";\n    *username = \"\";\n    *timeout = 0;\n  } else {\n    *address = queryConnectAddress.c_str();\n    *username = queryConnectUsername.c_str();\n    *timeout = queryConnectTimeout;\n  }\n}\n\nvoid XserverDesktop::approveConnection(uint32_t opaqueId, bool accept,\n                                       const char* rejectMsg)\n{\n  if (queryConnectId == opaqueId) {\n    server->approveConnection(queryConnectSocket, accept, rejectMsg);\n    queryConnectId = 0;\n    queryConnectTimer.stop();\n  }\n}\n\n///////////////////////////////////////////////////////////////////////////\n//\n// SDesktop callbacks\n\n\nvoid XserverDesktop::terminate()\n{\n  kill(getpid(), SIGTERM);\n}\n\nvoid XserverDesktop::pointerEvent(const core::Point& pos,\n                                  uint16_t buttonMask)\n{\n  vncPointerMove(pos.x + vncGetScreenX(screenIndex),\n                 pos.y + vncGetScreenY(screenIndex));\n  vncPointerButtonAction(buttonMask);\n}\n\nunsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height,\n                                             const rfb::ScreenSet& layout)\n{\n  unsigned int result;\n\n  vncSetGlueContext(screenIndex);\n  result = ::setScreenLayout(fb_width, fb_height, layout, &outputIdMap);\n\n  // Explicitly update the server state with the result as there\n  // can be corner cases where we don't get feedback from the X core\n  refreshScreenLayout();\n\n  return result;\n}\n\nvoid XserverDesktop::frameTick(uint64_t msc)\n{\n  std::map<uint64_t, uint64_t>::iterator iter, next;\n\n  for (iter = pendingMsc.begin(); iter != pendingMsc.end();) {\n    next = iter; next++;\n\n    if (iter->second <= msc) {\n      pendingMsc.erase(iter->first);\n      vncPresentMscEvent(iter->first, msc);\n    }\n\n    iter = next;\n  }\n}\n\nvoid XserverDesktop::handleClipboardRequest()\n{\n  vncHandleClipboardRequest();\n}\n\nvoid XserverDesktop::handleClipboardAnnounce(bool available)\n{\n  vncHandleClipboardAnnounce(available);\n}\n\nvoid XserverDesktop::handleClipboardData(const char* data_)\n{\n  vncHandleClipboardData(data_);\n}\n\nvoid XserverDesktop::grabRegion(const core::Region& region)\n{\n  if (shadowFramebuffer == nullptr)\n    return;\n\n  std::vector<core::Rect> rects;\n  std::vector<core::Rect>::iterator i;\n  region.get_rects(&rects);\n  for (i = rects.begin(); i != rects.end(); i++) {\n    uint8_t *buffer;\n    int bufStride;\n\n    buffer = getBufferRW(*i, &bufStride);\n    vncGetScreenImage(screenIndex, i->tl.x, i->tl.y, i->width(), i->height(),\n                      (char*)buffer, bufStride * format.bpp/8);\n    commitBufferRW(*i);\n  }\n}\n\nvoid XserverDesktop::keyEvent(uint32_t keysym, uint32_t keycode, bool down)\n{\n  if (!rawKeyboard)\n    keycode = 0;\n\n  vncKeyboardEvent(keysym, keycode, down);\n}\n\nvoid XserverDesktop::handleTimeout(core::Timer* t)\n{\n  if (t == &queryConnectTimer) {\n    server->approveConnection(queryConnectSocket, false,\n                              \"The attempt to prompt the user to \"\n                              \"accept the connection failed\");\n  }\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/XserverDesktop.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n//\n// XserverDesktop.h\n//\n\n#ifndef __XSERVERDESKTOP_H__\n#define __XSERVERDESKTOP_H__\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include <map>\n\n#include <stdint.h>\n\n#include <core/Timer.h>\n\n#include <rfb/SDesktop.h>\n#include <rfb/PixelBuffer.h>\n\n#include <unixcommon.h>\n\n#include \"vncInput.h\"\n\nnamespace rfb {\n  class VNCServerST;\n}\n\nnamespace network { class SocketListener; class Socket; }\n\nclass XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,\n                       public core::Timer::Callback {\npublic:\n\n  XserverDesktop(int screenIndex,\n                 std::list<network::SocketListener*> listeners_,\n                 const char* name, const rfb::PixelFormat &pf,\n                 int width, int height, void* fbptr, int stride);\n  virtual ~XserverDesktop();\n\n  // methods called from X server code\n  void blockUpdates();\n  void unblockUpdates();\n  void setFramebuffer(int w, int h, void* fbptr, int stride);\n  void refreshScreenLayout();\n  uint64_t getMsc();\n  void queueMsc(uint64_t id, uint64_t msc);\n  void abortMsc(uint64_t id);\n  void requestClipboard();\n  void announceClipboard(bool available);\n  void sendClipboardData(const char* data);\n  void bell();\n  void setLEDState(unsigned int state);\n  void setDesktopName(const char* name);\n  void setCursor(int width, int height, int hotX, int hotY,\n                 const unsigned char *rgbaData);\n  void setCursorPos(int x, int y, bool warped);\n  void add_changed(const core::Region& region);\n  void add_copied(const core::Region& dest, const core::Point& delta);\n  void handleSocketEvent(int fd, bool read, bool write);\n  void blockHandler(int* timeout);\n  bool addClient(network::Socket* sock, bool reverse, bool viewOnly);\n  void disconnectClients();\n\n  // QueryConnect methods called from X server code\n  // getQueryConnect()\n  //   Returns information about the currently waiting query\n  //   (or an id of 0 if there is none waiting)\n  void getQueryConnect(uint32_t* opaqueId, const char** address,\n                       const char** username, int *timeout);\n\n  // approveConnection()\n  //   Used by X server code to supply the result of a query.\n  void approveConnection(uint32_t opaqueId, bool accept,\n                         const char* rejectMsg=0);\n\n  // rfb::SDesktop callbacks\n  void init(rfb::VNCServer* vs) override;\n  void terminate() override;\n  void queryConnection(network::Socket* sock,\n                       const char* userName) override;\n  void pointerEvent(const core::Point& pos,\n                    uint16_t buttonMask) override;\n  void keyEvent(uint32_t keysym, uint32_t keycode, bool down) override;\n  unsigned int setScreenLayout(int fb_width, int fb_height,\n                               const rfb::ScreenSet& layout) override;\n  void frameTick(uint64_t msc) override;\n  void handleClipboardRequest() override;\n  void handleClipboardAnnounce(bool available) override;\n  void handleClipboardData(const char* data) override;\n\n  // rfb::PixelBuffer callbacks\n  void grabRegion(const core::Region& r) override;\n\nprotected:\n  bool handleListenerEvent(int fd);\n  bool handleSocketReadWrite(int fd, bool read, bool write);\n\n  void handleTimeout(core::Timer* t) override;\n\nprivate:\n\n  int screenIndex;\n  rfb::VNCServer* server;\n  std::list<network::SocketListener*> listeners;\n  uint8_t* shadowFramebuffer;\n\n  uint32_t queryConnectId;\n  network::Socket* queryConnectSocket;\n  std::string queryConnectAddress;\n  std::string queryConnectUsername;\n  core::Timer queryConnectTimer;\n\n  OutputIdMap outputIdMap;\n\n  std::map<uint64_t, uint64_t> pendingMsc;\n\n  core::Point oldCursorPos;\n};\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/Xvnc.man",
    "content": ".TH Xvnc 1 \"\" \"TigerVNC\" \"Virtual Network Computing\"\n.SH NAME\nXvnc \\- the X VNC server \n.SH SYNOPSIS\n.B Xvnc\n.RI [ options ] \n.RI : display#\n.SH DESCRIPTION\n.B Xvnc\nis the X VNC (Virtual Network Computing) server.  It is based on a standard X\nserver, but it has a \"virtual\" screen rather than a physical one.  X\napplications display themselves on it as if it were a normal X display, but\nthey can only be accessed via a VNC viewer - see \\fBvncviewer\\fP(1).\n\nSo Xvnc is really two servers in one. To the applications it is an X server,\nand to the remote VNC users it is a VNC server. By convention we have arranged\nthat the VNC server display number will be the same as the X server display\nnumber, which means you can use eg. snoopy:2 to refer to display 2 on machine\n\"snoopy\" in both the X world and the VNC world.\n\nThe best way of starting \\fBXvnc\\fP is via \\fBvncsession\\fP.  This sets up the\nenvironment appropriately and starts a desktop environment. See the manual\npage for \\fBvncsession\\fP(8) for more information.\n\n.SH OPTIONS\n.B Xvnc\ntakes lots of options - running \\fBXvnc -help\\fP gives a list.  Many of these\nare standard X server options, which are described in the \\fBXserver\\fP(1)\nmanual page.  In addition to options which can only be set via the\ncommand-line, there are also \"parameters\" which can be set both via the\ncommand-line and through the \\fBvncconfig\\fP(1) program.\n\n.TP\n.B \\-depth \\fIdepth\\fP\nSpecify the pixel depth in bits of the desktop to be created. Default is 24,\nother possible values are 16 and 32. Anything else is likely to cause strange\nbehaviour by applications and may prevent the server from starting at all.\n.\n.TP\n.B \\-geometry \\fIwidth\\fPx\\fIheight\\fP\nSpecify the size of the desktop to be created. Default is 1024x768.\n.\n.TP\n.B \\-help\nList all the options and parameters\n.\n.TP\n.B \\-inetd\nThis significantly changes Xvnc's behaviour so that it can be launched from\ninetd.  See the section below on usage with inetd.\n.\n.TP\n.B \\-pixelformat \\fIformat\\fP\nSpecify pixel format for server to use (BGRnnn or RGBnnn). The default for\ndepth 16 is RGB565 and for depth 24 and 32 is RGB888.\n.\n.TP\n.B \\-rendernode \\fIpath\\fP\nDRM render node to use for DRI3 GPU acceleration. Specify an empty path to\ndisable DRI3. Default is \\fBauto\\fP which makes \\fBXvnc\\fP pick a suitable\navailable render node.\n\n.SH PARAMETERS\nVNC parameters can be set both via the command-line and through the\n\\fBvncconfig\\fP(1) program, and with a VNC-enabled Xorg server via Options\nentries in the xorg.conf file.\n\nParameters can be turned on with -\\fIparam\\fP or off with\n-\\fIparam\\fP=0.  Parameters which take a value can be specified as\n-\\fIparam\\fP \\fIvalue\\fP.  Other valid forms are \\fIparam\\fP\\fB=\\fP\\fIvalue\\fP\n-\\fIparam\\fP=\\fIvalue\\fP --\\fIparam\\fP=\\fIvalue\\fP.  Parameter names are\ncase-insensitive.\n\n.TP\n.B \\-AcceptCutText\nAccept clipboard updates from clients. Default is on.\n.\n.TP\n.B \\-AcceptKeyEvents\nAccept key press and release events from clients. Default is on.\n.\n.TP\n.B \\-AcceptPointerEvents\nAccept pointer movement and button events from clients. Default is on.\n.\n.TP\n.B \\-AcceptSetDesktopSize\nAccept requests to resize the size of the desktop. Default is on.\n.\n.TP\n.B \\-AllowOverride\nComma separated list of parameters that can be modified using VNC extension.\nParameters can be modified for example using \\fBvncconfig\\fP(1) program from\ninside a running session.\n.\n.TP\n.B \\-AlwaysShared\nAlways treat incoming connections as shared, regardless of the client-specified\nsetting. Default is off.\n.\n.TP\n.B \\-AvoidShiftNumLock\nKey affected by NumLock often require a fake Shift to be inserted in order\nfor the correct symbol to be generated. Turning on this option avoids these\nextra fake Shift events but may result in a slightly different symbol\n(e.g. a Return instead of a keypad Enter).\n.\n.TP\n.B \\-BlacklistThreshold \\fIcount\\fP\nThe number of unauthenticated connection attempts allowed from any individual\nhost before that host is black-listed.  Default is 5.\n.\n.TP\n.B \\-BlacklistTimeout \\fIseconds\\fP\nThe initial timeout applied when a host is first black-listed.  The host\ncannot re-attempt a connection until the timeout expires.  Default is 10.\n.\n.TP\n.B \\-CompareFB \\fImode\\fP\nPerform pixel comparison on framebuffer to reduce unnecessary updates. Can\nbe either \\fB0\\fP (off), \\fB1\\fP (always) or \\fB2\\fP (auto). Default is\n\\fB2\\fP.\n.\n.TP\n.B \\-desktop \\fIdesktop-name\\fP\nEach desktop has a name which may be displayed by the viewer. It defaults to\n\"<user>@<hostname>\".\n.\n.TP\n.B \\-DisconnectClients\nDisconnect existing clients if an incoming connection is non-shared. Default is\non. If \\fBDisconnectClients\\fP is false, then a new non-shared connection will\nbe refused while there is a client active.  When combined with\n\\fBNeverShared\\fP this means only one client is allowed at a time.\n.\n.TP\n.B \\-FrameRate \\fIfps\\fP\nThe maximum number of updates per second sent to each client. If the screen\nupdates any faster then those changes will be aggregated and sent in a single\nupdate to the client. Note that this only controls the maximum rate and a\nclient may get a lower rate when resources are limited. Default is \\fB60\\fP.\n.\n.TP\n.B \\-GnuTLSPriority \\fIpriority\\fP\nGnuTLS priority string that controls the TLS session’s handshake algorithms.\nSee the GnuTLS manual for possible values. For GnuTLS < 3.6.3 the default\nvalue will be \\fBNORMAL\\fP to use upstream default. For newer versions\nof GnuTLS system-wide crypto policy will be used.\n.\n.TP\n.B \\-IdleTimeout \\fIseconds\\fP\nThe number of seconds after which an idle VNC connection will be dropped.\nDefault is 0, which means that idle connections will never be dropped.\n.\n.TP\n.B \\-ImprovedHextile\nUse improved compression algorithm for Hextile encoding which achieves better\ncompression ratios by the cost of using slightly more CPU time.  Default is\non.\n.\n.TP\n.B \\-interface \\fIIP address\\fP\nListen on interface. By default Xvnc listens on all available interfaces.\n.\n.TP\n.B \\-localhost\nOnly allow connections from the same machine. Useful if you use SSH and want to\nstop non-SSH connections from any other hosts.\n.\n.TP\n.B \\-Log \\fIlogname\\fP:\\fIdest\\fP:\\fIlevel\\fP[, ...]\nConfigures the debug log settings.  \\fIdest\\fP can currently be \\fBstderr\\fP,\n\\fBstdout\\fP or \\fBsyslog\\fP, and \\fIlevel\\fP is between 0 and 100, 100 meaning\nmost verbose output.  \\fIlogname\\fP is usually \\fB*\\fP meaning all, but you can\ntarget a specific source file if you know the name of its \"LogWriter\".  Default\nis \\fB*:stderr:30\\fP.\n.\n.TP\n.B \\-MaxConnectionTime \\fIseconds\\fP\nTerminate when a client has been connected for \\fIN\\fP seconds.  Default is\n0.\n.\n.TP\n.B \\-MaxCutText \\fIbytes\\fP\nThe maximum size of a clipboard update that will be accepted from a client.\nDefault is \\fB262144\\fP.\n.\n.TP\n.B \\-MaxDisconnectionTime \\fIseconds\\fP\nTerminate when no client has been connected for \\fIN\\fP seconds.  Default is\n0.\n.\n.TP\n.B \\-MaxIdleTime \\fIseconds\\fP\nTerminate after \\fIN\\fP seconds of user inactivity.  Default is 0.\n.\n.TP\n.B \\-NeverShared\nNever treat incoming connections as shared, regardless of the client-specified\nsetting. Default is off.\n.\n.TP\n.B \\-pam_service \\fIname\\fP, \\-PAMService \\fIname\\fP\nPAM service name to use when authentication users using any of the \"Plain\"\nsecurity types. Default is \\fBvnc\\fP.\n.\n.TP\n.B \\-Password \\fIpassword\\fP\nObfuscated binary encoding of the password which clients must supply to\naccess the server.  Using this parameter is insecure, use \\fBPasswordFile\\fP\nparameter instead.\n.\n.TP\n.B \\-PasswordFile \\fIpasswd-file\\fP, \\-rfbauth \\fIpasswd-file\\fP\nPassword file for VNC authentication.  There is no default, you should\nspecify the password file explicitly.  Password file should be created with\nthe \\fBvncpasswd\\fP(1) utility.  The file is accessed each time a connection\ncomes in, so it can be changed on the fly.\n.\n.TP\n.B \\-PlainUsers \\fIuser-list\\fP\nA comma separated list of user names that are allowed to authenticate via\nany of the \"Plain\" security types (Plain, TLSPlain, etc.). Specify \\fB*\\fP\nto allow any user to authenticate using this security type. Specify \\fB%u\\fP\nto allow the user of the server process. Default is to deny all users.\n.\n.TP\n.B \\-Protocol3.3\nAlways use protocol version 3.3 for backwards compatibility with badly-behaved\nclients. Default is off.\n.\n.TP\n.B \\-QueryConnect\nPrompts the user of the desktop to explicitly accept or reject incoming\nconnections. Default is off.\n\nThe \\fBvncconfig\\fP(1) program must be running on the desktop in order for\nQueryConnect to be supported.\n.\n.TP\n.B \\-QueryConnectTimeout \\fIseconds\\fP\nNumber of seconds to show the Accept connection dialog before rejecting the\nconnection.  Default is \\fB10\\fP.\n.\n.TP\n.B \\-RawKeyboard\nSend keyboard events straight through and avoid mapping them to the current\nkeyboard layout. This effectively makes the keyboard behave according to the\nlayout configured on the server instead of the layout configured on the\nclient. Default is off.\n.\n.TP\n.B \\-RemapKeys \\fImapping\nSets up a keyboard mapping.\n.I mapping\nis a comma-separated string of character mappings, each of the form\n.IR char -> char ,\nor\n.IR char <> char ,\nwhere\n.I char\nis a hexadecimal keysym. For example, to exchange the \" and @ symbols you would specify the following:\n\n.RS 10\nRemapKeys=0x22<>0x40\n.RE\n.\n.TP\n.B \\-RequireUsername\nRequire username for the RSA-AES security types. Default is off.\n.\n.TP\n.B \\-rfbport \\fIport\\fP\nSpecifies the TCP port on which Xvnc listens for connections from viewers (the\nprotocol used in VNC is called RFB - \"remote framebuffer\").  The default is\n5900 plus the display number. Specify \\fB-1\\fP to disable listening on a TCP\nport.\n.\n.TP\n.B \\-rfbunixmode \\fImode\\fP\nSpecifies the mode of the Unix domain socket.  The default is 0600.\n.\n.TP\n.B \\-rfbunixpath \\fIpath\\fP\nSpecifies the path of a Unix domain socket on which Xvnc listens for\nconnections from viewers.\n.\n.TP\n.B \\-RSAKey \\fIpath\\fP\nPath to the RSA key for the RSA-AES security types (\\fBRA2\\fP, \\fBRA2ne\\fP,\n\\fBRA2_256\\fP and \\fBRA2ne_256\\fP) in PEM format.\n.\n.TP\n.B \\-SecurityTypes \\fIsec-types\\fP\nSpecify which security scheme to use for incoming connections.  Valid values\nare a comma separated list of \\fBNone\\fP, \\fBVncAuth\\fP, \\fBPlain\\fP,\n\\fBTLSNone\\fP, \\fBTLSVnc\\fP, \\fBTLSPlain\\fP, \\fBX509None\\fP, \\fBX509Vnc\\fP,\n\\fBX509Plain\\fP, \\fBRA2\\fP, \\fBRA2ne\\fP, \\fBRA2_256\\fP and \\fBRA2ne_256\\fP.\nDefault is \\fBTLSVnc,VncAuth\\fP.\n.\n.TP\n.B \\-SendCutText\nSend clipboard changes to clients. Default is on.\n.\n.TP\n.B \\-SendPrimary\nSend the primary selection and cut buffer to the server as well as the\nclipboard selection. Default is on.\n.\n.TP\n.B \\-SetPrimary\nSet the primary selection as well as the clipboard selection.\nDefault is on.\n.\n.TP\n.B \\-UseBlacklist\nTemporarily reject connections from a host if it repeatedly fails to\nauthenticate. Default is on.\n.\n.TP\n.B \\-UseIPv4\nUse IPv4 for incoming and outgoing connections. Default is on.\n.\n.TP\n.B \\-UseIPv6\nUse IPv6 for incoming and outgoing connections. Default is on.\n.\n.TP\n.B \\-X509Cert \\fIpath\\fP\nPath to a X509 certificate in PEM format to be used for all X509 based\nsecurity types (X509None, X509Vnc, etc.).\n.\n.TP\n.B \\-X509Key \\fIpath\\fP\nPrivate key counter part to the certificate given in \\fBX509Cert\\fP. Must\nalso be in PEM format.\n\nAllowing override of parameters such as \\fBPAMService\\fP or \\fBPasswordFile\\fP\ncan negatively impact security if Xvnc runs under different user than the\nprograms allowed to override the parameters.\n\nWhen \\fBNoClipboard\\fP parameter is set, allowing override of \\fBSendCutText\\fP\nand \\fBAcceptCutText\\fP has no effect.\n\nDefault is \\fBdesktop,AcceptPointerEvents,SendCutText,AcceptCutText,SendPrimary,SetPrimary\\fP.\n\n.SH USAGE WITH INETD\nBy configuring the \\fBinetd\\fP(1) service appropriately, Xvnc can be launched\non demand when a connection comes in, rather than having to be started\nmanually.  When given the \\fB-inetd\\fP option, instead of listening for TCP\nconnections on a given port it uses its standard input and standard output.\nThere are two modes controlled by the wait/nowait entry in the inetd.conf file.\n\nIn the nowait mode, Xvnc uses its standard input and output directly as the\nconnection to a viewer.  It never has a listening socket, so cannot accept\nfurther connections from viewers (it can however connect out to listening\nviewers by use of the vncconfig program).  Further viewer connections to the\nsame TCP port result in inetd spawning off a new Xvnc to deal with each\nconnection.  When the connection to the viewer dies, the Xvnc and any\nassociated X clients die.  This behaviour is most useful when combined with the\nXDMCP options -query and -once.  An typical example in inetd.conf might be (all\non one line):\n\n5950   stream   tcp nowait nobody  /usr/local/bin/Xvnc Xvnc -inetd -query\nlocalhost -once securitytypes=none\n\nIn this example a viewer connection to :50 will result in a new Xvnc for that\nconnection which should display the standard XDM login screen on that machine.\nIt is usually OK to accept connections without a VNC password, since the user\nstill needs to log in via XDM in this case.\n\nIn the wait mode, when the first connection comes in, inetd gives the listening\nsocket to Xvnc.  This means that for a given TCP port, there is only ever one\nXvnc at a time.  Further viewer connections to the same port are accepted by\nthe same Xvnc in the normal way.  Even when the original connection is broken,\nthe Xvnc will continue to run.  If this is used with the XDMCP options -query\nand -once, the Xvnc and associated X clients will die when the user logs out of\nthe X session in the normal way.  It is important to use a VNC password in this\ncase.  A typical entry in inetd.conf might be:\n\n5951   stream   tcp wait   james     /usr/local/bin/Xvnc Xvnc -inetd -query localhost -once passwordFile=/home/james/.config/tigervnc/passwd\n\nIn fact typically, you would have one entry for each user who uses VNC\nregularly, each of whom has their own dedicated TCP port which they use.  In\nthis example, when user \"james\" connects to :51, he enters his VNC password,\nthen gets the XDM login screen where he logs in in the normal way.  However,\nunlike the previous example, if he disconnects, the session remains persistent,\nand when he reconnects he will get the same session back again.  When he logs\nout of the X session, the Xvnc will die, but of course a new one will be\ncreated automatically the next time he connects.\n\n.SH SEE ALSO\n.BR vncconfig (1),\n.BR vncpasswd (1),\n.BR vncviewer (1),\n.BR vncsession (8),\n.BR Xserver (1),\n.BR inetd (1)\n.br\nhttps://www.tigervnc.org\n\n.SH AUTHOR\nTristan Richardson, RealVNC Ltd. and others.\n\nVNC was originally developed by the RealVNC team while at Olivetti\nResearch Ltd / AT&T Laboratories Cambridge.  TightVNC additions were\nimplemented by Constantin Kaplinsky. Many other people have since\nparticipated in development, testing and support. This manual is part\nof the TigerVNC software suite.\n"
  },
  {
    "path": "unix/xserver/hw/vnc/buildtime.c",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\nchar buildtime[] = __DATE__ \" \" __TIME__;\n"
  },
  {
    "path": "unix/xserver/hw/vnc/qnum_to_xorgevdev.c",
    "content": "/*\n * This file is auto-generated from keymaps.csv\n * Database checksum sha256(527727ef96d7103a8d7725a6ed9738812660b5a3f4aec086dd7b587b1ba9fcca)\n * To re-generate, run:\n *   keymap-gen code-map --lang=stdc keymaps.csv qnum xorgevdev\n*/\nconst unsigned short code_map_qnum_to_xorgevdev[254] = {\n  [0x1] = 0x9, /* qnum:1 -> linux:1 (KEY_ESC) -> xorgevdev:9 */\n  [0x2] = 0xa, /* qnum:2 -> linux:2 (KEY_1) -> xorgevdev:10 */\n  [0x3] = 0xb, /* qnum:3 -> linux:3 (KEY_2) -> xorgevdev:11 */\n  [0x4] = 0xc, /* qnum:4 -> linux:4 (KEY_3) -> xorgevdev:12 */\n  [0x5] = 0xd, /* qnum:5 -> linux:5 (KEY_4) -> xorgevdev:13 */\n  [0x6] = 0xe, /* qnum:6 -> linux:6 (KEY_5) -> xorgevdev:14 */\n  [0x7] = 0xf, /* qnum:7 -> linux:7 (KEY_6) -> xorgevdev:15 */\n  [0x8] = 0x10, /* qnum:8 -> linux:8 (KEY_7) -> xorgevdev:16 */\n  [0x9] = 0x11, /* qnum:9 -> linux:9 (KEY_8) -> xorgevdev:17 */\n  [0xa] = 0x12, /* qnum:10 -> linux:10 (KEY_9) -> xorgevdev:18 */\n  [0xb] = 0x13, /* qnum:11 -> linux:11 (KEY_0) -> xorgevdev:19 */\n  [0xc] = 0x14, /* qnum:12 -> linux:12 (KEY_MINUS) -> xorgevdev:20 */\n  [0xd] = 0x15, /* qnum:13 -> linux:13 (KEY_EQUAL) -> xorgevdev:21 */\n  [0xe] = 0x16, /* qnum:14 -> linux:14 (KEY_BACKSPACE) -> xorgevdev:22 */\n  [0xf] = 0x17, /* qnum:15 -> linux:15 (KEY_TAB) -> xorgevdev:23 */\n  [0x10] = 0x18, /* qnum:16 -> linux:16 (KEY_Q) -> xorgevdev:24 */\n  [0x11] = 0x19, /* qnum:17 -> linux:17 (KEY_W) -> xorgevdev:25 */\n  [0x12] = 0x1a, /* qnum:18 -> linux:18 (KEY_E) -> xorgevdev:26 */\n  [0x13] = 0x1b, /* qnum:19 -> linux:19 (KEY_R) -> xorgevdev:27 */\n  [0x14] = 0x1c, /* qnum:20 -> linux:20 (KEY_T) -> xorgevdev:28 */\n  [0x15] = 0x1d, /* qnum:21 -> linux:21 (KEY_Y) -> xorgevdev:29 */\n  [0x16] = 0x1e, /* qnum:22 -> linux:22 (KEY_U) -> xorgevdev:30 */\n  [0x17] = 0x1f, /* qnum:23 -> linux:23 (KEY_I) -> xorgevdev:31 */\n  [0x18] = 0x20, /* qnum:24 -> linux:24 (KEY_O) -> xorgevdev:32 */\n  [0x19] = 0x21, /* qnum:25 -> linux:25 (KEY_P) -> xorgevdev:33 */\n  [0x1a] = 0x22, /* qnum:26 -> linux:26 (KEY_LEFTBRACE) -> xorgevdev:34 */\n  [0x1b] = 0x23, /* qnum:27 -> linux:27 (KEY_RIGHTBRACE) -> xorgevdev:35 */\n  [0x1c] = 0x24, /* qnum:28 -> linux:28 (KEY_ENTER) -> xorgevdev:36 */\n  [0x1d] = 0x25, /* qnum:29 -> linux:29 (KEY_LEFTCTRL) -> xorgevdev:37 */\n  [0x1e] = 0x26, /* qnum:30 -> linux:30 (KEY_A) -> xorgevdev:38 */\n  [0x1f] = 0x27, /* qnum:31 -> linux:31 (KEY_S) -> xorgevdev:39 */\n  [0x20] = 0x28, /* qnum:32 -> linux:32 (KEY_D) -> xorgevdev:40 */\n  [0x21] = 0x29, /* qnum:33 -> linux:33 (KEY_F) -> xorgevdev:41 */\n  [0x22] = 0x2a, /* qnum:34 -> linux:34 (KEY_G) -> xorgevdev:42 */\n  [0x23] = 0x2b, /* qnum:35 -> linux:35 (KEY_H) -> xorgevdev:43 */\n  [0x24] = 0x2c, /* qnum:36 -> linux:36 (KEY_J) -> xorgevdev:44 */\n  [0x25] = 0x2d, /* qnum:37 -> linux:37 (KEY_K) -> xorgevdev:45 */\n  [0x26] = 0x2e, /* qnum:38 -> linux:38 (KEY_L) -> xorgevdev:46 */\n  [0x27] = 0x2f, /* qnum:39 -> linux:39 (KEY_SEMICOLON) -> xorgevdev:47 */\n  [0x28] = 0x30, /* qnum:40 -> linux:40 (KEY_APOSTROPHE) -> xorgevdev:48 */\n  [0x29] = 0x31, /* qnum:41 -> linux:41 (KEY_GRAVE) -> xorgevdev:49 */\n  [0x2a] = 0x32, /* qnum:42 -> linux:42 (KEY_LEFTSHIFT) -> xorgevdev:50 */\n  [0x2b] = 0x33, /* qnum:43 -> linux:43 (KEY_BACKSLASH) -> xorgevdev:51 */\n  [0x2c] = 0x34, /* qnum:44 -> linux:44 (KEY_Z) -> xorgevdev:52 */\n  [0x2d] = 0x35, /* qnum:45 -> linux:45 (KEY_X) -> xorgevdev:53 */\n  [0x2e] = 0x36, /* qnum:46 -> linux:46 (KEY_C) -> xorgevdev:54 */\n  [0x2f] = 0x37, /* qnum:47 -> linux:47 (KEY_V) -> xorgevdev:55 */\n  [0x30] = 0x38, /* qnum:48 -> linux:48 (KEY_B) -> xorgevdev:56 */\n  [0x31] = 0x39, /* qnum:49 -> linux:49 (KEY_N) -> xorgevdev:57 */\n  [0x32] = 0x3a, /* qnum:50 -> linux:50 (KEY_M) -> xorgevdev:58 */\n  [0x33] = 0x3b, /* qnum:51 -> linux:51 (KEY_COMMA) -> xorgevdev:59 */\n  [0x34] = 0x3c, /* qnum:52 -> linux:52 (KEY_DOT) -> xorgevdev:60 */\n  [0x35] = 0x3d, /* qnum:53 -> linux:53 (KEY_SLASH) -> xorgevdev:61 */\n  [0x36] = 0x3e, /* qnum:54 -> linux:54 (KEY_RIGHTSHIFT) -> xorgevdev:62 */\n  [0x37] = 0x3f, /* qnum:55 -> linux:55 (KEY_KPASTERISK) -> xorgevdev:63 */\n  [0x38] = 0x40, /* qnum:56 -> linux:56 (KEY_LEFTALT) -> xorgevdev:64 */\n  [0x39] = 0x41, /* qnum:57 -> linux:57 (KEY_SPACE) -> xorgevdev:65 */\n  [0x3a] = 0x42, /* qnum:58 -> linux:58 (KEY_CAPSLOCK) -> xorgevdev:66 */\n  [0x3b] = 0x43, /* qnum:59 -> linux:59 (KEY_F1) -> xorgevdev:67 */\n  [0x3c] = 0x44, /* qnum:60 -> linux:60 (KEY_F2) -> xorgevdev:68 */\n  [0x3d] = 0x45, /* qnum:61 -> linux:61 (KEY_F3) -> xorgevdev:69 */\n  [0x3e] = 0x46, /* qnum:62 -> linux:62 (KEY_F4) -> xorgevdev:70 */\n  [0x3f] = 0x47, /* qnum:63 -> linux:63 (KEY_F5) -> xorgevdev:71 */\n  [0x40] = 0x48, /* qnum:64 -> linux:64 (KEY_F6) -> xorgevdev:72 */\n  [0x41] = 0x49, /* qnum:65 -> linux:65 (KEY_F7) -> xorgevdev:73 */\n  [0x42] = 0x4a, /* qnum:66 -> linux:66 (KEY_F8) -> xorgevdev:74 */\n  [0x43] = 0x4b, /* qnum:67 -> linux:67 (KEY_F9) -> xorgevdev:75 */\n  [0x44] = 0x4c, /* qnum:68 -> linux:68 (KEY_F10) -> xorgevdev:76 */\n  [0x45] = 0x4d, /* qnum:69 -> linux:69 (KEY_NUMLOCK) -> xorgevdev:77 */\n  [0x46] = 0x4e, /* qnum:70 -> linux:70 (KEY_SCROLLLOCK) -> xorgevdev:78 */\n  [0x47] = 0x4f, /* qnum:71 -> linux:71 (KEY_KP7) -> xorgevdev:79 */\n  [0x48] = 0x50, /* qnum:72 -> linux:72 (KEY_KP8) -> xorgevdev:80 */\n  [0x49] = 0x51, /* qnum:73 -> linux:73 (KEY_KP9) -> xorgevdev:81 */\n  [0x4a] = 0x52, /* qnum:74 -> linux:74 (KEY_KPMINUS) -> xorgevdev:82 */\n  [0x4b] = 0x53, /* qnum:75 -> linux:75 (KEY_KP4) -> xorgevdev:83 */\n  [0x4c] = 0x54, /* qnum:76 -> linux:76 (KEY_KP5) -> xorgevdev:84 */\n  [0x4d] = 0x55, /* qnum:77 -> linux:77 (KEY_KP6) -> xorgevdev:85 */\n  [0x4e] = 0x56, /* qnum:78 -> linux:78 (KEY_KPPLUS) -> xorgevdev:86 */\n  [0x4f] = 0x57, /* qnum:79 -> linux:79 (KEY_KP1) -> xorgevdev:87 */\n  [0x50] = 0x58, /* qnum:80 -> linux:80 (KEY_KP2) -> xorgevdev:88 */\n  [0x51] = 0x59, /* qnum:81 -> linux:81 (KEY_KP3) -> xorgevdev:89 */\n  [0x52] = 0x5a, /* qnum:82 -> linux:82 (KEY_KP0) -> xorgevdev:90 */\n  [0x53] = 0x5b, /* qnum:83 -> linux:83 (KEY_KPDOT) -> xorgevdev:91 */\n  [0x54] = 0x6b, /* qnum:84 -> linux:99 (KEY_SYSRQ) -> xorgevdev:107 */\n  [0x55] = 0xc2, /* qnum:85 -> linux:186 (KEY_F16) -> xorgevdev:194 */\n  [0x56] = 0x5e, /* qnum:86 -> linux:86 (KEY_102ND) -> xorgevdev:94 */\n  [0x57] = 0x5f, /* qnum:87 -> linux:87 (KEY_F11) -> xorgevdev:95 */\n  [0x58] = 0x60, /* qnum:88 -> linux:88 (KEY_F12) -> xorgevdev:96 */\n  [0x59] = 0x7d, /* qnum:89 -> linux:117 (KEY_KPEQUAL) -> xorgevdev:125 */\n  [0x5a] = 0xc6, /* qnum:90 -> linux:190 (KEY_F20) -> xorgevdev:198 */\n  [0x5b] = 0x6d, /* qnum:91 -> linux:101 (KEY_LINEFEED) -> xorgevdev:109 */\n  [0x5c] = 0x67, /* qnum:92 -> linux:95 (KEY_KPJPCOMMA) -> xorgevdev:103 */\n  [0x5d] = 0xbf, /* qnum:93 -> linux:183 (KEY_F13) -> xorgevdev:191 */\n  [0x5e] = 0xc0, /* qnum:94 -> linux:184 (KEY_F14) -> xorgevdev:192 */\n  [0x5f] = 0xc1, /* qnum:95 -> linux:185 (KEY_F15) -> xorgevdev:193 */\n  [0x63] = 0xb1, /* qnum:99 -> linux:169 (KEY_PHONE) -> xorgevdev:177 */\n  [0x64] = 0x8e, /* qnum:100 -> linux:134 (KEY_OPEN) -> xorgevdev:142 */\n  [0x65] = 0x8f, /* qnum:101 -> linux:135 (KEY_PASTE) -> xorgevdev:143 */\n  [0x66] = 0x95, /* qnum:102 -> linux:141 (KEY_SETUP) -> xorgevdev:149 */\n  [0x67] = 0x98, /* qnum:103 -> linux:144 (KEY_FILE) -> xorgevdev:152 */\n  [0x68] = 0x99, /* qnum:104 -> linux:145 (KEY_SENDFILE) -> xorgevdev:153 */\n  [0x69] = 0x9a, /* qnum:105 -> linux:146 (KEY_DELETEFILE) -> xorgevdev:154 */\n  [0x6a] = 0x9f, /* qnum:106 -> linux:151 (KEY_MSDOS) -> xorgevdev:159 */\n  [0x6b] = 0xa1, /* qnum:107 -> linux:153 (KEY_DIRECTION) -> xorgevdev:161 */\n  [0x6c] = 0xa9, /* qnum:108 -> linux:161 (KEY_EJECTCD) -> xorgevdev:169 */\n  [0x6d] = 0xc9, /* qnum:109 -> linux:193 (KEY_F23) -> xorgevdev:201 */\n  [0x6f] = 0xca, /* qnum:111 -> linux:194 (KEY_F24) -> xorgevdev:202 */\n  [0x70] = 0x65, /* qnum:112 -> linux:93 (KEY_KATAKANAHIRAGANA) -> xorgevdev:101 */\n  [0x71] = 0x83, /* qnum:113 -> linux:123 (KEY_HANJA) -> xorgevdev:131 */\n  [0x72] = 0x82, /* qnum:114 -> linux:122 (KEY_HANGEUL) -> xorgevdev:130 */\n  [0x73] = 0x61, /* qnum:115 -> linux:89 (KEY_RO) -> xorgevdev:97 */\n  [0x74] = 0xc7, /* qnum:116 -> linux:191 (KEY_F21) -> xorgevdev:199 */\n  [0x75] = 0xb9, /* qnum:117 -> linux:177 (KEY_SCROLLUP) -> xorgevdev:185 */\n  [0x76] = 0x5d, /* qnum:118 -> linux:85 (KEY_ZENKAKUHANKAKU) -> xorgevdev:93 */\n  [0x77] = 0x63, /* qnum:119 -> linux:91 (KEY_HIRAGANA) -> xorgevdev:99 */\n  [0x78] = 0x62, /* qnum:120 -> linux:90 (KEY_KATAKANA) -> xorgevdev:98 */\n  [0x79] = 0x64, /* qnum:121 -> linux:92 (KEY_HENKAN) -> xorgevdev:100 */\n  [0x7b] = 0x66, /* qnum:123 -> linux:94 (KEY_MUHENKAN) -> xorgevdev:102 */\n  [0x7d] = 0x84, /* qnum:125 -> linux:124 (KEY_YEN) -> xorgevdev:132 */\n  [0x7e] = 0x81, /* qnum:126 -> linux:121 (KEY_KPCOMMA) -> xorgevdev:129 */\n  [0x81] = 0xb3, /* qnum:129 -> linux:171 (KEY_CONFIG) -> xorgevdev:179 */\n  [0x82] = 0x9e, /* qnum:130 -> linux:150 (KEY_WWW) -> xorgevdev:158 */\n  [0x83] = 0xc3, /* qnum:131 -> linux:187 (KEY_F17) -> xorgevdev:195 */\n  [0x84] = 0xc5, /* qnum:132 -> linux:189 (KEY_F19) -> xorgevdev:197 */\n  [0x85] = 0x89, /* qnum:133 -> linux:129 (KEY_AGAIN) -> xorgevdev:137 */\n  [0x86] = 0x8a, /* qnum:134 -> linux:130 (KEY_PROPS) -> xorgevdev:138 */\n  [0x87] = 0x8b, /* qnum:135 -> linux:131 (KEY_UNDO) -> xorgevdev:139 */\n  [0x88] = 0xb8, /* qnum:136 -> linux:176 (KEY_EDIT) -> xorgevdev:184 */\n  [0x89] = 0xbd, /* qnum:137 -> linux:181 (KEY_NEW) -> xorgevdev:189 */\n  [0x8a] = 0xbe, /* qnum:138 -> linux:182 (KEY_REDO) -> xorgevdev:190 */\n  [0x8b] = 0x80, /* qnum:139 -> linux:120 (KEY_SCALE) -> xorgevdev:128 */\n  [0x8c] = 0x8c, /* qnum:140 -> linux:132 (KEY_FRONT) -> xorgevdev:140 */\n  [0x8e] = 0xf1, /* qnum:142 -> linux:233 (KEY_FORWARDMAIL) -> xorgevdev:241 */\n  [0x8f] = 0xba, /* qnum:143 -> linux:178 (KEY_SCROLLDOWN) -> xorgevdev:186 */\n  [0x90] = 0xad, /* qnum:144 -> linux:165 (KEY_PREVIOUSSONG) -> xorgevdev:173 */\n  [0x92] = 0xa0, /* qnum:146 -> linux:152 (KEY_SCREENLOCK) -> xorgevdev:160 */\n  [0x93] = 0x9b, /* qnum:147 -> linux:147 (KEY_XFER) -> xorgevdev:155 */\n  [0x94] = 0xe6, /* qnum:148 -> linux:222 (KEY_ALTERASE) -> xorgevdev:230 */\n  [0x95] = 0xcb, /* qnum:149 -> linux:195 (unnamed) -> xorgevdev:203 */\n  [0x96] = 0xcc, /* qnum:150 -> linux:196 (unnamed) -> xorgevdev:204 */\n  [0x97] = 0x9d, /* qnum:151 -> linux:149 (KEY_PROG2) -> xorgevdev:157 */\n  [0x98] = 0xb0, /* qnum:152 -> linux:168 (KEY_REWIND) -> xorgevdev:176 */\n  [0x99] = 0xab, /* qnum:153 -> linux:163 (KEY_NEXTSONG) -> xorgevdev:171 */\n  [0x9a] = 0xcd, /* qnum:154 -> linux:197 (unnamed) -> xorgevdev:205 */\n  [0x9b] = 0xce, /* qnum:155 -> linux:198 (unnamed) -> xorgevdev:206 */\n  [0x9c] = 0x68, /* qnum:156 -> linux:96 (KEY_KPENTER) -> xorgevdev:104 */\n  [0x9d] = 0x69, /* qnum:157 -> linux:97 (KEY_RIGHTCTRL) -> xorgevdev:105 */\n  [0x9e] = 0x93, /* qnum:158 -> linux:139 (KEY_MENU) -> xorgevdev:147 */\n  [0x9f] = 0x9c, /* qnum:159 -> linux:148 (KEY_PROG1) -> xorgevdev:156 */\n  [0xa0] = 0x79, /* qnum:160 -> linux:113 (KEY_MUTE) -> xorgevdev:121 */\n  [0xa1] = 0x94, /* qnum:161 -> linux:140 (KEY_CALC) -> xorgevdev:148 */\n  [0xa2] = 0xac, /* qnum:162 -> linux:164 (KEY_PLAYPAUSE) -> xorgevdev:172 */\n  [0xa3] = 0xa8, /* qnum:163 -> linux:160 (KEY_CLOSECD) -> xorgevdev:168 */\n  [0xa4] = 0xae, /* qnum:164 -> linux:166 (KEY_STOPCD) -> xorgevdev:174 */\n  [0xa5] = 0xd5, /* qnum:165 -> linux:205 (KEY_SUSPEND) -> xorgevdev:213 */\n  [0xa6] = 0xa2, /* qnum:166 -> linux:154 (KEY_CYCLEWINDOWS) -> xorgevdev:162 */\n  [0xa7] = 0xcf, /* qnum:167 -> linux:199 (unnamed) -> xorgevdev:207 */\n  [0xa8] = 0xd0, /* qnum:168 -> linux:200 (KEY_PLAYCD) -> xorgevdev:208 */\n  [0xa9] = 0xd1, /* qnum:169 -> linux:201 (KEY_PAUSECD) -> xorgevdev:209 */\n  [0xab] = 0xd2, /* qnum:171 -> linux:202 (KEY_PROG3) -> xorgevdev:210 */\n  [0xac] = 0xd3, /* qnum:172 -> linux:203 (KEY_PROG4) -> xorgevdev:211 */\n  [0xad] = 0xd4, /* qnum:173 -> linux:204 (KEY_DASHBOARD) -> xorgevdev:212 */\n  [0xae] = 0x7a, /* qnum:174 -> linux:114 (KEY_VOLUMEDOWN) -> xorgevdev:122 */\n  [0xaf] = 0xd6, /* qnum:175 -> linux:206 (KEY_CLOSE) -> xorgevdev:214 */\n  [0xb0] = 0x7b, /* qnum:176 -> linux:115 (KEY_VOLUMEUP) -> xorgevdev:123 */\n  [0xb1] = 0xaf, /* qnum:177 -> linux:167 (KEY_RECORD) -> xorgevdev:175 */\n  [0xb2] = 0xb4, /* qnum:178 -> linux:172 (KEY_HOMEPAGE) -> xorgevdev:180 */\n  [0xb3] = 0xd7, /* qnum:179 -> linux:207 (KEY_PLAY) -> xorgevdev:215 */\n  [0xb4] = 0xd8, /* qnum:180 -> linux:208 (KEY_FASTFORWARD) -> xorgevdev:216 */\n  [0xb5] = 0x6a, /* qnum:181 -> linux:98 (KEY_KPSLASH) -> xorgevdev:106 */\n  [0xb6] = 0xd9, /* qnum:182 -> linux:209 (KEY_BASSBOOST) -> xorgevdev:217 */\n  [0xb7] = 0x6b, /* qnum:183 -> linux:99 (KEY_SYSRQ) -> xorgevdev:107 */\n  [0xb8] = 0x6c, /* qnum:184 -> linux:100 (KEY_RIGHTALT) -> xorgevdev:108 */\n  [0xb9] = 0xda, /* qnum:185 -> linux:210 (KEY_PRINT) -> xorgevdev:218 */\n  [0xba] = 0xdb, /* qnum:186 -> linux:211 (KEY_HP) -> xorgevdev:219 */\n  [0xbb] = 0xdc, /* qnum:187 -> linux:212 (KEY_CAMERA) -> xorgevdev:220 */\n  [0xbc] = 0x91, /* qnum:188 -> linux:137 (KEY_CUT) -> xorgevdev:145 */\n  [0xbd] = 0xdd, /* qnum:189 -> linux:213 (KEY_SOUND) -> xorgevdev:221 */\n  [0xbe] = 0xde, /* qnum:190 -> linux:214 (KEY_QUESTION) -> xorgevdev:222 */\n  [0xbf] = 0xdf, /* qnum:191 -> linux:215 (KEY_EMAIL) -> xorgevdev:223 */\n  [0xc0] = 0xe0, /* qnum:192 -> linux:216 (KEY_CHAT) -> xorgevdev:224 */\n  [0xc1] = 0x90, /* qnum:193 -> linux:136 (KEY_FIND) -> xorgevdev:144 */\n  [0xc2] = 0xe2, /* qnum:194 -> linux:218 (KEY_CONNECT) -> xorgevdev:226 */\n  [0xc3] = 0xe3, /* qnum:195 -> linux:219 (KEY_FINANCE) -> xorgevdev:227 */\n  [0xc4] = 0xe4, /* qnum:196 -> linux:220 (KEY_SPORT) -> xorgevdev:228 */\n  [0xc5] = 0xe5, /* qnum:197 -> linux:221 (KEY_SHOP) -> xorgevdev:229 */\n  [0xc6] = 0x7f, /* qnum:198 -> linux:119 (KEY_PAUSE) -> xorgevdev:127 */\n  [0xc7] = 0x6e, /* qnum:199 -> linux:102 (KEY_HOME) -> xorgevdev:110 */\n  [0xc8] = 0x6f, /* qnum:200 -> linux:103 (KEY_UP) -> xorgevdev:111 */\n  [0xc9] = 0x70, /* qnum:201 -> linux:104 (KEY_PAGEUP) -> xorgevdev:112 */\n  [0xca] = 0xe7, /* qnum:202 -> linux:223 (KEY_CANCEL) -> xorgevdev:231 */\n  [0xcb] = 0x71, /* qnum:203 -> linux:105 (KEY_LEFT) -> xorgevdev:113 */\n  [0xcc] = 0xe8, /* qnum:204 -> linux:224 (KEY_BRIGHTNESSDOWN) -> xorgevdev:232 */\n  [0xcd] = 0x72, /* qnum:205 -> linux:106 (KEY_RIGHT) -> xorgevdev:114 */\n  [0xce] = 0x7e, /* qnum:206 -> linux:118 (KEY_KPPLUSMINUS) -> xorgevdev:126 */\n  [0xcf] = 0x73, /* qnum:207 -> linux:107 (KEY_END) -> xorgevdev:115 */\n  [0xd0] = 0x74, /* qnum:208 -> linux:108 (KEY_DOWN) -> xorgevdev:116 */\n  [0xd1] = 0x75, /* qnum:209 -> linux:109 (KEY_PAGEDOWN) -> xorgevdev:117 */\n  [0xd2] = 0x76, /* qnum:210 -> linux:110 (KEY_INSERT) -> xorgevdev:118 */\n  [0xd3] = 0x77, /* qnum:211 -> linux:111 (KEY_DELETE) -> xorgevdev:119 */\n  [0xd4] = 0xe9, /* qnum:212 -> linux:225 (KEY_BRIGHTNESSUP) -> xorgevdev:233 */\n  [0xd5] = 0xf2, /* qnum:213 -> linux:234 (KEY_SAVE) -> xorgevdev:242 */\n  [0xd6] = 0xeb, /* qnum:214 -> linux:227 (KEY_SWITCHVIDEOMODE) -> xorgevdev:235 */\n  [0xd7] = 0xec, /* qnum:215 -> linux:228 (KEY_KBDILLUMTOGGLE) -> xorgevdev:236 */\n  [0xd8] = 0xed, /* qnum:216 -> linux:229 (KEY_KBDILLUMDOWN) -> xorgevdev:237 */\n  [0xd9] = 0xee, /* qnum:217 -> linux:230 (KEY_KBDILLUMUP) -> xorgevdev:238 */\n  [0xda] = 0xef, /* qnum:218 -> linux:231 (KEY_SEND) -> xorgevdev:239 */\n  [0xdb] = 0x85, /* qnum:219 -> linux:125 (KEY_LEFTMETA) -> xorgevdev:133 */\n  [0xdc] = 0x86, /* qnum:220 -> linux:126 (KEY_RIGHTMETA) -> xorgevdev:134 */\n  [0xdd] = 0x87, /* qnum:221 -> linux:127 (KEY_COMPOSE) -> xorgevdev:135 */\n  [0xde] = 0x7c, /* qnum:222 -> linux:116 (KEY_POWER) -> xorgevdev:124 */\n  [0xdf] = 0x96, /* qnum:223 -> linux:142 (KEY_SLEEP) -> xorgevdev:150 */\n  [0xe3] = 0x97, /* qnum:227 -> linux:143 (KEY_WAKEUP) -> xorgevdev:151 */\n  [0xe4] = 0xf0, /* qnum:228 -> linux:232 (KEY_REPLY) -> xorgevdev:240 */\n  [0xe5] = 0xe1, /* qnum:229 -> linux:217 (KEY_SEARCH) -> xorgevdev:225 */\n  [0xe6] = 0xa4, /* qnum:230 -> linux:156 (KEY_BOOKMARKS) -> xorgevdev:164 */\n  [0xe7] = 0xb5, /* qnum:231 -> linux:173 (KEY_REFRESH) -> xorgevdev:181 */\n  [0xe8] = 0x88, /* qnum:232 -> linux:128 (KEY_STOP) -> xorgevdev:136 */\n  [0xe9] = 0xa7, /* qnum:233 -> linux:159 (KEY_FORWARD) -> xorgevdev:167 */\n  [0xea] = 0xa6, /* qnum:234 -> linux:158 (KEY_BACK) -> xorgevdev:166 */\n  [0xeb] = 0xa5, /* qnum:235 -> linux:157 (KEY_COMPUTER) -> xorgevdev:165 */\n  [0xec] = 0xa3, /* qnum:236 -> linux:155 (KEY_MAIL) -> xorgevdev:163 */\n  [0xed] = 0xea, /* qnum:237 -> linux:226 (KEY_MEDIA) -> xorgevdev:234 */\n  [0xef] = 0x78, /* qnum:239 -> linux:112 (KEY_MACRO) -> xorgevdev:120 */\n  [0xf0] = 0xf3, /* qnum:240 -> linux:235 (KEY_DOCUMENTS) -> xorgevdev:243 */\n  [0xf1] = 0xf4, /* qnum:241 -> linux:236 (KEY_BATTERY) -> xorgevdev:244 */\n  [0xf2] = 0xf5, /* qnum:242 -> linux:237 (KEY_BLUETOOTH) -> xorgevdev:245 */\n  [0xf3] = 0xf6, /* qnum:243 -> linux:238 (KEY_WLAN) -> xorgevdev:246 */\n  [0xf4] = 0xf7, /* qnum:244 -> linux:239 (KEY_UWB) -> xorgevdev:247 */\n  [0xf5] = 0x92, /* qnum:245 -> linux:138 (KEY_HELP) -> xorgevdev:146 */\n  [0xf6] = 0xbb, /* qnum:246 -> linux:179 (KEY_KPLEFTPAREN) -> xorgevdev:187 */\n  [0xf7] = 0xc4, /* qnum:247 -> linux:188 (KEY_F18) -> xorgevdev:196 */\n  [0xf8] = 0x8d, /* qnum:248 -> linux:133 (KEY_COPY) -> xorgevdev:141 */\n  [0xf9] = 0xc8, /* qnum:249 -> linux:192 (KEY_F22) -> xorgevdev:200 */\n  [0xfb] = 0xbc, /* qnum:251 -> linux:180 (KEY_KPRIGHTPAREN) -> xorgevdev:188 */\n  [0xfd] = 0xaa, /* qnum:253 -> linux:162 (KEY_EJECTCLOSECD) -> xorgevdev:170 */\n};\nconst unsigned int code_map_qnum_to_xorgevdev_len = sizeof(code_map_qnum_to_xorgevdev)/sizeof(code_map_qnum_to_xorgevdev[0]);\n"
  },
  {
    "path": "unix/xserver/hw/vnc/qnum_to_xorgkbd.c",
    "content": "/*\n * This file is auto-generated from keymaps.csv\n * Database checksum sha256(527727ef96d7103a8d7725a6ed9738812660b5a3f4aec086dd7b587b1ba9fcca)\n * To re-generate, run:\n *   keymap-gen code-map --lang=stdc keymaps.csv qnum xorgkbd\n*/\nconst unsigned short code_map_qnum_to_xorgkbd[254] = {\n  [0x1] = 0x9, /* qnum:1 -> linux:1 (KEY_ESC) -> xorgkbd:9 */\n  [0x2] = 0xa, /* qnum:2 -> linux:2 (KEY_1) -> xorgkbd:10 */\n  [0x3] = 0xb, /* qnum:3 -> linux:3 (KEY_2) -> xorgkbd:11 */\n  [0x4] = 0xc, /* qnum:4 -> linux:4 (KEY_3) -> xorgkbd:12 */\n  [0x5] = 0xd, /* qnum:5 -> linux:5 (KEY_4) -> xorgkbd:13 */\n  [0x6] = 0xe, /* qnum:6 -> linux:6 (KEY_5) -> xorgkbd:14 */\n  [0x7] = 0xf, /* qnum:7 -> linux:7 (KEY_6) -> xorgkbd:15 */\n  [0x8] = 0x10, /* qnum:8 -> linux:8 (KEY_7) -> xorgkbd:16 */\n  [0x9] = 0x11, /* qnum:9 -> linux:9 (KEY_8) -> xorgkbd:17 */\n  [0xa] = 0x12, /* qnum:10 -> linux:10 (KEY_9) -> xorgkbd:18 */\n  [0xb] = 0x13, /* qnum:11 -> linux:11 (KEY_0) -> xorgkbd:19 */\n  [0xc] = 0x14, /* qnum:12 -> linux:12 (KEY_MINUS) -> xorgkbd:20 */\n  [0xd] = 0x15, /* qnum:13 -> linux:13 (KEY_EQUAL) -> xorgkbd:21 */\n  [0xe] = 0x16, /* qnum:14 -> linux:14 (KEY_BACKSPACE) -> xorgkbd:22 */\n  [0xf] = 0x17, /* qnum:15 -> linux:15 (KEY_TAB) -> xorgkbd:23 */\n  [0x10] = 0x18, /* qnum:16 -> linux:16 (KEY_Q) -> xorgkbd:24 */\n  [0x11] = 0x19, /* qnum:17 -> linux:17 (KEY_W) -> xorgkbd:25 */\n  [0x12] = 0x1a, /* qnum:18 -> linux:18 (KEY_E) -> xorgkbd:26 */\n  [0x13] = 0x1b, /* qnum:19 -> linux:19 (KEY_R) -> xorgkbd:27 */\n  [0x14] = 0x1c, /* qnum:20 -> linux:20 (KEY_T) -> xorgkbd:28 */\n  [0x15] = 0x1d, /* qnum:21 -> linux:21 (KEY_Y) -> xorgkbd:29 */\n  [0x16] = 0x1e, /* qnum:22 -> linux:22 (KEY_U) -> xorgkbd:30 */\n  [0x17] = 0x1f, /* qnum:23 -> linux:23 (KEY_I) -> xorgkbd:31 */\n  [0x18] = 0x20, /* qnum:24 -> linux:24 (KEY_O) -> xorgkbd:32 */\n  [0x19] = 0x21, /* qnum:25 -> linux:25 (KEY_P) -> xorgkbd:33 */\n  [0x1a] = 0x22, /* qnum:26 -> linux:26 (KEY_LEFTBRACE) -> xorgkbd:34 */\n  [0x1b] = 0x23, /* qnum:27 -> linux:27 (KEY_RIGHTBRACE) -> xorgkbd:35 */\n  [0x1c] = 0x24, /* qnum:28 -> linux:28 (KEY_ENTER) -> xorgkbd:36 */\n  [0x1d] = 0x25, /* qnum:29 -> linux:29 (KEY_LEFTCTRL) -> xorgkbd:37 */\n  [0x1e] = 0x26, /* qnum:30 -> linux:30 (KEY_A) -> xorgkbd:38 */\n  [0x1f] = 0x27, /* qnum:31 -> linux:31 (KEY_S) -> xorgkbd:39 */\n  [0x20] = 0x28, /* qnum:32 -> linux:32 (KEY_D) -> xorgkbd:40 */\n  [0x21] = 0x29, /* qnum:33 -> linux:33 (KEY_F) -> xorgkbd:41 */\n  [0x22] = 0x2a, /* qnum:34 -> linux:34 (KEY_G) -> xorgkbd:42 */\n  [0x23] = 0x2b, /* qnum:35 -> linux:35 (KEY_H) -> xorgkbd:43 */\n  [0x24] = 0x2c, /* qnum:36 -> linux:36 (KEY_J) -> xorgkbd:44 */\n  [0x25] = 0x2d, /* qnum:37 -> linux:37 (KEY_K) -> xorgkbd:45 */\n  [0x26] = 0x2e, /* qnum:38 -> linux:38 (KEY_L) -> xorgkbd:46 */\n  [0x27] = 0x2f, /* qnum:39 -> linux:39 (KEY_SEMICOLON) -> xorgkbd:47 */\n  [0x28] = 0x30, /* qnum:40 -> linux:40 (KEY_APOSTROPHE) -> xorgkbd:48 */\n  [0x29] = 0x31, /* qnum:41 -> linux:41 (KEY_GRAVE) -> xorgkbd:49 */\n  [0x2a] = 0x32, /* qnum:42 -> linux:42 (KEY_LEFTSHIFT) -> xorgkbd:50 */\n  [0x2b] = 0x33, /* qnum:43 -> linux:43 (KEY_BACKSLASH) -> xorgkbd:51 */\n  [0x2c] = 0x34, /* qnum:44 -> linux:44 (KEY_Z) -> xorgkbd:52 */\n  [0x2d] = 0x35, /* qnum:45 -> linux:45 (KEY_X) -> xorgkbd:53 */\n  [0x2e] = 0x36, /* qnum:46 -> linux:46 (KEY_C) -> xorgkbd:54 */\n  [0x2f] = 0x37, /* qnum:47 -> linux:47 (KEY_V) -> xorgkbd:55 */\n  [0x30] = 0x38, /* qnum:48 -> linux:48 (KEY_B) -> xorgkbd:56 */\n  [0x31] = 0x39, /* qnum:49 -> linux:49 (KEY_N) -> xorgkbd:57 */\n  [0x32] = 0x3a, /* qnum:50 -> linux:50 (KEY_M) -> xorgkbd:58 */\n  [0x33] = 0x3b, /* qnum:51 -> linux:51 (KEY_COMMA) -> xorgkbd:59 */\n  [0x34] = 0x3c, /* qnum:52 -> linux:52 (KEY_DOT) -> xorgkbd:60 */\n  [0x35] = 0x3d, /* qnum:53 -> linux:53 (KEY_SLASH) -> xorgkbd:61 */\n  [0x36] = 0x3e, /* qnum:54 -> linux:54 (KEY_RIGHTSHIFT) -> xorgkbd:62 */\n  [0x37] = 0x3f, /* qnum:55 -> linux:55 (KEY_KPASTERISK) -> xorgkbd:63 */\n  [0x38] = 0x40, /* qnum:56 -> linux:56 (KEY_LEFTALT) -> xorgkbd:64 */\n  [0x39] = 0x41, /* qnum:57 -> linux:57 (KEY_SPACE) -> xorgkbd:65 */\n  [0x3a] = 0x42, /* qnum:58 -> linux:58 (KEY_CAPSLOCK) -> xorgkbd:66 */\n  [0x3b] = 0x43, /* qnum:59 -> linux:59 (KEY_F1) -> xorgkbd:67 */\n  [0x3c] = 0x44, /* qnum:60 -> linux:60 (KEY_F2) -> xorgkbd:68 */\n  [0x3d] = 0x45, /* qnum:61 -> linux:61 (KEY_F3) -> xorgkbd:69 */\n  [0x3e] = 0x46, /* qnum:62 -> linux:62 (KEY_F4) -> xorgkbd:70 */\n  [0x3f] = 0x47, /* qnum:63 -> linux:63 (KEY_F5) -> xorgkbd:71 */\n  [0x40] = 0x48, /* qnum:64 -> linux:64 (KEY_F6) -> xorgkbd:72 */\n  [0x41] = 0x49, /* qnum:65 -> linux:65 (KEY_F7) -> xorgkbd:73 */\n  [0x42] = 0x4a, /* qnum:66 -> linux:66 (KEY_F8) -> xorgkbd:74 */\n  [0x43] = 0x4b, /* qnum:67 -> linux:67 (KEY_F9) -> xorgkbd:75 */\n  [0x44] = 0x4c, /* qnum:68 -> linux:68 (KEY_F10) -> xorgkbd:76 */\n  [0x45] = 0x4d, /* qnum:69 -> linux:69 (KEY_NUMLOCK) -> xorgkbd:77 */\n  [0x46] = 0x4e, /* qnum:70 -> linux:70 (KEY_SCROLLLOCK) -> xorgkbd:78 */\n  [0x47] = 0x4f, /* qnum:71 -> linux:71 (KEY_KP7) -> xorgkbd:79 */\n  [0x48] = 0x50, /* qnum:72 -> linux:72 (KEY_KP8) -> xorgkbd:80 */\n  [0x49] = 0x51, /* qnum:73 -> linux:73 (KEY_KP9) -> xorgkbd:81 */\n  [0x4a] = 0x52, /* qnum:74 -> linux:74 (KEY_KPMINUS) -> xorgkbd:82 */\n  [0x4b] = 0x53, /* qnum:75 -> linux:75 (KEY_KP4) -> xorgkbd:83 */\n  [0x4c] = 0x54, /* qnum:76 -> linux:76 (KEY_KP5) -> xorgkbd:84 */\n  [0x4d] = 0x55, /* qnum:77 -> linux:77 (KEY_KP6) -> xorgkbd:85 */\n  [0x4e] = 0x56, /* qnum:78 -> linux:78 (KEY_KPPLUS) -> xorgkbd:86 */\n  [0x4f] = 0x57, /* qnum:79 -> linux:79 (KEY_KP1) -> xorgkbd:87 */\n  [0x50] = 0x58, /* qnum:80 -> linux:80 (KEY_KP2) -> xorgkbd:88 */\n  [0x51] = 0x59, /* qnum:81 -> linux:81 (KEY_KP3) -> xorgkbd:89 */\n  [0x52] = 0x5a, /* qnum:82 -> linux:82 (KEY_KP0) -> xorgkbd:90 */\n  [0x53] = 0x5b, /* qnum:83 -> linux:83 (KEY_KPDOT) -> xorgkbd:91 */\n  [0x54] = 0x6f, /* qnum:84 -> linux:99 (KEY_SYSRQ) -> xorgkbd:111 */\n  [0x55] = 0x79, /* qnum:85 -> linux:186 (KEY_F16) -> xorgkbd:121 */\n  [0x56] = 0x5e, /* qnum:86 -> linux:86 (KEY_102ND) -> xorgkbd:94 */\n  [0x57] = 0x5f, /* qnum:87 -> linux:87 (KEY_F11) -> xorgkbd:95 */\n  [0x58] = 0x60, /* qnum:88 -> linux:88 (KEY_F12) -> xorgkbd:96 */\n  [0x59] = 0x7e, /* qnum:89 -> linux:117 (KEY_KPEQUAL) -> xorgkbd:126 */\n  [0x5d] = 0x76, /* qnum:93 -> linux:183 (KEY_F13) -> xorgkbd:118 */\n  [0x5e] = 0x77, /* qnum:94 -> linux:184 (KEY_F14) -> xorgkbd:119 */\n  [0x5f] = 0x78, /* qnum:95 -> linux:185 (KEY_F15) -> xorgkbd:120 */\n  [0x70] = 0x78, /* qnum:112 -> linux:93 (KEY_KATAKANAHIRAGANA) -> xorgkbd:120 */\n  [0x71] = 0x79, /* qnum:113 -> linux:123 (KEY_HANJA) -> xorgkbd:121 */\n  [0x72] = 0x7a, /* qnum:114 -> linux:122 (KEY_HANGEUL) -> xorgkbd:122 */\n  [0x73] = 0x7b, /* qnum:115 -> linux:89 (KEY_RO) -> xorgkbd:123 */\n  [0x79] = 0x81, /* qnum:121 -> linux:92 (KEY_HENKAN) -> xorgkbd:129 */\n  [0x7b] = 0x83, /* qnum:123 -> linux:94 (KEY_MUHENKAN) -> xorgkbd:131 */\n  [0x7d] = 0x85, /* qnum:125 -> linux:124 (KEY_YEN) -> xorgkbd:133 */\n  [0x83] = 0x7a, /* qnum:131 -> linux:187 (KEY_F17) -> xorgkbd:122 */\n  [0x9c] = 0x6c, /* qnum:156 -> linux:96 (KEY_KPENTER) -> xorgkbd:108 */\n  [0x9d] = 0x6d, /* qnum:157 -> linux:97 (KEY_RIGHTCTRL) -> xorgkbd:109 */\n  [0xb5] = 0x70, /* qnum:181 -> linux:98 (KEY_KPSLASH) -> xorgkbd:112 */\n  [0xb7] = 0x6f, /* qnum:183 -> linux:99 (KEY_SYSRQ) -> xorgkbd:111 */\n  [0xb8] = 0x71, /* qnum:184 -> linux:100 (KEY_RIGHTALT) -> xorgkbd:113 */\n  [0xc6] = 0x6e, /* qnum:198 -> linux:119 (KEY_PAUSE) -> xorgkbd:110 */\n  [0xc7] = 0x61, /* qnum:199 -> linux:102 (KEY_HOME) -> xorgkbd:97 */\n  [0xc8] = 0x62, /* qnum:200 -> linux:103 (KEY_UP) -> xorgkbd:98 */\n  [0xc9] = 0x63, /* qnum:201 -> linux:104 (KEY_PAGEUP) -> xorgkbd:99 */\n  [0xcb] = 0x64, /* qnum:203 -> linux:105 (KEY_LEFT) -> xorgkbd:100 */\n  [0xcd] = 0x66, /* qnum:205 -> linux:106 (KEY_RIGHT) -> xorgkbd:102 */\n  [0xcf] = 0x67, /* qnum:207 -> linux:107 (KEY_END) -> xorgkbd:103 */\n  [0xd0] = 0x68, /* qnum:208 -> linux:108 (KEY_DOWN) -> xorgkbd:104 */\n  [0xd1] = 0x69, /* qnum:209 -> linux:109 (KEY_PAGEDOWN) -> xorgkbd:105 */\n  [0xd2] = 0x6a, /* qnum:210 -> linux:110 (KEY_INSERT) -> xorgkbd:106 */\n  [0xd3] = 0x6b, /* qnum:211 -> linux:111 (KEY_DELETE) -> xorgkbd:107 */\n  [0xdb] = 0x73, /* qnum:219 -> linux:125 (KEY_LEFTMETA) -> xorgkbd:115 */\n  [0xdc] = 0x74, /* qnum:220 -> linux:126 (KEY_RIGHTMETA) -> xorgkbd:116 */\n  [0xdd] = 0x75, /* qnum:221 -> linux:127 (KEY_COMPOSE) -> xorgkbd:117 */\n};\nconst unsigned int code_map_qnum_to_xorgkbd_len = sizeof(code_map_qnum_to_xorgkbd)/sizeof(code_map_qnum_to_xorgkbd[0]);\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncBlockHandler.c",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include <errno.h>\n\n#include <X11/Xpoll.h>\n\n#include \"os.h\"\n#include \"dix.h\"\n#include \"scrnintstr.h\"\n\n#include \"vncExtInit.h\"\n#include \"vncBlockHandler.h\"\n#include \"xorg-version.h\"\n\nstatic void vncBlockHandler(void* data, void* timeout);\nstatic void vncSocketNotify(int fd, int xevents, void *data);\n\nvoid vncRegisterBlockHandlers(void)\n{\n  if (!RegisterBlockAndWakeupHandlers(vncBlockHandler,\n                                      (ServerWakeupHandlerProcPtr)NoopDDA,\n                                      0))\n    FatalError(\"RegisterBlockAndWakeupHandlers() failed\\n\");\n}\n\nvoid vncSetNotifyFd(int fd, int scrIdx, int read, int write)\n{\n  int mask = (read ? X_NOTIFY_READ : 0) | (write ? X_NOTIFY_WRITE : 0);\n  SetNotifyFd(fd, vncSocketNotify, mask, (void*)(intptr_t)scrIdx);\n}\n\nvoid vncRemoveNotifyFd(int fd)\n{\n  RemoveNotifyFd(fd);\n}\n\nstatic void vncSocketNotify(int fd, int xevents, void *data)\n{\n  int scrIdx;\n\n  scrIdx = (intptr_t)data;\n  vncHandleSocketEvent(fd, scrIdx,\n                       xevents & X_NOTIFY_READ,\n                       xevents & X_NOTIFY_WRITE);\n}\n\n//\n// vncBlockHandler - called just before the X server goes into poll().\n//\n\nstatic void vncBlockHandler(void* data, void* timeout)\n{\n  vncCallBlockHandlers(timeout);\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncBlockHandler.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef VNCBLOCKHANDLER_H\n#define VNCBLOCKHANDLER_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid vncRegisterBlockHandlers(void);\n\nvoid vncSetNotifyFd(int fd, int scrIdx, int read, int write);\nvoid vncRemoveNotifyFd(int fd);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncDRI3.c",
    "content": "/* Copyright 2024 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include <errno.h>\n#include <fcntl.h>\n#include <glob.h>\n#include <unistd.h>\n\n#ifdef HAVE_GBM\n#include <gbm.h>\n#endif\n\n#include \"vncDRI3.h\"\n#include <dri3.h>\n#include <fb.h>\n#include <misyncshm.h>\n\n#ifdef FB_ACCESS_WRAPPER\n#error \"This code is not compatible with accessors\"\n#endif\n\nconst char *renderNode = \"auto\";\n\nstatic DevPrivateKeyRec vncDRI3ScreenPrivateKey;\nstatic DevPrivateKeyRec vncDRI3PixmapPrivateKey;\n\ntypedef struct vncDRI3ScreenPrivate {\n  CloseScreenProcPtr CloseScreen;\n\n  DestroyPixmapProcPtr DestroyPixmap;\n\n#ifdef HAVE_GBM\n  const char *devicePath;\n  struct gbm_device *device;\n  int fd;\n#endif\n} vncDRI3ScreenPrivateRec, *vncDRI3ScreenPrivatePtr;\n\ntypedef struct vncDRI3PixmapPrivate {\n#ifdef HAVE_GBM\n  struct gbm_bo *bo;\n#endif\n} vncDRI3PixmapPrivateRec, *vncDRI3PixmapPrivatePtr;\n\n#define wrap(priv, real, mem, func) {\\\n  priv->mem = real->mem; \\\n  real->mem = func; \\\n}\n\n#define unwrap(priv, real, mem) {\\\n  real->mem = priv->mem; \\\n}\n\nstatic inline vncDRI3ScreenPrivatePtr vncDRI3ScreenPrivate(ScreenPtr screen)\n{\n  return (vncDRI3ScreenPrivatePtr)dixLookupPrivate(&(screen)->devPrivates, &vncDRI3ScreenPrivateKey);\n}\n\nstatic inline vncDRI3PixmapPrivatePtr vncDRI3PixmapPrivate(PixmapPtr pixmap)\n{\n  return (vncDRI3PixmapPrivatePtr)dixLookupPrivate(&(pixmap)->devPrivates, &vncDRI3PixmapPrivateKey);\n}\n\nstatic int vncDRI3Open(ScreenPtr screen, RRProviderPtr provider,\n                       int *fd)\n{\n#ifdef HAVE_GBM\n  vncDRI3ScreenPrivatePtr screenPriv = vncDRI3ScreenPrivate(screen);\n\n  *fd = open(screenPriv->devicePath, O_RDWR|O_CLOEXEC);\n  if (*fd < 0)\n    return BadAlloc;\n\n  return Success;\n#else\n  return BadAlloc;\n#endif\n}\n\n/* Taken from glamor */\n#ifdef HAVE_GBM\nstatic uint32_t gbm_format_for_depth(CARD8 depth)\n{\n  switch (depth) {\n  case 16:\n    return GBM_FORMAT_RGB565;\n  case 24:\n    return GBM_FORMAT_XRGB8888;\n  case 30:\n    return GBM_FORMAT_ARGB2101010;\n  default:\n    ErrorF(\"unexpected depth: %d\\n\", depth);\n  case 32:\n    return GBM_FORMAT_ARGB8888;\n  }\n}\n#endif\n\nstatic PixmapPtr vncPixmapFromFd(ScreenPtr screen, int fd,\n                                 CARD16 width, CARD16 height,\n                                 CARD16 stride, CARD8 depth,\n                                 CARD8 bpp)\n{\n#ifdef HAVE_GBM\n  vncDRI3ScreenPrivatePtr screenPriv = vncDRI3ScreenPrivate(screen);\n  vncDRI3PixmapPrivatePtr pixmapPriv;\n\n  struct gbm_import_fd_data data;\n  struct gbm_bo *bo;\n  PixmapPtr pixmap;\n\n  if (bpp != sizeof(FbBits)*8) {\n    ErrorF(\"Incompatible bits per pixel given for GPU buffer\\n\");\n    return NULL;\n  }\n\n  if ((stride % sizeof(FbBits)) != 0) {\n    ErrorF(\"Incompatible stride given for GPU buffer\\n\");\n    return NULL;\n  }\n\n  data.fd = fd;\n  data.width = width;\n  data.height = height;\n  data.stride = stride;\n  data.format = gbm_format_for_depth(depth);\n\n  bo = gbm_bo_import(screenPriv->device, GBM_BO_IMPORT_FD, &data,\n                     GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR);\n  if (bo == NULL)\n    return NULL;\n\n  pixmap = screen->CreatePixmap(screen, width, height, depth, 0);\n\n  pixmapPriv = vncDRI3PixmapPrivate(pixmap);\n  pixmapPriv->bo = bo;\n\n  vncDRI3SyncPixmapFromGPU(pixmap);\n\n  return pixmap;\n#else\n  return NULL;\n#endif\n}\n\nstatic Bool vncDRI3DestroyPixmap(PixmapPtr pixmap)\n{\n  ScreenPtr screen = pixmap->drawable.pScreen;\n  vncDRI3ScreenPrivatePtr screenPriv = vncDRI3ScreenPrivate(screen);\n  Bool ret;\n\n#ifdef HAVE_GBM\n  if (pixmap->refcnt == 1) {\n    vncDRI3PixmapPrivatePtr pixmapPriv = vncDRI3PixmapPrivate(pixmap);\n\n    if (pixmapPriv->bo != NULL) {\n      gbm_bo_destroy(pixmapPriv->bo);\n      pixmapPriv->bo = NULL;\n    }\n  }\n#endif\n\n  unwrap(screenPriv, screen, DestroyPixmap);\n  ret = screen->DestroyPixmap(pixmap);\n  wrap(screenPriv, screen, DestroyPixmap, vncDRI3DestroyPixmap);\n\n  return ret;\n}\n\n#ifdef HAVE_GBM\nstatic int vncDRI3FdFromPixmapVisitWindow(WindowPtr window, void *data)\n{\n  ScreenPtr screen = window->drawable.pScreen;\n  PixmapPtr pixmap = data;\n\n  if ((*screen->GetWindowPixmap)(window) == pixmap)\n    window->drawable.serialNumber = NEXT_SERIAL_NUMBER;\n\n  return WT_WALKCHILDREN;\n}\n#endif\n\nstatic int vncFdFromPixmap(ScreenPtr screen, PixmapPtr pixmap,\n                           CARD16 *stride, CARD32 *size)\n{\n#ifdef HAVE_GBM\n  vncDRI3ScreenPrivatePtr screenPriv = vncDRI3ScreenPrivate(screen);\n  vncDRI3PixmapPrivatePtr pixmapPriv = vncDRI3PixmapPrivate(pixmap);\n\n  if (pixmap->drawable.bitsPerPixel != sizeof(FbBits)*8) {\n    ErrorF(\"Incompatible bits per pixel given for pixmap\\n\");\n    return -1;\n  }\n\n  if (pixmapPriv->bo == NULL) {\n    /* GBM_BO_USE_LINEAR ? */\n    pixmapPriv->bo = gbm_bo_create(screenPriv->device,\n                                   pixmap->drawable.width,\n                                   pixmap->drawable.height,\n                                   gbm_format_for_depth(pixmap->drawable.depth),\n                                   GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR);\n    if (pixmapPriv->bo == NULL) {\n      ErrorF(\"Failed to create GPU buffer: %s\\n\", strerror(errno));\n      return -1;\n    }\n\n    if ((gbm_bo_get_stride(pixmapPriv->bo) % sizeof(FbBits)) != 0) {\n      ErrorF(\"Incompatible stride for created GPU buffer\\n\");\n      gbm_bo_destroy(pixmapPriv->bo);\n      pixmapPriv->bo = NULL;\n      return -1;\n    }\n\n    /* Force re-validation of any gc:s */\n    pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;\n    WalkTree(screen, vncDRI3FdFromPixmapVisitWindow, pixmap);\n  }\n\n  vncDRI3SyncPixmapToGPU(pixmap);\n\n  *stride = gbm_bo_get_stride(pixmapPriv->bo);\n  /* FIXME */\n  *size = *stride * gbm_bo_get_height(pixmapPriv->bo);\n\n  return gbm_bo_get_fd(pixmapPriv->bo);\n#else\n  return -1;\n#endif\n}\n\nBool vncDRI3IsHardwarePixmap(PixmapPtr pixmap)\n{\n#ifdef HAVE_GBM\n  vncDRI3PixmapPrivatePtr pixmapPriv = vncDRI3PixmapPrivate(pixmap);\n  return pixmapPriv->bo != NULL;\n#else\n  return FALSE;\n#endif\n}\n\nBool vncDRI3IsHardwareDrawable(DrawablePtr drawable)\n{\n  PixmapPtr pixmap;\n  int xoff, yoff;\n\n  fbGetDrawablePixmap(drawable, pixmap, xoff, yoff);\n  (void)xoff;\n  (void)yoff;\n\n  return vncDRI3IsHardwarePixmap(pixmap);\n}\n\nBool vncDRI3SyncPixmapToGPU(PixmapPtr pixmap)\n{\n#ifdef HAVE_GBM\n  vncDRI3PixmapPrivatePtr pixmapPriv = vncDRI3PixmapPrivate(pixmap);\n\n  int width, height;\n\n  FbBits *bo_data;\n  uint32_t bo_stride;\n  void *map_data;\n  uint32_t bo_bpp;\n\n  FbBits *pixmap_data;\n  int pixmap_stride;\n  int pixmap_bpp;\n\n  pixman_bool_t ret;\n\n  if (pixmapPriv->bo == NULL)\n    return TRUE;\n\n  width = gbm_bo_get_width(pixmapPriv->bo);\n  height = gbm_bo_get_height(pixmapPriv->bo);\n\n  map_data = NULL;\n  bo_data = gbm_bo_map(pixmapPriv->bo, 0, 0, width, height,\n                       GBM_BO_TRANSFER_WRITE, &bo_stride, &map_data);\n  if (bo_data == NULL) {\n    ErrorF(\"Could not map GPU buffer: %s\\n\", strerror(errno));\n    return FALSE;\n  }\n\n  bo_bpp = gbm_bo_get_bpp(pixmapPriv->bo);\n  assert(bo_bpp == sizeof(FbBits)*8);\n  assert((bo_stride % (bo_bpp/8)) == 0);\n\n  fbGetPixmapBitsData(pixmap, pixmap_data,\n                      pixmap_stride, pixmap_bpp);\n  assert(pixmap_data != NULL);\n  assert(pixmap_bpp == sizeof(FbBits)*8);\n\n  assert(bo_bpp == pixmap_bpp);\n\n  /* Try accelerated copy first */\n  ret = pixman_blt((uint32_t*)pixmap_data, (uint32_t*)bo_data,\n                   pixmap_stride, bo_stride / (bo_bpp/8),\n                   pixmap_bpp, bo_bpp, 0, 0, 0, 0, width, height);\n  if (!ret) {\n    /* Fall back to slow pure C version */\n    fbBlt(pixmap_data, pixmap_stride, 0,\n          bo_data, bo_stride / (bo_bpp/8), 0,\n          width * bo_bpp, height,\n          GXcopy, FB_ALLONES, bo_bpp, FALSE, FALSE);\n  }\n\n  gbm_bo_unmap(pixmapPriv->bo, map_data);\n#endif\n\n  return TRUE;\n}\n\nBool vncDRI3SyncPixmapFromGPU(PixmapPtr pixmap)\n{\n#ifdef HAVE_GBM\n  vncDRI3PixmapPrivatePtr pixmapPriv = vncDRI3PixmapPrivate(pixmap);\n\n  int width, height;\n\n  FbBits *bo_data;\n  uint32_t bo_stride;\n  void *map_data;\n  uint32_t bo_bpp;\n\n  FbBits *pixmap_data;\n  int pixmap_stride;\n  int pixmap_bpp;\n\n  pixman_bool_t ret;\n\n  if (pixmapPriv->bo == NULL)\n    return TRUE;\n\n  width = gbm_bo_get_width(pixmapPriv->bo);\n  height = gbm_bo_get_height(pixmapPriv->bo);\n\n  map_data = NULL;\n  bo_data = gbm_bo_map(pixmapPriv->bo, 0, 0, width, height,\n                       GBM_BO_TRANSFER_READ, &bo_stride, &map_data);\n  if (bo_data == NULL) {\n    ErrorF(\"Could not map GPU buffer: %s\\n\", strerror(errno));\n    return FALSE;\n  }\n\n  bo_bpp = gbm_bo_get_bpp(pixmapPriv->bo);\n  assert(bo_bpp == sizeof(FbBits)*8);\n  assert((bo_stride % (bo_bpp/8)) == 0);\n\n  fbGetPixmapBitsData(pixmap, pixmap_data,\n                      pixmap_stride, pixmap_bpp);\n  assert(pixmap_data != NULL);\n  assert(pixmap_bpp == sizeof(FbBits)*8);\n\n  assert(bo_bpp == pixmap_bpp);\n\n  /* Try accelerated copy first */\n  ret = pixman_blt((uint32_t*)bo_data, (uint32_t*)pixmap_data,\n                   bo_stride / (bo_bpp/8), pixmap_stride,\n                   bo_bpp, pixmap_bpp, 0, 0, 0, 0, width, height);\n  if (!ret) {\n    /* Fall back to slow pure C version */\n    fbBlt(bo_data, bo_stride / (bo_bpp/8), 0,\n          pixmap_data, pixmap_stride, 0,\n          width * bo_bpp, height,\n          GXcopy, FB_ALLONES, bo_bpp, FALSE, FALSE);\n  }\n\n  gbm_bo_unmap(pixmapPriv->bo, map_data);\n#endif\n\n  return TRUE;\n}\n\nBool vncDRI3SyncDrawableToGPU(DrawablePtr drawable)\n{\n  PixmapPtr pixmap;\n  int xoff, yoff;\n\n  fbGetDrawablePixmap(drawable, pixmap, xoff, yoff);\n  (void)xoff;\n  (void)yoff;\n\n  return vncDRI3SyncPixmapToGPU(pixmap);\n}\n\nBool vncDRI3SyncDrawableFromGPU(DrawablePtr drawable)\n{\n  PixmapPtr pixmap;\n  int xoff, yoff;\n\n  fbGetDrawablePixmap(drawable, pixmap, xoff, yoff);\n  (void)xoff;\n  (void)yoff;\n\n  return vncDRI3SyncPixmapFromGPU(pixmap);\n}\n\nstatic const dri3_screen_info_rec vncDRI3ScreenInfo = {\n  .version = 1,\n\n  .open = vncDRI3Open,\n  .pixmap_from_fd = vncPixmapFromFd,\n  .fd_from_pixmap = vncFdFromPixmap,\n};\n\nstatic Bool vncDRI3CloseScreen(ScreenPtr screen)\n{\n  vncDRI3ScreenPrivatePtr screenPriv = vncDRI3ScreenPrivate(screen);\n\n  unwrap(screenPriv, screen, CloseScreen);\n\n  unwrap(screenPriv, screen, DestroyPixmap);\n\n#ifdef HAVE_GBM\n  gbm_device_destroy(screenPriv->device);\n  screenPriv->device = NULL;\n\n  close(screenPriv->fd);\n  screenPriv->fd = -1;\n#endif\n\n  return (*screen->CloseScreen)(screen);\n}\n\nBool vncDRI3Init(ScreenPtr screen)\n{\n  vncDRI3ScreenPrivatePtr screenPriv;\n\n  /*\n   * We don't queue any gbm operations, so we don't have to do anything\n   * more than simply activate this extension.\n   */\n#ifdef HAVE_XSHMFENCE\n  if (!miSyncShmScreenInit(screen))\n    return FALSE;\n#endif\n\n  /* Empty render node is interpreted as disabling DRI3 */\n  if (renderNode[0] == '\\0')\n    return TRUE;\n\n  if ((renderNode[0] != '/') &&\n      (strcasecmp(renderNode, \"auto\") != 0)) {\n    ErrorF(\"Invalid render node path \\\"%s\\\"\\n\", renderNode);\n    return FALSE;\n  }\n\n  if (!dixRegisterPrivateKey(&vncDRI3ScreenPrivateKey, PRIVATE_SCREEN,\n                             sizeof(vncDRI3ScreenPrivateRec)))\n    return FALSE;\n  if (!dixRegisterPrivateKey(&vncDRI3PixmapPrivateKey, PRIVATE_PIXMAP,\n                             sizeof(vncDRI3PixmapPrivateRec)))\n    return FALSE;\n\n  if (!vncDRI3DrawInit(screen))\n    return FALSE;\n\n#ifdef HAVE_GBM\n  screenPriv = vncDRI3ScreenPrivate(screen);\n\n  if (strcasecmp(renderNode, \"auto\") == 0) {\n    glob_t globbuf;\n    int ret;\n\n    ret = glob(\"/dev/dri/renderD*\", 0, NULL, &globbuf);\n    if (ret == GLOB_NOMATCH) {\n      ErrorF(\"Could not find any render nodes\\n\");\n      return FALSE;\n    }\n    if (ret != 0) {\n      ErrorF(\"Failure enumerating render nodes\\n\");\n      return FALSE;\n    }\n\n    screenPriv->devicePath = NULL;\n    for (size_t i = 0;i < globbuf.gl_pathc;i++) {\n      if (access(globbuf.gl_pathv[i], R_OK|W_OK) == 0) {\n        screenPriv->devicePath = strdup(globbuf.gl_pathv[i]);\n        break;\n      }\n    }\n\n    globfree(&globbuf);\n\n    if (screenPriv->devicePath == NULL) {\n      ErrorF(\"Could not find any available render nodes\\n\");\n      return FALSE;\n    }\n  } else {\n    screenPriv->devicePath = renderNode;\n  }\n\n  screenPriv->fd = open(screenPriv->devicePath, O_RDWR|O_CLOEXEC);\n  if (screenPriv->fd < 0) {\n    ErrorF(\"Failed to open \\\"%s\\\": %s\\n\",\n           screenPriv->devicePath, strerror(errno));\n    return FALSE;\n  }\n\n  screenPriv->device = gbm_create_device(screenPriv->fd);\n  if (screenPriv->device == NULL) {\n    close(screenPriv->fd);\n    screenPriv->fd = -1;\n    ErrorF(\"Could create GPU render device\\n\");\n    return FALSE;\n  }\n#else\n  ErrorF(\"Built without GBM support\\n\");\n  return FALSE;\n#endif\n\n  wrap(screenPriv, screen, CloseScreen, vncDRI3CloseScreen);\n\n  wrap(screenPriv, screen, DestroyPixmap, vncDRI3DestroyPixmap);\n\n  return dri3_screen_init(screen, &vncDRI3ScreenInfo);\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncDRI3.h",
    "content": "/* Copyright 2024 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __VNCDRI3_H__\n#define __VNCDRI3_H__\n\n#ifdef DRI3\n\n#include <dix.h>\n\nextern const char *renderNode;\n\nBool vncDRI3Init(ScreenPtr screen);\n\nBool vncDRI3IsHardwarePixmap(PixmapPtr pixmap);\nBool vncDRI3IsHardwareDrawable(DrawablePtr drawable);\n\nBool vncDRI3SyncPixmapToGPU(PixmapPtr pixmap);\nBool vncDRI3SyncPixmapFromGPU(PixmapPtr pixmap);\n\nBool vncDRI3SyncDrawableToGPU(DrawablePtr drawable);\nBool vncDRI3SyncDrawableFromGPU(DrawablePtr drawable);\n\nBool vncDRI3DrawInit(ScreenPtr screen);\n\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncDRI3Draw.c",
    "content": "/* Copyright 2024 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include \"vncDRI3.h\"\n\n#include <fb.h>\n#include <gcstruct.h>\n#include <pixmapstr.h>\n\nstatic DevPrivateKeyRec vncDRI3DrawScreenPrivateKey;\nstatic DevPrivateKeyRec vncDRI3GCPrivateKey;\n\ntypedef struct vncDRI3DrawScreenPrivateRec {\n  CloseScreenProcPtr CloseScreen;\n\n  CreateGCProcPtr CreateGC;\n  SourceValidateProcPtr SourceValidate;\n\n  CompositeProcPtr Composite;\n  GlyphsProcPtr Glyphs;\n  CompositeRectsProcPtr CompositeRects;\n  TrapezoidsProcPtr Trapezoids;\n  TrianglesProcPtr Triangles;\n  TriStripProcPtr TriStrip;\n  TriFanProcPtr TriFan;\n} vncDRI3DrawScreenPrivateRec, *vncDRI3DrawScreenPrivatePtr;\n\ntypedef struct vncDRI3GCPrivateRec {\n  const GCFuncs *funcs;\n  const GCOps *ops;\n} vncDRI3GCPrivateRec, *vncDRI3GCPrivatePtr;\n\n#define wrap(priv, real, mem, func) {\\\n  priv->mem = real->mem; \\\n  real->mem = func; \\\n}\n\n#define unwrap(priv, real, mem) {\\\n  real->mem = priv->mem; \\\n}\n\nstatic inline vncDRI3DrawScreenPrivatePtr vncDRI3DrawScreenPrivate(ScreenPtr screen)\n{\n  return (vncDRI3DrawScreenPrivatePtr)dixLookupPrivate(&(screen)->devPrivates, &vncDRI3DrawScreenPrivateKey);\n}\n\nstatic inline vncDRI3GCPrivatePtr vncDRI3GCPrivate(GCPtr gc)\n{\n  return (vncDRI3GCPrivatePtr)dixLookupPrivate(&(gc)->devPrivates, &vncDRI3GCPrivateKey);\n}\n\nstatic GCFuncs vncDRI3GCFuncs;\nstatic GCOps vncDRI3GCOps;\n\n/* GC functions */\n\nstatic void vncDRI3ValidateGC(GCPtr gc, unsigned long changes,\n                              DrawablePtr drawable)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  unwrap(gcPriv, gc, funcs);\n  if (gcPriv->ops != NULL)\n    unwrap(gcPriv, gc, ops);\n\n  (*gc->funcs->ValidateGC)(gc, changes, drawable);\n\n  if (vncDRI3IsHardwareDrawable(drawable)) {\n    wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  } else {\n    gcPriv->ops = NULL;\n  }\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n}\n\nstatic void vncDRI3ChangeGC(GCPtr gc, unsigned long mask)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n  unwrap(gcPriv, gc, funcs);\n  if (gcPriv->ops != NULL)\n    unwrap(gcPriv, gc, ops);\n  (*gc->funcs->ChangeGC)(gc, mask);\n  if (gcPriv->ops != NULL)\n    wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n}\n\nstatic void vncDRI3CopyGC(GCPtr src, unsigned long mask, GCPtr dst)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(dst);\n  unwrap(gcPriv, dst, funcs);\n  if (gcPriv->ops != NULL)\n    unwrap(gcPriv, dst, ops);\n  (*dst->funcs->CopyGC)(src, mask, dst);\n  if (gcPriv->ops != NULL)\n    wrap(gcPriv, dst, ops, &vncDRI3GCOps);\n  wrap(gcPriv, dst, funcs, &vncDRI3GCFuncs);\n}\n\nstatic void vncDRI3DestroyGC(GCPtr gc)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n  unwrap(gcPriv, gc, funcs);\n  if (gcPriv->ops != NULL)\n    unwrap(gcPriv, gc, ops);\n  (*gc->funcs->DestroyGC)(gc);\n  if (gcPriv->ops != NULL)\n    wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n}\n\nstatic void vncDRI3ChangeClip(GCPtr gc, int type, void *value, int nrects)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n  unwrap(gcPriv, gc, funcs);\n  if (gcPriv->ops != NULL)\n    unwrap(gcPriv, gc, ops);\n  (*gc->funcs->ChangeClip)(gc, type, value, nrects);\n  if (gcPriv->ops != NULL)\n    wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n}\n\nstatic void vncDRI3DestroyClip(GCPtr gc)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n  unwrap(gcPriv, gc, funcs);\n  if (gcPriv->ops != NULL)\n    unwrap(gcPriv, gc, ops);\n  (*gc->funcs->DestroyClip)(gc);\n  if (gcPriv->ops != NULL)\n    wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n}\n\nstatic void vncDRI3CopyClip(GCPtr dst, GCPtr src)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(dst);\n  unwrap(gcPriv, dst, funcs);\n  if (gcPriv->ops != NULL)\n    unwrap(gcPriv, dst, ops);\n  (*dst->funcs->CopyClip)(dst, src);\n  if (gcPriv->ops != NULL)\n    wrap(gcPriv, dst, ops, &vncDRI3GCOps);\n  wrap(gcPriv, dst, funcs, &vncDRI3GCFuncs);\n}\n\n/* GC operations */\n\nstatic void vncDRI3FillSpans(DrawablePtr drawable, GCPtr gc, int nInit,\n                             DDXPointPtr pptInit, int *pwidthInit,\n                             int fSorted)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->FillSpans)(drawable, gc, nInit, pptInit, pwidthInit, fSorted);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3SetSpans(DrawablePtr drawable, GCPtr gc, char *psrc,\n                            DDXPointPtr ppt, int *pwidth, int nspans,\n                            int fSorted)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->SetSpans)(drawable, gc, psrc, ppt, pwidth, nspans, fSorted);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3PutImage(DrawablePtr drawable, GCPtr gc, int depth,\n                            int x, int y, int w, int h, int leftPad,\n                            int format, char *pBits)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->PutImage)(drawable, gc, depth, x, y, w, h, leftPad, format, pBits);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic RegionPtr vncDRI3CopyArea(DrawablePtr src, DrawablePtr dst,\n                                 GCPtr gc, int srcx, int srcy,\n                                 int w, int h, int dstx, int dsty)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n  RegionPtr ret;\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(dst);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  ret = (*gc->ops->CopyArea)(src, dst, gc, srcx, srcy, w, h, dstx, dsty);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(dst);\n\n  return ret;\n}\n\nstatic RegionPtr vncDRI3CopyPlane(DrawablePtr src, DrawablePtr dst,\n                                  GCPtr gc, int srcx, int srcy,\n                                  int w, int h, int dstx, int dsty,\n                                  unsigned long plane)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n  RegionPtr ret;\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(dst);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  ret = (*gc->ops->CopyPlane)(src, dst, gc, srcx, srcy, w, h, dstx, dsty, plane);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(dst);\n\n  return ret;\n}\n\nstatic void vncDRI3PolyPoint(DrawablePtr drawable, GCPtr gc, int mode,\n                             int npt, xPoint *pts)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->PolyPoint)(drawable, gc, mode, npt, pts);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3Polylines(DrawablePtr drawable, GCPtr gc, int mode,\n                             int npt, DDXPointPtr ppts)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->Polylines)(drawable, gc, mode, npt, ppts);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3PolySegment(DrawablePtr drawable, GCPtr gc, int nseg,\n                               xSegment *segs)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->PolySegment)(drawable, gc, nseg, segs);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3PolyRectangle(DrawablePtr drawable, GCPtr gc,\n                                 int nrects, xRectangle *rects)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->PolyRectangle)(drawable, gc, nrects, rects);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3PolyArc(DrawablePtr drawable, GCPtr gc, int narcs,\n                           xArc *arcs)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->PolyArc)(drawable, gc, narcs, arcs);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3FillPolygon(DrawablePtr drawable, GCPtr gc,\n                               int shape, int mode, int count,\n                               DDXPointPtr pts)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->FillPolygon)(drawable, gc, shape, mode, count, pts);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3PolyFillRect(DrawablePtr drawable, GCPtr gc,\n                                int nrects, xRectangle *rects)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->PolyFillRect)(drawable, gc, nrects, rects);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3PolyFillArc(DrawablePtr drawable, GCPtr gc,\n                               int narcs, xArc *arcs)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->PolyFillArc)(drawable, gc, narcs, arcs);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic int vncDRI3PolyText8(DrawablePtr drawable, GCPtr gc,\n                            int x, int y, int count, char *chars)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n  int ret;\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  ret = (*gc->ops->PolyText8)(drawable, gc, x, y, count, chars);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n\n  return ret;\n}\n\nstatic int vncDRI3PolyText16(DrawablePtr drawable, GCPtr gc,\n                             int x, int y, int count,\n                             unsigned short *chars)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n  int ret;\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  ret = (*gc->ops->PolyText16)(drawable, gc, x, y, count, chars);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n\n  return ret;\n}\n\nstatic void vncDRI3ImageText8(DrawablePtr drawable, GCPtr gc,\n                              int x, int y, int count, char *chars)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->ImageText8)(drawable, gc, x, y, count, chars);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3ImageText16(DrawablePtr drawable, GCPtr gc,\n                               int x, int y, int count,\n                               unsigned short *chars)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->ImageText16)(drawable, gc, x, y, count, chars);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3ImageGlyphBlt(DrawablePtr drawable, GCPtr gc, int x,\n                                 int y, unsigned int nglyph,\n                                 CharInfoPtr *ppci, void * pglyphBase)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->ImageGlyphBlt)(drawable, gc, x, y, nglyph, ppci, pglyphBase);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3PolyGlyphBlt(DrawablePtr drawable, GCPtr gc, int x,\n                                int y, unsigned int nglyph,\n                                CharInfoPtr *ppci, void * pglyphBase)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->PolyGlyphBlt)(drawable, gc, x, y, nglyph, ppci, pglyphBase);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic void vncDRI3PushPixels(GCPtr gc, PixmapPtr pBitMap,\n                              DrawablePtr drawable,\n                              int w, int h, int x, int y)\n{\n  vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(gcPriv, gc, funcs);\n  unwrap(gcPriv, gc, ops);\n  (*gc->ops->PushPixels)(gc, pBitMap, drawable, w, h, x, y);\n  wrap(gcPriv, gc, ops, &vncDRI3GCOps);\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  vncDRI3SyncDrawableToGPU(drawable);\n}\n\nstatic GCFuncs vncDRI3GCFuncs = {\n  .ValidateGC = vncDRI3ValidateGC,\n  .ChangeGC = vncDRI3ChangeGC,\n  .CopyGC = vncDRI3CopyGC,\n  .DestroyGC = vncDRI3DestroyGC,\n  .ChangeClip = vncDRI3ChangeClip,\n  .DestroyClip = vncDRI3DestroyClip,\n  .CopyClip = vncDRI3CopyClip,\n};\n\nstatic GCOps vncDRI3GCOps = {\n  .FillSpans = vncDRI3FillSpans,\n  .SetSpans = vncDRI3SetSpans,\n  .PutImage = vncDRI3PutImage,\n  .CopyArea = vncDRI3CopyArea,\n  .CopyPlane = vncDRI3CopyPlane,\n  .PolyPoint = vncDRI3PolyPoint,\n  .Polylines = vncDRI3Polylines,\n  .PolySegment = vncDRI3PolySegment,\n  .PolyRectangle = vncDRI3PolyRectangle,\n  .PolyArc = vncDRI3PolyArc,\n  .FillPolygon = vncDRI3FillPolygon,\n  .PolyFillRect = vncDRI3PolyFillRect,\n  .PolyFillArc = vncDRI3PolyFillArc,\n  .PolyText8 = vncDRI3PolyText8,\n  .PolyText16 = vncDRI3PolyText16,\n  .ImageText8 = vncDRI3ImageText8,\n  .ImageText16 = vncDRI3ImageText16,\n  .ImageGlyphBlt = vncDRI3ImageGlyphBlt,\n  .PolyGlyphBlt = vncDRI3PolyGlyphBlt,\n  .PushPixels = vncDRI3PushPixels,\n};\n\nstatic Bool vncDRI3CreateGC(GCPtr gc)\n{\n  ScreenPtr screen = gc->pScreen;\n  vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);\n  vncDRI3GCPrivatePtr gcPriv;\n  Bool ret;\n\n  unwrap(screenPriv, screen, CreateGC);\n  ret = (*screen->CreateGC)(gc);\n  wrap(screenPriv, screen, CreateGC, vncDRI3CreateGC);\n\n  gcPriv = vncDRI3GCPrivate(gc);\n\n  wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);\n\n  return ret;\n}\n\nstatic void vncDRI3SourceValidate(DrawablePtr drawable,\n                                  int x, int y,\n                                  int width, int height,\n                                  unsigned int subWindowMode)\n{\n  ScreenPtr screen = drawable->pScreen;\n  vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);\n\n  /* FIXME: Compute what we need to sync */\n  vncDRI3SyncDrawableFromGPU(drawable);\n\n  unwrap(screenPriv, screen, SourceValidate);\n  screen->SourceValidate(drawable, x, y, width, height, subWindowMode);\n  wrap(screenPriv, screen, SourceValidate, vncDRI3SourceValidate);\n}\n\nstatic void vncDRI3Composite(CARD8 op, PicturePtr pSrc,\n                             PicturePtr pMask, PicturePtr pDst,\n                             INT16 xSrc, INT16 ySrc, INT16 xMask,\n                             INT16 yMask, INT16 xDst, INT16 yDst,\n                             CARD16 width, CARD16 height)\n{\n  ScreenPtr screen = pDst->pDrawable->pScreen;\n  PictureScreenPtr ps = GetPictureScreen(screen);\n  vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);\n\n  vncDRI3SyncDrawableFromGPU(pDst->pDrawable);\n\n  unwrap(screenPriv, ps, Composite);\n  (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,\n                   xMask, yMask, xDst, yDst, width, height);\n  wrap(screenPriv, ps, Composite, vncDRI3Composite);\n\n  vncDRI3SyncDrawableToGPU(pDst->pDrawable);\n}\n\nstatic void vncDRI3Glyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n                          PictFormatPtr maskFormat,\n                          INT16 xSrc, INT16 ySrc, int nlists,\n                          GlyphListPtr lists, GlyphPtr * glyphs)\n{\n  ScreenPtr screen = pDst->pDrawable->pScreen;\n  PictureScreenPtr ps = GetPictureScreen(screen);\n  vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);\n\n  vncDRI3SyncDrawableFromGPU(pDst->pDrawable);\n\n  unwrap(screenPriv, ps, Glyphs);\n  (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc,\n                nlists, lists, glyphs);\n  wrap(screenPriv, ps, Glyphs, vncDRI3Glyphs);\n\n  vncDRI3SyncDrawableToGPU(pDst->pDrawable);\n}\n\nstatic void vncDRI3CompositeRects(CARD8 op, PicturePtr pDst,\n            xRenderColor * color, int nRect, xRectangle *rects)\n{\n  ScreenPtr screen = pDst->pDrawable->pScreen;\n  PictureScreenPtr ps = GetPictureScreen(screen);\n  vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);\n\n  vncDRI3SyncDrawableFromGPU(pDst->pDrawable);\n\n  unwrap(screenPriv, ps, CompositeRects);\n  (*ps->CompositeRects)(op, pDst, color, nRect, rects);\n  wrap(screenPriv, ps, CompositeRects, vncDRI3CompositeRects);\n\n  vncDRI3SyncDrawableToGPU(pDst->pDrawable);\n}\n\nstatic void vncDRI3Trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int ntrap, xTrapezoid * traps)\n{\n  ScreenPtr screen = pDst->pDrawable->pScreen;\n  PictureScreenPtr ps = GetPictureScreen(screen);\n  vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);\n\n  /* FIXME: Rarely used, so we just sync everything */\n  vncDRI3SyncDrawableFromGPU(pDst->pDrawable);\n\n  unwrap(screenPriv, ps, Trapezoids);\n  (*ps->Trapezoids)(op, pSrc, pDst, maskFormat, xSrc, ySrc,\n                    ntrap, traps);\n  wrap(screenPriv, ps, Trapezoids, vncDRI3Trapezoids);\n\n  vncDRI3SyncDrawableToGPU(pDst->pDrawable);\n}\n\nstatic void vncDRI3Triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int ntri, xTriangle * tris)\n{\n  ScreenPtr screen = pDst->pDrawable->pScreen;\n  PictureScreenPtr ps = GetPictureScreen(screen);\n  vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);\n\n  /* FIXME: Rarely used, so we just sync everything */\n  vncDRI3SyncDrawableFromGPU(pDst->pDrawable);\n\n  unwrap(screenPriv, ps, Triangles);\n  (*ps->Triangles)(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);\n  wrap(screenPriv, ps, Triangles, vncDRI3Triangles);\n\n  vncDRI3SyncDrawableToGPU(pDst->pDrawable);\n}\n\nstatic void vncDRI3TriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int npoint, xPointFixed * points)\n{\n  ScreenPtr screen = pDst->pDrawable->pScreen;\n  PictureScreenPtr ps = GetPictureScreen(screen);\n  vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);\n\n  /* FIXME: Rarely used, so we just sync everything */\n  vncDRI3SyncDrawableFromGPU(pDst->pDrawable);\n\n  unwrap(screenPriv, ps, TriStrip);\n  (*ps->TriStrip)(op, pSrc, pDst, maskFormat, xSrc, ySrc,\n                  npoint, points);\n  wrap(screenPriv, ps, TriStrip, vncDRI3TriStrip)\n\n  vncDRI3SyncDrawableToGPU(pDst->pDrawable);\n}\n\nstatic void vncDRI3TriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int npoint, xPointFixed * points)\n{\n  ScreenPtr screen = pDst->pDrawable->pScreen;\n  PictureScreenPtr ps = GetPictureScreen(screen);\n  vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);\n\n  /* FIXME: Rarely used, so we just sync everything */\n  vncDRI3SyncDrawableFromGPU(pDst->pDrawable);\n\n  unwrap(screenPriv, ps, TriFan);\n  (*ps->TriFan)(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, points);\n  wrap(screenPriv, ps, TriFan, vncDRI3TriFan);\n\n  vncDRI3SyncDrawableToGPU(pDst->pDrawable);\n}\n\nstatic Bool vncDRI3DrawCloseScreen(ScreenPtr screen)\n{\n  vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);\n  PictureScreenPtr ps;\n\n  unwrap(screenPriv, screen, CloseScreen);\n\n  unwrap(screenPriv, screen, CreateGC);\n  unwrap(screenPriv, screen, SourceValidate);\n\n  ps = GetPictureScreenIfSet(screen);\n  if (ps) {\n    unwrap(screenPriv, ps, Composite);\n    unwrap(screenPriv, ps, Glyphs);\n    unwrap(screenPriv, ps, CompositeRects);\n    unwrap(screenPriv, ps, Trapezoids);\n    unwrap(screenPriv, ps, Triangles);\n    unwrap(screenPriv, ps, TriStrip);\n    unwrap(screenPriv, ps, TriFan);\n  }\n\n  return (*screen->CloseScreen)(screen);\n}\n\nBool vncDRI3DrawInit(ScreenPtr screen)\n{\n  vncDRI3DrawScreenPrivatePtr screenPriv;\n  PictureScreenPtr ps;\n\n  if (!dixRegisterPrivateKey(&vncDRI3DrawScreenPrivateKey,\n                             PRIVATE_SCREEN,\n                             sizeof(vncDRI3DrawScreenPrivateRec)))\n    return FALSE;\n  if (!dixRegisterPrivateKey(&vncDRI3GCPrivateKey, PRIVATE_GC,\n                             sizeof(vncDRI3GCPrivateRec)))\n    return FALSE;\n\n  screenPriv = vncDRI3DrawScreenPrivate(screen);\n\n  wrap(screenPriv, screen, CloseScreen, vncDRI3DrawCloseScreen);\n\n  wrap(screenPriv, screen, CreateGC, vncDRI3CreateGC);\n  wrap(screenPriv, screen, SourceValidate, vncDRI3SourceValidate);\n\n  ps = GetPictureScreenIfSet(screen);\n  if (ps) {\n    wrap(screenPriv, ps, Composite, vncDRI3Composite);\n    wrap(screenPriv, ps, Glyphs, vncDRI3Glyphs);\n    wrap(screenPriv, ps, CompositeRects, vncDRI3CompositeRects);\n    wrap(screenPriv, ps, Trapezoids, vncDRI3Trapezoids);\n    wrap(screenPriv, ps, Triangles, vncDRI3Triangles);\n    wrap(screenPriv, ps, TriStrip, vncDRI3TriStrip);\n    wrap(screenPriv, ps, TriFan, vncDRI3TriFan);\n  }\n\n  return TRUE;\n}"
  },
  {
    "path": "unix/xserver/hw/vnc/vncExt.c",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2015 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#define NEED_EVENTS\n#include \"misc.h\"\n#include \"os.h\"\n#include \"dixstruct.h\"\n#include \"extnsionst.h\"\n#include \"scrnintstr.h\"\n\n#define _VNCEXT_SERVER_\n#define _VNCEXT_PROTO_\n#include \"vncExt.h\"\n\n#include \"xorg-version.h\"\n\n#include \"vncExtInit.h\"\n#include \"RFBGlue.h\"\n\nstatic int ProcVncExtDispatch(ClientPtr client);\nstatic int SProcVncExtDispatch(ClientPtr client);\nstatic void vncResetProc(ExtensionEntry* extEntry);\n\nstatic void vncClientStateChange(CallbackListPtr*, void *, void *);\n\nstatic int vncErrorBase = 0;\nstatic int vncEventBase = 0;\n\nint vncNoClipboard = 0;\n\nstatic struct VncInputSelect* vncInputSelectHead = NULL;\n\nstruct VncInputSelect {\n  ClientPtr client;\n  Window window;\n  int mask;\n  struct VncInputSelect* next;\n};\n\nvoid vncAddExtension(void)\n{\n  ExtensionEntry* extEntry;\n\n  extEntry = AddExtension(VNCEXTNAME, VncExtNumberEvents, VncExtNumberErrors,\n                          ProcVncExtDispatch, SProcVncExtDispatch, vncResetProc,\n                          StandardMinorOpcode);\n  if (!extEntry) {\n    FatalError(\"vncAddExtension: AddExtension failed\\n\");\n  }\n\n  vncErrorBase = extEntry->errorBase;\n  vncEventBase = extEntry->eventBase;\n\n  if (!AddCallback(&ClientStateCallback, vncClientStateChange, 0)) {\n    FatalError(\"Add ClientStateCallback failed\\n\");\n  }\n}\n\nint vncNotifyQueryConnect(void)\n{\n  int count;\n  xVncExtQueryConnectNotifyEvent ev;\n\n  ev.type = vncEventBase + VncExtQueryConnectNotify;\n\n  count = 0;\n  for (struct VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {\n    if (cur->mask & VncExtQueryConnectMask) {\n      ev.sequenceNumber = cur->client->sequence;\n      ev.window = cur->window;\n      if (cur->client->swapped) {\n        swaps(&ev.sequenceNumber);\n        swapl(&ev.window);\n      }\n      WriteToClient(cur->client, sizeof(xVncExtQueryConnectNotifyEvent),\n                    (char *)&ev);\n      count++;\n    }\n  }\n\n  return count;\n}\n\nstatic int ProcVncExtSetParam(ClientPtr client)\n{\n  char *param, *value;\n  xVncExtSetParamReply rep;\n\n  REQUEST(xVncExtSetParamReq);\n  REQUEST_FIXED_SIZE(xVncExtSetParamReq,\n                     ((stuff->paramLen + 3) & ~3) +\n                     ((stuff->valueLen + 3) & ~3));\n\n  param = malloc(stuff->paramLen+1);\n  if (param == NULL)\n    return BadAlloc;\n  strncpy(param, (char*)&stuff[1], stuff->paramLen);\n  param[stuff->paramLen] = '\\0';\n\n  value = malloc(stuff->valueLen+1);\n  if (value == NULL) {\n    free(param);\n    return BadAlloc;\n  }\n  strncpy(value, (char*)&stuff[1] + ((stuff->paramLen + 3) & ~3), stuff->valueLen);\n  value[stuff->valueLen] = '\\0';\n\n  rep.type = X_Reply;\n  rep.length = 0;\n  rep.success = 0;\n  rep.sequenceNumber = client->sequence;\n\n  /*\n   * Prevent change of clipboard related parameters if clipboard is disabled.\n   */\n  if (vncNoClipboard &&\n      (strcasecmp(param, \"SendCutText\") == 0 ||\n       strcasecmp(param, \"AcceptCutText\") == 0))\n    goto deny;\n\n  if (!vncOverrideParam(param, value))\n    goto deny;\n\n  rep.success = 1;\n\n  // Send DesktopName update if desktop name has been changed\n  if (strcasecmp(param, \"desktop\") == 0)\n    vncUpdateDesktopName();\n\ndeny:\n  free(param);\n  free(value);\n\n  if (client->swapped) {\n    swaps(&rep.sequenceNumber);\n    swapl(&rep.length);\n  }\n  WriteToClient(client, sizeof(xVncExtSetParamReply), (char *)&rep);\n  return (client->noClientException);\n}\n\nstatic int SProcVncExtSetParam(ClientPtr client)\n{\n  REQUEST(xVncExtSetParamReq);\n  swaps(&stuff->length);\n  REQUEST_AT_LEAST_SIZE(xVncExtSetParamReq);\n  return ProcVncExtSetParam(client);\n}\n\nstatic int ProcVncExtGetParam(ClientPtr client)\n{\n  char* param;\n  char* value;\n  size_t len;\n  xVncExtGetParamReply rep;\n\n  REQUEST(xVncExtGetParamReq);\n  REQUEST_FIXED_SIZE(xVncExtGetParamReq, stuff->paramLen);\n\n  param = malloc(stuff->paramLen+1);\n  if (param == NULL)\n    return BadAlloc;\n  strncpy(param, (char*)&stuff[1], stuff->paramLen);\n  param[stuff->paramLen] = 0;\n\n  value = vncGetParam(param);\n  len = value ? strlen(value) : 0;\n\n  free(param);\n\n  rep.type = X_Reply;\n  rep.sequenceNumber = client->sequence;\n  rep.success = 0;\n  if (value)\n    rep.success = 1;\n  rep.length = (len + 3) >> 2;\n  rep.valueLen = len;\n  if (client->swapped) {\n    swaps(&rep.sequenceNumber);\n    swapl(&rep.length);\n    swaps(&rep.valueLen);\n  }\n  WriteToClient(client, sizeof(xVncExtGetParamReply), (char *)&rep);\n  if (value)\n    WriteToClient(client, len, value);\n  free(value);\n  return (client->noClientException);\n}\n\nstatic int SProcVncExtGetParam(ClientPtr client)\n{\n  REQUEST(xVncExtGetParamReq);\n  swaps(&stuff->length);\n  REQUEST_AT_LEAST_SIZE(xVncExtGetParamReq);\n  return ProcVncExtGetParam(client);\n}\n\nstatic int ProcVncExtGetParamDesc(ClientPtr client)\n{\n  char* param;\n  const char* desc;\n  size_t len;\n  xVncExtGetParamDescReply rep;\n\n  REQUEST(xVncExtGetParamDescReq);\n  REQUEST_FIXED_SIZE(xVncExtGetParamDescReq, stuff->paramLen);\n\n  param = malloc(stuff->paramLen+1);\n  if (param == NULL)\n    return BadAlloc;\n  strncpy(param, (char*)&stuff[1], stuff->paramLen);\n  param[stuff->paramLen] = 0;\n\n  desc = vncGetParamDesc(param);\n  len = desc ? strlen(desc) : 0;\n\n  free(param);\n\n  rep.type = X_Reply;\n  rep.sequenceNumber = client->sequence;\n  rep.success = 0;\n  if (desc)\n    rep.success = 1;\n  rep.length = (len + 3) >> 2;\n  rep.descLen = len;\n  if (client->swapped) {\n    swaps(&rep.sequenceNumber);\n    swapl(&rep.length);\n    swaps(&rep.descLen);\n  }\n  WriteToClient(client, sizeof(xVncExtGetParamDescReply), (char *)&rep);\n  if (desc)\n    WriteToClient(client, len, desc);\n  return (client->noClientException);\n}\n\nstatic int SProcVncExtGetParamDesc(ClientPtr client)\n{\n  REQUEST(xVncExtGetParamDescReq);\n  swaps(&stuff->length);\n  REQUEST_AT_LEAST_SIZE(xVncExtGetParamDescReq);\n  return ProcVncExtGetParamDesc(client);\n}\n\nstatic int ProcVncExtListParams(ClientPtr client)\n{\n  xVncExtListParamsReply rep;\n  char *params;\n  size_t len;\n\n  REQUEST_SIZE_MATCH(xVncExtListParamsReq);\n\n  rep.type = X_Reply;\n  rep.sequenceNumber = client->sequence;\n\n  params = vncGetParamList();\n  if (params == NULL)\n    return BadAlloc;\n\n  len = strlen(params);\n\n  rep.length = (len + 3) >> 2;\n  rep.nParams = vncGetParamCount();\n  if (client->swapped) {\n    swaps(&rep.sequenceNumber);\n    swapl(&rep.length);\n    swaps(&rep.nParams);\n  }\n  WriteToClient(client, sizeof(xVncExtListParamsReply), (char *)&rep);\n  WriteToClient(client, len, (char*)params);\n  free(params);\n  return (client->noClientException);\n}\n\nstatic int SProcVncExtListParams(ClientPtr client)\n{\n  REQUEST(xVncExtListParamsReq);\n  swaps(&stuff->length);\n  REQUEST_SIZE_MATCH(xVncExtListParamsReq);\n  return ProcVncExtListParams(client);\n}\n\nstatic int ProcVncExtSelectInput(ClientPtr client)\n{\n  struct VncInputSelect** nextPtr;\n  struct VncInputSelect* cur;\n  REQUEST(xVncExtSelectInputReq);\n  REQUEST_SIZE_MATCH(xVncExtSelectInputReq);\n  nextPtr = &vncInputSelectHead;\n  for (cur = vncInputSelectHead; cur; cur = *nextPtr) {\n    if (cur->client == client && cur->window == stuff->window) {\n      cur->mask = stuff->mask;\n      if (!cur->mask) {\n        *nextPtr = cur->next;\n        free(cur);\n      }\n      break;\n    }\n    nextPtr = &cur->next;\n  }\n  if (!cur) {\n    cur = malloc(sizeof(struct VncInputSelect));\n    if (cur == NULL)\n      return BadAlloc;\n    memset(cur, 0, sizeof(struct VncInputSelect));\n\n    cur->client = client;\n    cur->window = stuff->window;\n    cur->mask = stuff->mask;\n\n    cur->next = vncInputSelectHead;\n    vncInputSelectHead = cur;\n  }\n  return (client->noClientException);\n}\n\nstatic int SProcVncExtSelectInput(ClientPtr client)\n{\n  REQUEST(xVncExtSelectInputReq);\n  swaps(&stuff->length);\n  REQUEST_SIZE_MATCH(xVncExtSelectInputReq);\n  swapl(&stuff->window);\n  swapl(&stuff->mask);\n  return ProcVncExtSelectInput(client);\n}\n\nstatic int ProcVncExtConnect(ClientPtr client)\n{\n  char *address;\n  xVncExtConnectReply rep;\n\n  REQUEST(xVncExtConnectReq);\n  REQUEST_FIXED_SIZE(xVncExtConnectReq, stuff->strLen);\n\n  address = malloc(stuff->strLen+1);\n  if (address == NULL)\n    return BadAlloc;\n  strncpy(address, (char*)&stuff[1], stuff->strLen);\n  address[stuff->strLen] = 0;\n\n  rep.success = 0;\n  if (vncConnectClient(address, (int)stuff->viewOnly) == 0)\n        rep.success = 1;\n\n  rep.type = X_Reply;\n  rep.length = 0;\n  rep.sequenceNumber = client->sequence;\n  if (client->swapped) {\n    swaps(&rep.sequenceNumber);\n    swapl(&rep.length);\n  }\n  WriteToClient(client, sizeof(xVncExtConnectReply), (char *)&rep);\n\n  free(address);\n\n  return (client->noClientException);\n}\n\nstatic int SProcVncExtConnect(ClientPtr client)\n{\n  REQUEST(xVncExtConnectReq);\n  swaps(&stuff->length);\n  REQUEST_AT_LEAST_SIZE(xVncExtConnectReq);\n  return ProcVncExtConnect(client);\n}\n\n\nstatic int ProcVncExtGetQueryConnect(ClientPtr client)\n{\n  uint32_t opaqueId;\n  const char *qcAddress, *qcUsername;\n  int qcTimeout;\n\n  xVncExtGetQueryConnectReply rep;\n\n  REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);\n\n  vncGetQueryConnect(&opaqueId, &qcAddress, &qcUsername, &qcTimeout);\n\n  rep.type = X_Reply;\n  rep.sequenceNumber = client->sequence;\n  rep.timeout = qcTimeout;\n  rep.addrLen = qcTimeout ? strlen(qcAddress) : 0;\n  rep.userLen = qcTimeout ? strlen(qcUsername) : 0;\n  rep.opaqueId = (CARD32)(long)opaqueId;\n  rep.length = ((rep.userLen + 3) >> 2) + ((rep.addrLen + 3) >> 2);\n  if (client->swapped) {\n    swaps(&rep.sequenceNumber);\n    swapl(&rep.addrLen);\n    swapl(&rep.userLen);\n    swapl(&rep.timeout);\n    swapl(&rep.opaqueId);\n    swapl(&rep.length);\n  }\n  WriteToClient(client, sizeof(xVncExtGetQueryConnectReply), (char *)&rep);\n  if (qcTimeout)\n    WriteToClient(client, strlen(qcAddress), qcAddress);\n  if (qcTimeout)\n    WriteToClient(client, strlen(qcUsername), qcUsername);\n  return (client->noClientException);\n}\n\nstatic int SProcVncExtGetQueryConnect(ClientPtr client)\n{\n  REQUEST(xVncExtGetQueryConnectReq);\n  swaps(&stuff->length);\n  REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);\n  return ProcVncExtGetQueryConnect(client);\n}\n\n\nstatic int ProcVncExtApproveConnect(ClientPtr client)\n{\n  REQUEST(xVncExtApproveConnectReq);\n  REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);\n  vncApproveConnection(stuff->opaqueId, stuff->approve);\n  // Inform other clients of the event and tidy up\n  vncNotifyQueryConnect();\n  return (client->noClientException);\n}\n\nstatic int SProcVncExtApproveConnect(ClientPtr client)\n{\n  REQUEST(xVncExtApproveConnectReq);\n  swaps(&stuff->length);\n  swapl(&stuff->opaqueId);\n  REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);\n  return ProcVncExtApproveConnect(client);\n}\n\n\nstatic int ProcVncExtDispatch(ClientPtr client)\n{\n  REQUEST(xReq);\n  switch (stuff->data) {\n  case X_VncExtSetParam:\n    return ProcVncExtSetParam(client);\n  case X_VncExtGetParam:\n    return ProcVncExtGetParam(client);\n  case X_VncExtGetParamDesc:\n    return ProcVncExtGetParamDesc(client);\n  case X_VncExtListParams:\n    return ProcVncExtListParams(client);\n  case X_VncExtSelectInput:\n    return ProcVncExtSelectInput(client);\n  case X_VncExtConnect:\n    return ProcVncExtConnect(client);\n  case X_VncExtGetQueryConnect:\n    return ProcVncExtGetQueryConnect(client);\n  case X_VncExtApproveConnect:\n    return ProcVncExtApproveConnect(client);\n  default:\n    return BadRequest;\n  }\n}\n\nstatic int SProcVncExtDispatch(ClientPtr client)\n{\n  REQUEST(xReq);\n  switch (stuff->data) {\n  case X_VncExtSetParam:\n    return SProcVncExtSetParam(client);\n  case X_VncExtGetParam:\n    return SProcVncExtGetParam(client);\n  case X_VncExtGetParamDesc:\n    return SProcVncExtGetParamDesc(client);\n  case X_VncExtListParams:\n    return SProcVncExtListParams(client);\n  case X_VncExtSelectInput:\n    return SProcVncExtSelectInput(client);\n  case X_VncExtConnect:\n    return SProcVncExtConnect(client);\n  case X_VncExtGetQueryConnect:\n    return SProcVncExtGetQueryConnect(client);\n  case X_VncExtApproveConnect:\n    return SProcVncExtApproveConnect(client);\n  default:\n    return BadRequest;\n  }\n}\n\nstatic void vncResetProc(ExtensionEntry* extEntry)\n{\n  vncExtensionClose();\n}\n\nstatic void vncClientStateChange(CallbackListPtr * l, void * d, void * p)\n{\n  ClientPtr client = ((NewClientInfoRec*)p)->client;\n  if (client->clientState == ClientStateGone) {\n    struct VncInputSelect** nextPtr = &vncInputSelectHead;\n    for (struct VncInputSelect* cur = vncInputSelectHead; cur; cur = *nextPtr) {\n      if (cur->client == client) {\n        *nextPtr = cur->next;\n        free(cur);\n        continue;\n      }\n      nextPtr = &cur->next;\n    }\n  }\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncExtInit.cc",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdio.h>\n#include <errno.h>\n#include <unistd.h>\n#include <sys/types.h>\n#include <pwd.h>\n\n#include <string>\n\n#include <core/Configuration.h>\n#include <core/Logger_stdio.h>\n#include <core/LogWriter.h>\n#include <core/Region.h>\n\n#include <rfb/ServerCore.h>\n#include <rdr/HexOutStream.h>\n#include <rfb/ledStates.h>\n\n#include <network/TcpSocket.h>\n#include <network/UnixSocket.h>\n\n#include \"XserverDesktop.h\"\n#include \"vncExtInit.h\"\n#include \"vncHooks.h\"\n#include \"vncBlockHandler.h\"\n#include \"vncSelection.h\"\n#include \"XorgGlue.h\"\n#include \"RandrGlue.h\"\n#include \"xorg-version.h\"\n\nextern \"C\" {\nvoid vncSetGlueContext(int screenIndex);\n}\n\nstatic core::LogWriter vlog(\"vncext\");\n\n// We can't safely get this from Xorg\n#define MAXSCREENS 16\n\nstatic unsigned long vncExtGeneration = 0;\nstatic bool initialised = false;\nstatic XserverDesktop* desktop[MAXSCREENS] = { 0, };\nvoid* vncFbptr[MAXSCREENS] = { 0, };\nint vncFbstride[MAXSCREENS];\n\nint vncInetdSock = -1;\n\nstatic const char* defaultDesktopName();\n\ncore::IntParameter\n  rfbport(\"rfbport\",\n          \"TCP port to listen for RFB protocol\", 0, -1, 65535);\ncore::StringParameter\n  rfbunixpath(\"rfbunixpath\",\n              \"Unix socket to listen for RFB protocol\", \"\");\ncore::IntParameter\n  rfbunixmode(\"rfbunixmode\",\n              \"Unix socket access mode\", 0600, 0000, 0777);\ncore::StringParameter\n  desktopName(\"desktop\", \"Name of VNC desktop\", defaultDesktopName());\ncore::BoolParameter\n  localhostOnly(\"localhost\",\n                \"Only allow connections from localhost\", false);\ncore::StringParameter\n  interface(\"interface\",\n            \"Listen on the specified network address\", \"all\");\ncore::BoolParameter\n  avoidShiftNumLock(\"AvoidShiftNumLock\",\n                    \"Avoid fake Shift presses for keys affected by \"\n                    \"NumLock.\", true);\ncore::StringListParameter\n  allowOverride(\"AllowOverride\",\n                \"Comma separated list of parameters that can be \"\n                \"modified using VNC extension.\",\n                {\"desktop\", \"AcceptPointerEvents\", \"SendCutText\",\n                 \"AcceptCutText\", \"SendPrimary\", \"SetPrimary\"});\ncore::BoolParameter\n  setPrimary(\"SetPrimary\",\n             \"Set the PRIMARY as well as the CLIPBOARD selection\",\n             true);\ncore::BoolParameter\n  sendPrimary(\"SendPrimary\",\n              \"Send the PRIMARY as well as the CLIPBOARD selection\",\n              true);\n\nstatic const char* defaultDesktopName()\n{\n  size_t host_max = sysconf(_SC_HOST_NAME_MAX);\n  if (host_max < 0)\n    return \"\";\n\n  std::vector<char> hostname(host_max + 1);\n  if (gethostname(hostname.data(), hostname.size()) == -1)\n    return \"\";\n\n  struct passwd* pwent = getpwuid(getuid());\n  if (pwent == nullptr)\n    return \"\";\n\n  size_t len = snprintf(nullptr, 0, \"%s@%s\", pwent->pw_name, hostname.data());\n  if (len < 0)\n    return \"\";\n\n  char* name = new char[len + 1];\n\n  snprintf(name, len + 1, \"%s@%s\", pwent->pw_name, hostname.data());\n\n  return name;\n}\n\nstatic rfb::PixelFormat vncGetPixelFormat(int scrIdx)\n{\n  int depth, bpp;\n  int trueColour, bigEndian;\n  int redMask, greenMask, blueMask;\n\n  int redShift, greenShift, blueShift;\n  int redMax, greenMax, blueMax;\n\n  vncGetScreenFormat(scrIdx, &depth, &bpp, &trueColour, &bigEndian,\n                     &redMask, &greenMask, &blueMask);\n\n  if (!trueColour) {\n    vlog.error(\"Pseudocolour not supported\");\n    abort();\n  }\n\n  redShift   = ffs(redMask) - 1;\n  greenShift = ffs(greenMask) - 1;\n  blueShift  = ffs(blueMask) - 1;\n  redMax     = redMask   >> redShift;\n  greenMax   = greenMask >> greenShift;\n  blueMax    = blueMask  >> blueShift;\n\n  return rfb::PixelFormat(bpp, depth, bigEndian, trueColour,\n                          redMax, greenMax, blueMax,\n                          redShift, greenShift, blueShift);\n}\n\nvoid vncExtensionInit(void)\n{\n  if (vncExtGeneration == vncGetServerGeneration()) {\n    vlog.error(\"vncExtensionInit: Called twice in same generation?\");\n    return;\n  }\n  vncExtGeneration = vncGetServerGeneration();\n\n  if (vncGetScreenCount() > MAXSCREENS)\n    vncFatalError(\"vncExtensionInit: Too many screens\\n\");\n\n  vncAddExtension();\n\n  vncSelectionInit();\n\n  vlog.info(\"VNC extension running!\");\n\n  try {\n    if (!initialised) {\n      core::initStdIOLoggers();\n\n      allowOverride.setImmutable();\n\n      initialised = true;\n    }\n\n    for (int scr = 0; scr < vncGetScreenCount(); scr++) {\n\n      if (!desktop[scr]) {\n        std::list<network::SocketListener*> listeners;\n        bool inetd = false;\n        if (scr == 0 && vncInetdSock != -1) {\n          inetd = true;\n          if (network::isSocketListening(vncInetdSock))\n          {\n            listeners.push_back(new network::TcpListener(vncInetdSock));\n            vlog.info(\"inetd wait\");\n          }\n        }\n\n        if (!inetd && ((const char*)rfbunixpath)[0] != '\\0') {\n          char path[PATH_MAX];\n          int mode = (int)rfbunixmode;\n\n          if (scr == 0)\n            strncpy(path, rfbunixpath, sizeof(path));\n          else\n            snprintf(path, sizeof(path), \"%s.%d\",\n                     (const char*)rfbunixpath, scr);\n          path[sizeof(path)-1] = '\\0';\n\n          listeners.push_back(new network::UnixListener(path, mode));\n\n          vlog.info(\"Listening for VNC connections on %s (mode %04o)\",\n                    path, mode);\n        }\n\n        if (!inetd && rfbport != -1) {\n          std::list<network::SocketListener*> tcp_listeners;\n          const char *addr = interface;\n          int port = rfbport;\n          if (port == 0) port = 5900 + atoi(vncGetDisplay());\n          port += 1000 * scr;\n          if (strcasecmp(addr, \"all\") == 0)\n            addr = 0;\n          if (localhostOnly)\n            network::createLocalTcpListeners(&tcp_listeners, port);\n          else\n            network::createTcpListeners(&tcp_listeners, addr, port);\n\n          if (!tcp_listeners.empty()) {\n            listeners.splice (listeners.end(), tcp_listeners);\n            vlog.info(\"Listening for VNC connections on %s interface(s), port %d\",\n                      localhostOnly ? \"local\" : (const char*)interface,\n                      port);\n          }\n        }\n\n        if (!inetd && listeners.empty())\n          throw std::runtime_error(\"No path or port configured for incoming connections\");\n\n        rfb::PixelFormat pf = vncGetPixelFormat(scr);\n\n        vncSetGlueContext(scr);\n        desktop[scr] = new XserverDesktop(scr,\n                                          listeners,\n                                          desktopName,\n                                          pf,\n                                          vncGetScreenWidth(),\n                                          vncGetScreenHeight(),\n                                          vncFbptr[scr],\n                                          vncFbstride[scr]);\n        vlog.info(\"Created VNC server for screen %d\", scr);\n\n        if (scr == 0 && vncInetdSock != -1 && listeners.empty()) {\n          network::Socket* sock = new network::TcpSocket(vncInetdSock);\n          if (!desktop[scr]->addClient(sock, false, false)) {\n            delete sock;\n            throw std::runtime_error(\"Failed to add inetd socket\");\n          }\n          vlog.info(\"Added inetd sock\");\n        }\n      }\n\n      vncHooksInit(scr);\n    }\n  } catch (std::exception& e) {\n    vncFatalError(\"vncExtInit: %s\\n\",e.what());\n  }\n\n  vncRegisterBlockHandlers();\n}\n\nvoid vncExtensionClose(void)\n{\n  try {\n    for (int scr = 0; scr < vncGetScreenCount(); scr++) {\n      delete desktop[scr];\n      desktop[scr] = nullptr;\n    }\n  } catch (std::exception& e) {\n    vncFatalError(\"vncExtInit: %s\\n\",e.what());\n  }\n}\n\nvoid vncHandleSocketEvent(int fd, int scrIdx, int read, int write)\n{\n  desktop[scrIdx]->handleSocketEvent(fd, read, write);\n}\n\nvoid vncCallBlockHandlers(int* timeout)\n{\n  for (int scr = 0; scr < vncGetScreenCount(); scr++)\n    desktop[scr]->blockHandler(timeout);\n}\n\nint vncGetAvoidShiftNumLock(void)\n{\n  return (bool)avoidShiftNumLock;\n}\n\nint vncGetSetPrimary(void)\n{\n  return (bool)setPrimary;\n}\n\nint vncGetSendPrimary(void)\n{\n  return (bool)sendPrimary;\n}\n\nvoid vncUpdateDesktopName(void)\n{\n  for (int scr = 0; scr < vncGetScreenCount(); scr++)\n    desktop[scr]->setDesktopName(desktopName);\n}\n\nvoid vncRequestClipboard(void)\n{\n  for (int scr = 0; scr < vncGetScreenCount(); scr++)\n    desktop[scr]->requestClipboard();\n}\n\nvoid vncAnnounceClipboard(int available)\n{\n  for (int scr = 0; scr < vncGetScreenCount(); scr++)\n    desktop[scr]->announceClipboard(available);\n}\n\nvoid vncSendClipboardData(const char* data)\n{\n  for (int scr = 0; scr < vncGetScreenCount(); scr++)\n    desktop[scr]->sendClipboardData(data);\n}\n\nint vncConnectClient(const char *addr, int viewOnly)\n{\n  if (strlen(addr) == 0) {\n    try {\n      desktop[0]->disconnectClients();\n    } catch (std::exception& e) {\n      vlog.error(\"Disconnecting all clients: %s\", e.what());\n      return -1;\n    }\n    return 0;\n  }\n\n  std::string host;\n  int port;\n\n  network::getHostAndPort(addr, &host, &port, 5500);\n\n  try {\n    network::Socket* sock = new network::TcpSocket(host.c_str(), port);\n    vlog.info(\"Reverse connection: %s:%d%s\", host.c_str(), port,\n              viewOnly ? \" (view only)\" : \"\");\n    if (!desktop[0]->addClient(sock, true, (bool)viewOnly)) {\n      delete sock;\n      throw std::runtime_error(\"Failed to add reverse connection socket\");\n    }\n  } catch (std::exception& e) {\n    vlog.error(\"Reverse connection: %s\", e.what());\n    return -1;\n  }\n\n  return 0;\n}\n\nvoid vncGetQueryConnect(uint32_t *opaqueId, const char**username,\n                        const char **address, int *timeout)\n{\n  for (int scr = 0; scr < vncGetScreenCount(); scr++) {\n    desktop[scr]->getQueryConnect(opaqueId, username, address, timeout);\n    if (opaqueId != 0)\n      break;\n  }\n}\n\nvoid vncApproveConnection(uint32_t opaqueId, int approve)\n{\n  for (int scr = 0; scr < vncGetScreenCount(); scr++) {\n    desktop[scr]->approveConnection(opaqueId, approve,\n                                    \"Connection rejected by local user\");\n  }\n}\n\nvoid vncBell()\n{\n  for (int scr = 0; scr < vncGetScreenCount(); scr++)\n    desktop[scr]->bell();\n}\n\nvoid vncSetLEDState(unsigned long leds)\n{\n  unsigned int state;\n\n  state = 0;\n  if (leds & (1 << 0))\n    state |= rfb::ledCapsLock;\n  if (leds & (1 << 1))\n    state |= rfb::ledNumLock;\n  if (leds & (1 << 2))\n    state |= rfb::ledScrollLock;\n\n  for (int scr = 0; scr < vncGetScreenCount(); scr++)\n    desktop[scr]->setLEDState(state);\n}\n\nvoid vncAddChanged(int scrIdx, int nRects,\n                   const struct UpdateRect *rects)\n{\n  for (int i = 0;i < nRects;i++) {\n    desktop[scrIdx]->add_changed({{rects[i].x1, rects[i].y1,\n                                   rects[i].x2, rects[i].y2}});\n  }\n}\n\nvoid vncAddCopied(int scrIdx, int nRects,\n                  const struct UpdateRect *rects,\n                  int dx, int dy)\n{\n  for (int i = 0;i < nRects;i++) {\n    desktop[scrIdx]->add_copied({{rects[i].x1, rects[i].y1,\n                                  rects[i].x2, rects[i].y2}},\n                                {dx, dy});\n  }\n}\n\nvoid vncSetCursorSprite(int width, int height, int hotX, int hotY,\n                        const unsigned char *rgbaData)\n{\n  for (int scr = 0; scr < vncGetScreenCount(); scr++)\n    desktop[scr]->setCursor(width, height, hotX, hotY, rgbaData);\n}\n\nvoid vncSetCursorPos(int scrIdx, int x, int y)\n{\n  desktop[scrIdx]->setCursorPos(x, y, true);\n}\n\nvoid vncPreScreenResize(int scrIdx)\n{\n  // We need to prevent the RFB core from accessing the framebuffer\n  // for a while as there might be updates thrown our way inside\n  // the routines that change the screen (i.e. before we have a\n  // pointer to the new framebuffer).\n  desktop[scrIdx]->blockUpdates();\n}\n\nvoid vncPostScreenResize(int scrIdx, int success, int width, int height)\n{\n  if (success) {\n    // Let the RFB core know of the new dimensions and framebuffer\n    try {\n      desktop[scrIdx]->setFramebuffer(width, height,\n                                      vncFbptr[scrIdx],\n                                      vncFbstride[scrIdx]);\n    } catch (std::exception& e) {\n      vncFatalError(\"vncPostScreenResize: %s\\n\", e.what());\n    }\n  }\n\n  desktop[scrIdx]->unblockUpdates();\n\n  if (success) {\n    // Mark entire screen as changed\n    desktop[scrIdx]->add_changed({{0, 0, width, height}});\n  }\n}\n\nvoid vncRefreshScreenLayout(int scrIdx)\n{\n  try {\n    desktop[scrIdx]->refreshScreenLayout();\n  } catch (std::exception& e) {\n    vncFatalError(\"vncRefreshScreenLayout: %s\\n\", e.what());\n  }\n}\n\nuint64_t vncGetMsc(int scrIdx)\n{\n  try {\n    return desktop[scrIdx]->getMsc();\n  } catch (std::exception& e) {\n    vncFatalError(\"vncGetMsc: %s\\n\", e.what());\n  }\n}\n\nvoid vncQueueMsc(int scrIdx, uint64_t id, uint64_t msc)\n{\n  try {\n    desktop[scrIdx]->queueMsc(id, msc);\n  } catch (std::exception& e) {\n    vncFatalError(\"vncQueueMsc: %s\\n\", e.what());\n  }\n}\n\nvoid vncAbortMsc(int scrIdx, uint64_t id)\n{\n  try {\n    desktop[scrIdx]->abortMsc(id);\n  } catch (std::exception& e) {\n    vncFatalError(\"vncAbortMsc: %s\\n\", e.what());\n  }\n}\n\nint vncOverrideParam(const char *param, const char *value)\n{\n  for (const char* allowed : allowOverride) {\n    if (strcasecmp(allowed, param) == 0)\n      return core::Configuration::setParam(param, value);\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncExtInit.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __VNCEXTINIT_H__\n#define __VNCEXTINIT_H__\n\n#include <stdint.h>\n#include <stddef.h>\n#include <sys/select.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// vncExt.c\nextern int vncNoClipboard;\n\nvoid vncAddExtension(void);\n\nint vncNotifyQueryConnect(void);\n\n// vncExtInit.cc\nextern void* vncFbptr[];\nextern int vncFbstride[];\n\nextern int vncInetdSock;\n\nvoid vncExtensionInit(void);\nvoid vncExtensionClose(void);\n\nvoid vncHandleSocketEvent(int fd, int scrIdx, int read, int write);\nvoid vncCallBlockHandlers(int* timeout);\n\nint vncGetAvoidShiftNumLock(void);\n\nint vncGetSetPrimary(void);\nint vncGetSendPrimary(void);\n\nvoid vncUpdateDesktopName(void);\n\nvoid vncRequestClipboard(void);\nvoid vncAnnounceClipboard(int available);\nvoid vncSendClipboardData(const char* data);\n\nint vncConnectClient(const char *addr, int viewOnly);\n\nvoid vncGetQueryConnect(uint32_t *opaqueId, const char**username,\n                        const char **address, int *timeout);\nvoid vncApproveConnection(uint32_t opaqueId, int approve);\n\nvoid vncBell(void);\n\nvoid vncSetLEDState(unsigned long leds);\n\n// Must match rfb::ShortRect in common/rfb/Region.h, and BoxRec in the\n// Xorg source.\nstruct UpdateRect {\n  short x1, y1, x2, y2;\n};\n\nvoid vncAddChanged(int scrIdx, int nRects,\n                   const struct UpdateRect *rects);\nvoid vncAddCopied(int scrIdx, int nRects,\n                  const struct UpdateRect *rects,\n                  int dx, int dy);\n\nvoid vncSetCursorSprite(int width, int height, int hotX, int hotY,\n                        const unsigned char *rgbaData);\nvoid vncSetCursorPos(int scrIdx, int x, int y);\n\nvoid vncPreScreenResize(int scrIdx);\nvoid vncPostScreenResize(int scrIdx, int success, int width, int height);\nvoid vncRefreshScreenLayout(int scrIdx);\n\nuint64_t vncGetMsc(int scrIdx);\nvoid vncQueueMsc(int scrIdx, uint64_t id, uint64_t msc);\nvoid vncAbortMsc(int scrIdx, uint64_t id);\n\nint vncOverrideParam(const char *param, const char *value);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncHooks.c",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2024 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include <stdio.h>\n\n#include \"vncHooks.h\"\n#include \"vncExtInit.h\"\n\n#include \"xorg-version.h\"\n\n#include \"scrnintstr.h\"\n#include \"windowstr.h\"\n#include \"cursorstr.h\"\n#include \"gcstruct.h\"\n#include \"regionstr.h\"\n#include \"dixfontstr.h\"\n#include \"colormapst.h\"\n#include \"mipointer.h\"\n#include \"mipointrst.h\"\n#include \"picturestr.h\"\n#include \"randrstr.h\"\n\n#define DBGPRINT(x) //(fprintf x)\n\n// MAX_RECTS_PER_OP is the maximum number of rectangles we generate from\n// operations like Polylines and PolySegment.  If the operation is more complex\n// than this, we simply use the bounding box.  Ideally it would be a\n// command-line option, but that would involve an extra malloc each time, so we\n// fix it here.\n#define MAX_RECTS_PER_OP 5\n\n// vncHooksScreenRec and vncHooksGCRec contain pointers to the original\n// functions which we \"wrap\" in order to hook the screen changes.  The screen\n// functions are each wrapped individually, while the GC \"funcs\" and \"ops\" are\n// wrapped as a unit.\n\ntypedef struct _vncHooksScreenRec {\n  int                          ignoreHooks;\n\n  CloseScreenProcPtr           CloseScreen;\n  CreateGCProcPtr              CreateGC;\n  CopyWindowProcPtr            CopyWindow;\n  ClearToBackgroundProcPtr     ClearToBackground;\n  CursorWarpedToProcPtr        CursorWarpedTo;\n  ScreenBlockHandlerProcPtr    BlockHandler;\n\n  CompositeProcPtr             Composite;\n  GlyphsProcPtr                Glyphs;\n  CompositeRectsProcPtr        CompositeRects;\n  TrapezoidsProcPtr            Trapezoids;\n  TrianglesProcPtr             Triangles;\n  TriStripProcPtr              TriStrip;\n  TriFanProcPtr                TriFan;\n\n  RRSetConfigProcPtr           rrSetConfig;\n  RRScreenSetSizeProcPtr       rrScreenSetSize;\n  RRCrtcSetProcPtr             rrCrtcSet;\n\n  miPointerSpriteFuncPtr       spriteFuncs;\n} vncHooksScreenRec, *vncHooksScreenPtr;\n\ntypedef struct _vncHooksGCRec {\n    const GCFuncs *funcs;\n    const GCOps *ops;\n} vncHooksGCRec, *vncHooksGCPtr;\n\n#define wrap(priv, real, mem, func) {\\\n    priv->mem = real->mem; \\\n    real->mem = func; \\\n}\n\n#define unwrap(priv, real, mem) {\\\n    real->mem = priv->mem; \\\n}\n\nstatic DevPrivateKeyRec vncHooksScreenKeyRec;\nstatic DevPrivateKeyRec vncHooksGCKeyRec;\n#define vncHooksScreenPrivateKey (&vncHooksScreenKeyRec)\n#define vncHooksGCPrivateKey (&vncHooksGCKeyRec)\n\n#define vncHooksScreenPrivate(pScreen) \\\n        (vncHooksScreenPtr) dixLookupPrivate(&(pScreen)->devPrivates, \\\n                                             vncHooksScreenPrivateKey)\n#define vncHooksGCPrivate(pGC) \\\n        (vncHooksGCPtr) dixLookupPrivate(&(pGC)->devPrivates, \\\n                                         vncHooksGCPrivateKey)\n\n// screen functions\n\nstatic Bool vncHooksCloseScreen(ScreenPtr pScreen);\nstatic Bool vncHooksCreateGC(GCPtr pGC);\nstatic void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,\n                               RegionPtr pOldRegion);\nstatic void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,\n                                      int h, Bool generateExposures);\nstatic void vncHooksCursorWarpedTo(DeviceIntPtr pDev,\n                                   ScreenPtr pScreen_, ClientPtr pClient,\n                                   WindowPtr pWindow, SpritePtr pSprite,\n                                   int x, int y);\nstatic void vncHooksBlockHandler(ScreenPtr pScreen, void * pTimeout);\nstatic void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, \n\t\t\t      PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, \n\t\t\t      INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);\nstatic void vncHooksGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, \n\t\t\t      PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists, \n\t\t\t      GlyphListPtr lists, GlyphPtr * glyphs);\nstatic void vncHooksCompositeRects(CARD8 op, PicturePtr pDst,\n            xRenderColor * color, int nRect, xRectangle *rects);\nstatic void vncHooksTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int ntrap, xTrapezoid * traps);\nstatic void vncHooksTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int ntri, xTriangle * tris);\nstatic void vncHooksTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int npoint, xPointFixed * points);\nstatic void vncHooksTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int npoint, xPointFixed * points);\nstatic Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation,\n                                   int rate, RRScreenSizePtr pSize);\nstatic Bool vncHooksRandRScreenSetSize(ScreenPtr pScreen,\n                                       CARD16 width, CARD16 height,\n                                       CARD32 mmWidth, CARD32 mmHeight);\nstatic Bool vncHooksRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc,\n                                 RRModePtr mode, int x, int y,\n                                 Rotation rotation, int numOutputs,\n                                 RROutputPtr *outputs);\n\n// Sprite functions\n\nstatic Bool vncHooksRealizeCursor(DeviceIntPtr dev, ScreenPtr screen,\n                                  CursorPtr cursor);\nstatic Bool vncHooksUnrealizeCursor(DeviceIntPtr dev, ScreenPtr screen,\n                                    CursorPtr cursor);\nstatic void vncHooksSetCursor(DeviceIntPtr dev, ScreenPtr screen,\n                              CursorPtr cursor, int x, int y);\nstatic void vncHooksMoveCursor(DeviceIntPtr dev, ScreenPtr screen,\n                               int x, int y);\nstatic Bool vncHooksDeviceCursorInitialize(DeviceIntPtr dev,\n                                           ScreenPtr screen);\nstatic void vncHooksDeviceCursorCleanup(DeviceIntPtr dev,\n                                        ScreenPtr screen);\n\nstatic miPointerSpriteFuncRec vncHooksSpriteFuncs = {\n    vncHooksRealizeCursor,\n    vncHooksUnrealizeCursor,\n    vncHooksSetCursor,\n    vncHooksMoveCursor,\n    vncHooksDeviceCursorInitialize,\n    vncHooksDeviceCursorCleanup\n};\n\n// GC \"funcs\"\n\nstatic void vncHooksValidateGC(GCPtr pGC, unsigned long changes,\n                               DrawablePtr pDrawable);\nstatic void vncHooksChangeGC(GCPtr pGC, unsigned long mask);\nstatic void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst);\nstatic void vncHooksDestroyGC(GCPtr pGC);\nstatic void vncHooksChangeClip(GCPtr pGC, int type, void * pValue,int nrects);\nstatic void vncHooksDestroyClip(GCPtr pGC);\nstatic void vncHooksCopyClip(GCPtr dst, GCPtr src);\n\nstatic GCFuncs vncHooksGCFuncs = {\n  vncHooksValidateGC, vncHooksChangeGC, vncHooksCopyGC, vncHooksDestroyGC,\n  vncHooksChangeClip, vncHooksDestroyClip, vncHooksCopyClip,\n};\n\n// GC \"ops\"\n\nstatic void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,\n                              DDXPointPtr pptInit, int *pwidthInit,\n                              int fSorted);\nstatic void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,\n                             DDXPointPtr ppt, int *pwidth, int nspans,\n                             int fSorted);\nstatic void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,\n                             int x, int y, int w, int h, int leftPad,\n                             int format, char *pBits);\nstatic RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,\n                                  GCPtr pGC, int srcx, int srcy, int w, int h,\n                                  int dstx, int dsty);\nstatic RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,\n                                   GCPtr pGC, int srcx, int srcy, int w, int h,\n                                   int dstx, int dsty, unsigned long plane);\nstatic void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,\n                              int npt, xPoint *pts);\nstatic void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,\n                              int npt, DDXPointPtr ppts);\nstatic void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,\n                                xSegment *segs);\nstatic void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,\n                                  xRectangle *rects);\nstatic void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,\n                            xArc *arcs);\nstatic void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,\n                                int mode, int count, DDXPointPtr pts);\nstatic void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,\n                                 xRectangle *rects);\nstatic void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,\n                                xArc *arcs);\nstatic int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,\n                             int count, char *chars);\nstatic int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,\n                              int count, unsigned short *chars);\nstatic void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,\n                               int count, char *chars);\nstatic void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,\n                                int count, unsigned short *chars);\nstatic void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,\n                                  int y, unsigned int nglyph,\n                                  CharInfoPtr *ppci, void * pglyphBase);\nstatic void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,\n                                 int y, unsigned int nglyph,\n                                 CharInfoPtr *ppci, void * pglyphBase);\nstatic void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,\n                               DrawablePtr pDrawable, int w, int h, int x,\n                               int y);\n\nstatic GCOps vncHooksGCOps = {\n  vncHooksFillSpans, vncHooksSetSpans, vncHooksPutImage, vncHooksCopyArea,\n  vncHooksCopyPlane, vncHooksPolyPoint, vncHooksPolylines, vncHooksPolySegment,\n  vncHooksPolyRectangle, vncHooksPolyArc, vncHooksFillPolygon,\n  vncHooksPolyFillRect, vncHooksPolyFillArc, vncHooksPolyText8,\n  vncHooksPolyText16, vncHooksImageText8, vncHooksImageText16,\n  vncHooksImageGlyphBlt, vncHooksPolyGlyphBlt, vncHooksPushPixels\n};\n\n\n\n/////////////////////////////////////////////////////////////////////////////\n// vncHooksInit() is called at initialisation time and every time the server\n// resets.  It is called once for each screen, but the indexes are only\n// allocated once for each server generation.\n\nint vncHooksInit(int scrIdx)\n{\n  ScreenPtr pScreen;\n  vncHooksScreenPtr vncHooksScreen;\n\n  PictureScreenPtr ps;\n  rrScrPrivPtr rp;\n  miPointerScreenPtr miPointerPriv;\n\n  pScreen = screenInfo.screens[scrIdx];\n\n  if (sizeof(BoxRec) != sizeof(struct UpdateRect)) {\n    ErrorF(\"vncHooksInit: Incompatible BoxRec size\\n\");\n    return FALSE;\n  }\n\n  if (!dixRegisterPrivateKey(&vncHooksScreenKeyRec, PRIVATE_SCREEN,\n      sizeof(vncHooksScreenRec))) {\n    ErrorF(\"vncHooksInit: Allocation of vncHooksScreen failed\\n\");\n    return FALSE;\n  }\n  if (!dixRegisterPrivateKey(&vncHooksGCKeyRec, PRIVATE_GC,\n      sizeof(vncHooksGCRec))) {\n    ErrorF(\"vncHooksInit: Allocation of vncHooksGCRec failed\\n\");\n    return FALSE;\n  }\n\n  vncHooksScreen = vncHooksScreenPrivate(pScreen);\n\n  vncHooksScreen->ignoreHooks = 0;\n\n  wrap(vncHooksScreen, pScreen, CloseScreen, vncHooksCloseScreen);\n  wrap(vncHooksScreen, pScreen, CreateGC, vncHooksCreateGC);\n  wrap(vncHooksScreen, pScreen, CopyWindow, vncHooksCopyWindow);\n  wrap(vncHooksScreen, pScreen, ClearToBackground, vncHooksClearToBackground);\n  wrap(vncHooksScreen, pScreen, CursorWarpedTo, vncHooksCursorWarpedTo);\n  wrap(vncHooksScreen, pScreen, BlockHandler, vncHooksBlockHandler);\n\n  ps = GetPictureScreenIfSet(pScreen);\n  if (ps) {\n    wrap(vncHooksScreen, ps, Composite, vncHooksComposite);\n    wrap(vncHooksScreen, ps, Glyphs, vncHooksGlyphs);\n    wrap(vncHooksScreen, ps, CompositeRects, vncHooksCompositeRects);\n    wrap(vncHooksScreen, ps, Trapezoids, vncHooksTrapezoids);\n    wrap(vncHooksScreen, ps, Triangles, vncHooksTriangles);\n    wrap(vncHooksScreen, ps, TriStrip, vncHooksTriStrip);\n    wrap(vncHooksScreen, ps, TriFan, vncHooksTriFan);\n  }\n\n  rp = rrGetScrPriv(pScreen);\n  if (rp) {\n    /* Some RandR callbacks are optional */\n    if (rp->rrSetConfig)\n      wrap(vncHooksScreen, rp, rrSetConfig, vncHooksRandRSetConfig);\n    if (rp->rrScreenSetSize)\n      wrap(vncHooksScreen, rp, rrScreenSetSize, vncHooksRandRScreenSetSize);\n    if (rp->rrCrtcSet)\n      wrap(vncHooksScreen, rp, rrCrtcSet, vncHooksRandRCrtcSet);\n  }\n\n  miPointerPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);\n  if (miPointerPriv) {\n    wrap(vncHooksScreen, miPointerPriv, spriteFuncs, &vncHooksSpriteFuncs);\n  }\n\n  return TRUE;\n}\n\n/////////////////////////////////////////////////////////////////////////////\n// vncGetScreenImage() grabs a chunk of data from the main screen into the\n// provided buffer. It lives here rather than in XorgGlue.c because it\n// temporarily pauses the hooks.\n\nvoid vncGetScreenImage(int scrIdx, int x, int y, int width, int height,\n                       char *buffer, int strideBytes)\n{\n  ScreenPtr pScreen = screenInfo.screens[scrIdx];\n  vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);\n\n  int i;\n\n  vncHooksScreen->ignoreHooks++;\n\n  // We do one line at a time since GetImage() cannot handle stride\n  for (i = y; i < y + height; i++) {\n    DrawablePtr pDrawable;\n    pDrawable = (DrawablePtr) pScreen->root;\n\n    (*pScreen->GetImage) (pDrawable, x, i, width, 1,\n                          ZPixmap, (unsigned long)~0L, buffer);\n\n    buffer += strideBytes;\n  }\n\n  vncHooksScreen->ignoreHooks--;\n}\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Helper functions\n//\n\nstatic inline void add_changed(ScreenPtr pScreen, RegionPtr reg)\n{\n  vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);\n  if (vncHooksScreen->ignoreHooks)\n    return;\n  if (RegionNil(reg))\n    return;\n  vncAddChanged(pScreen->myNum,\n                RegionNumRects(reg),\n                (const struct UpdateRect*)RegionRects(reg));\n}\n\nstatic inline void add_copied(ScreenPtr pScreen, RegionPtr dst,\n                              int dx, int dy)\n{\n  vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);\n  if (vncHooksScreen->ignoreHooks)\n    return;\n  if (RegionNil(dst))\n    return;\n  vncAddCopied(pScreen->myNum,\n               RegionNumRects(dst),\n               (const struct UpdateRect*)RegionRects(dst), dx, dy);\n}\n\nstatic inline Bool is_visible(DrawablePtr drawable)\n{\n  PixmapPtr scrPixmap;\n\n  scrPixmap = drawable->pScreen->GetScreenPixmap(drawable->pScreen);\n\n  if (drawable->type == DRAWABLE_WINDOW) {\n    WindowPtr window;\n    PixmapPtr winPixmap;\n\n    window = (WindowPtr)drawable;\n    winPixmap = drawable->pScreen->GetWindowPixmap(window);\n\n    if (!window->viewable)\n      return FALSE;\n\n    if (winPixmap != scrPixmap)\n      return FALSE;\n\n    return TRUE;\n  }\n\n  if (drawable != &scrPixmap->drawable)\n    return FALSE;\n\n  return TRUE;\n}\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// screen functions\n//\n\n// Unwrap and rewrap helpers\n\n#define SCREEN_PROLOGUE(scrn,field)                                       \\\n  ScreenPtr pScreen = scrn;                                               \\\n  vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);      \\\n  unwrap(vncHooksScreen, pScreen, field);                                 \\\n  DBGPRINT((stderr,\"vncHooks\" #field \" called\\n\"));\n\n#define SCREEN_EPILOGUE(field)                                            \\\n  wrap(vncHooksScreen, pScreen, field, vncHooks##field);                  \\\n\n\n// CloseScreen - unwrap the screen functions and call the original CloseScreen\n// function\n\nstatic Bool vncHooksCloseScreen(ScreenPtr pScreen_)\n{\n  PictureScreenPtr ps;\n  rrScrPrivPtr rp;\n  miPointerScreenPtr miPointerPriv;\n\n  SCREEN_PROLOGUE(pScreen_, CloseScreen);\n\n  unwrap(vncHooksScreen, pScreen, CreateGC);\n  unwrap(vncHooksScreen, pScreen, CopyWindow);\n  unwrap(vncHooksScreen, pScreen, ClearToBackground);\n  unwrap(vncHooksScreen, pScreen, BlockHandler);\n\n  ps = GetPictureScreenIfSet(pScreen);\n  if (ps) {\n    unwrap(vncHooksScreen, ps, Composite);\n    unwrap(vncHooksScreen, ps, Glyphs);\n    unwrap(vncHooksScreen, ps, CompositeRects);\n    unwrap(vncHooksScreen, ps, Trapezoids);\n    unwrap(vncHooksScreen, ps, Triangles);\n    unwrap(vncHooksScreen, ps, TriStrip);\n    unwrap(vncHooksScreen, ps, TriFan);\n  }\n\n  rp = rrGetScrPriv(pScreen);\n  if (rp) {\n    unwrap(vncHooksScreen, rp, rrSetConfig);\n    unwrap(vncHooksScreen, rp, rrScreenSetSize);\n    unwrap(vncHooksScreen, rp, rrCrtcSet);\n  }\n\n  miPointerPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);\n  if (miPointerPriv) {\n    unwrap(vncHooksScreen, miPointerPriv, spriteFuncs);\n  }\n\n  DBGPRINT((stderr,\"vncHooksCloseScreen: Unwrapped screen functions\\n\"));\n\n  return (*pScreen->CloseScreen)(pScreen);\n}\n\n// CreateGC - wrap the \"GC funcs\"\n\nstatic Bool vncHooksCreateGC(GCPtr pGC)\n{\n  vncHooksGCPtr vncHooksGC = vncHooksGCPrivate(pGC);\n  Bool ret;\n\n  SCREEN_PROLOGUE(pGC->pScreen, CreateGC);\n\n  ret = (*pScreen->CreateGC) (pGC);\n\n  vncHooksGC->ops = NULL;\n  vncHooksGC->funcs = pGC->funcs;\n  pGC->funcs = &vncHooksGCFuncs;\n\n  SCREEN_EPILOGUE(CreateGC);\n\n  return ret;\n}\n\n// CopyWindow - destination of the copy is the old region, clipped by\n// borderClip, translated by the delta.  This call only does the copy - it\n// doesn't affect any other bits.\n\nstatic void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,\n                               RegionPtr pOldRegion)\n{\n  int dx, dy;\n  RegionRec copied;\n\n  SCREEN_PROLOGUE(pWin->drawable.pScreen, CopyWindow);\n\n  if (is_visible(&pWin->drawable)) {\n    BoxRec screen_box;\n    RegionRec screen_rgn;\n\n    RegionNull(&copied);\n    RegionCopy(&copied, pOldRegion);\n\n    screen_box.x1 = 0;\n    screen_box.y1 = 0;\n    screen_box.x2 = pScreen->width;\n    screen_box.y2 = pScreen->height;\n\n    RegionInitBoxes(&screen_rgn, &screen_box, 1);\n\n    dx = pWin->drawable.x - ptOldOrg.x;\n    dy = pWin->drawable.y - ptOldOrg.y;\n\n    // RFB tracks copies in terms of destination rectangle, not source.\n    // We also need to copy with changes to the Window's clipping region.\n    // Finally, make sure we don't get copies to or from regions outside\n    // the framebuffer.\n    RegionIntersect(&copied, &copied, &screen_rgn);\n    RegionTranslate(&copied, dx, dy);\n    RegionIntersect(&copied, &copied, &screen_rgn);\n    RegionIntersect(&copied, &copied, &pWin->borderClip);\n\n    RegionUninit(&screen_rgn);\n  } else {\n    RegionNull(&copied);\n    dx = dy = 0;\n  }\n\n  (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);\n\n  add_copied(pScreen, &copied, dx, dy);\n\n  RegionUninit(&copied);\n\n  SCREEN_EPILOGUE(CopyWindow);\n}\n\n// ClearToBackground - changed region is the given rectangle, clipped by\n// clipList, but only if generateExposures is false.\n\nstatic void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,\n                                      int h, Bool generateExposures)\n{\n  RegionRec reg;\n\n  SCREEN_PROLOGUE(pWin->drawable.pScreen, ClearToBackground);\n\n  if (is_visible(&pWin->drawable)) {\n    BoxRec box;\n\n    box.x1 = x + pWin->drawable.x;\n    box.y1 = y + pWin->drawable.y;\n    box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width);\n    box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height);\n\n    RegionInitBoxes(&reg, &box, 1);\n    RegionIntersect(&reg, &reg, &pWin->clipList);\n  } else {\n    RegionNull(&reg);\n  }\n\n  (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);\n\n  if (!generateExposures) {\n    add_changed(pScreen, &reg);\n  }\n\n  RegionUninit(&reg);\n\n  SCREEN_EPILOGUE(ClearToBackground);\n}\n\n// CursorWarpedTo - notify that the cursor was warped\n\nstatic void vncHooksCursorWarpedTo(DeviceIntPtr pDev,\n                                   ScreenPtr pScreen_, ClientPtr pClient,\n                                   WindowPtr pWindow, SpritePtr pSprite,\n                                   int x, int y)\n{\n  SCREEN_PROLOGUE(pScreen_, CursorWarpedTo);\n\n  if (pScreen->CursorWarpedTo)\n    (*pScreen->CursorWarpedTo) (pDev, pScreen_, pClient, pWindow, pSprite, x, y);\n\n  vncSetCursorPos(pScreen->myNum, x, y);\n\n  SCREEN_EPILOGUE(CursorWarpedTo);\n}\n\n// BlockHandler - ignore any changes during the block handler - it's likely\n// these are just drawing the cursor.\n\nstatic void vncHooksBlockHandler(ScreenPtr pScreen_, void * pTimeout)\n{\n  SCREEN_PROLOGUE(pScreen_, BlockHandler);\n\n  vncHooksScreen->ignoreHooks++;\n\n  (*pScreen->BlockHandler) (pScreen, pTimeout);\n\n  vncHooksScreen->ignoreHooks--;\n\n  SCREEN_EPILOGUE(BlockHandler);\n}\n\n// Unwrap and rewrap helpers\n\n#define RENDER_PROLOGUE(scrn,field)                                       \\\n  ScreenPtr pScreen = scrn;                                               \\\n  PictureScreenPtr ps = GetPictureScreen(pScreen);                        \\\n  vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);      \\\n  unwrap(vncHooksScreen, ps, field);                                      \\\n  DBGPRINT((stderr,\"vncHooks\" #field \" called\\n\"));\n\n#define RENDER_EPILOGUE(field)                                            \\\n  wrap(vncHooksScreen, ps, field, vncHooks##field);                       \\\n\n// Composite - The core of XRENDER\n\nstatic void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,\n\t\t       PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, \n\t\t       INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)\n{\n  RegionRec changed;\n\n  RENDER_PROLOGUE(pDst->pDrawable->pScreen, Composite);\n\n  if (is_visible(pDst->pDrawable)) {\n    BoxRec box;\n    RegionRec fbreg;\n\n    box.x1 = max(pDst->pDrawable->x + xDst, 0);\n    box.y1 = max(pDst->pDrawable->y + yDst, 0);\n    box.x2 = box.x1 + width;\n    box.y2 = box.y1 + height;\n    RegionInitBoxes(&changed, &box, 1);\n\n    box.x1 = 0;\n    box.y1 = 0;\n    box.x2 = pScreen->width;\n    box.y2 = pScreen->height;\n    RegionInitBoxes(&fbreg, &box, 1);\n\n    RegionIntersect(&changed, &changed, &fbreg);\n\n    RegionUninit(&fbreg);\n  } else {\n    RegionNull(&changed);\n  }\n\n\n  (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,\n\t\t   xMask, yMask, xDst, yDst, width, height);\n\n  add_changed(pScreen, &changed);\n\n  RegionUninit(&changed);\n\n  RENDER_EPILOGUE(Composite);\n}\n\nstatic RegionPtr\nGlyphsToRegion(ScreenPtr pScreen, int nlist, GlyphListPtr list, GlyphPtr *glyphs)\n{\n  int n;\n  GlyphPtr glyph;\n  int x, y;\n\n  int nrects = nlist;\n  xRectangle rects[nrects];\n  xRectanglePtr rect;\n\n  x = 0;\n  y = 0;\n  rect = &rects[0];\n  while (nlist--) {\n    int left, right, top, bottom;\n\n    x += list->xOff;\n    y += list->yOff;\n    n = list->len;\n    list++;\n\n    left = INT_MAX;\n    top = INT_MAX;\n    right = -INT_MAX;\n    bottom = -INT_MAX;\n    while (n--) {\n      int gx, gy, gw, gh;\n\n      glyph = *glyphs++;\n      gx = x - glyph->info.x;\n      gy = y - glyph->info.y;\n      gw = glyph->info.width;\n      gh = glyph->info.height;\n      x += glyph->info.xOff;\n      y += glyph->info.yOff;\n\n      if (gx < left)\n        left = gx;\n      if (gy < top)\n        top = gy;\n      if (gx + gw > right)\n        right = gx + gw;\n      if (gy + gh > bottom)\n        bottom = gy + gh;\n    }\n\n    rect->x = left;\n    rect->y = top;\n    if ((right > left) && (bottom > top)) {\n      rect->width = right - left;\n      rect->height = bottom - top;\n    } else {\n      rect->width = 0;\n      rect->height = 0;\n    }\n    rect++;\n  }\n\n  return RECTS_TO_REGION(pScreen, nrects, rects, CT_NONE);\n}\n\n// Glyphs - Glyph specific version of Composite (caches and whatnot)\n\nstatic void vncHooksGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n           PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists, \n           GlyphListPtr lists, GlyphPtr * glyphs)\n{\n  RegionPtr changed;\n\n  RENDER_PROLOGUE(pDst->pDrawable->pScreen, Glyphs);\n\n  if (is_visible(pDst->pDrawable)) {\n    BoxRec fbbox;\n    RegionRec fbreg;\n\n    changed = GlyphsToRegion(pScreen, nlists, lists, glyphs);\n    RegionTranslate(changed,\n                     pDst->pDrawable->x, pDst->pDrawable->y);\n\n    fbbox.x1 = 0;\n    fbbox.y1 = 0;\n    fbbox.x2 = pScreen->width;\n    fbbox.y2 = pScreen->height;\n    RegionInitBoxes(&fbreg, &fbbox, 1);\n\n    RegionIntersect(changed, changed, &fbreg);\n\n    RegionUninit(&fbreg);\n  } else {\n    changed = RegionCreate(NullBox, 0);\n  }\n\n  (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlists, lists, glyphs);\n\n  add_changed(pScreen, changed);\n\n  RegionDestroy(changed);\n\n  RENDER_EPILOGUE(Glyphs);\n}\n\nstatic void vncHooksCompositeRects(CARD8 op, PicturePtr pDst,\n            xRenderColor * color, int nRect, xRectangle *rects)\n{\n  RegionPtr changed;\n\n  RENDER_PROLOGUE(pDst->pDrawable->pScreen, CompositeRects);\n\n  if (is_visible(pDst->pDrawable)) {\n    changed = RECTS_TO_REGION(pScreen, nRect, rects, CT_NONE);\n  } else {\n    changed = RegionCreate(NullBox, 0);\n  }\n\n  (*ps->CompositeRects)(op, pDst, color, nRect, rects);\n\n  add_changed(pScreen, changed);\n\n  RegionDestroy(changed);\n\n  RENDER_EPILOGUE(CompositeRects);\n}\n\nstatic inline short FixedToShort(xFixed fixed)\n{\n  return (fixed + 0x8000) >> 16;\n}\n\nstatic void vncHooksTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int ntrap, xTrapezoid * traps)\n{\n  RegionRec changed;\n\n  RENDER_PROLOGUE(pDst->pDrawable->pScreen, Trapezoids);\n\n  if (is_visible(pDst->pDrawable)) {\n    BoxRec box;\n    RegionRec fbreg;\n\n    // FIXME: We do a very crude bounding box around everything.\n    //        Might not be worth optimizing since this call is rarely\n    //        used.\n    box.x1 = SHRT_MAX;\n    box.y1 = SHRT_MAX;\n    box.x2 = 0;\n    box.y2 = 0;\n    for (int i = 0;i < ntrap;i++) {\n      if (FixedToShort(traps[i].left.p1.x) < box.x1)\n        box.x1 = FixedToShort(traps[i].left.p1.x);\n      if (FixedToShort(traps[i].left.p2.x) < box.x1)\n        box.x1 = FixedToShort(traps[i].left.p2.x);\n      if (FixedToShort(traps[i].top) < box.y1)\n        box.y1 = FixedToShort(traps[i].top);\n      if (FixedToShort(traps[i].right.p1.x) > box.x2)\n        box.x2 = FixedToShort(traps[i].right.p1.x);\n      if (FixedToShort(traps[i].right.p2.x) > box.x2)\n        box.x2 = FixedToShort(traps[i].right.p2.x);\n      if (FixedToShort(traps[i].bottom) > box.y2)\n        box.y2 = FixedToShort(traps[i].bottom);\n    }\n\n    box.x1 += pDst->pDrawable->x;\n    box.y1 += pDst->pDrawable->y;\n    box.x2 += pDst->pDrawable->x;\n    box.y2 += pDst->pDrawable->y;\n    RegionInitBoxes(&changed, &box, 1);\n\n    box.x1 = 0;\n    box.y1 = 0;\n    box.x2 = pScreen->width;\n    box.y2 = pScreen->height;\n    RegionInitBoxes(&fbreg, &box, 1);\n\n    RegionIntersect(&changed, &changed, &fbreg);\n\n    RegionUninit(&fbreg);\n  } else {\n    RegionNull(&changed);\n  }\n\n  (*ps->Trapezoids)(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);\n\n  add_changed(pScreen, &changed);\n\n  RegionUninit(&changed);\n\n  RENDER_EPILOGUE(Trapezoids);\n}\n\nstatic void vncHooksTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int ntri, xTriangle * tris)\n{\n  RegionRec changed;\n\n  RENDER_PROLOGUE(pDst->pDrawable->pScreen, Triangles);\n\n  if (is_visible(pDst->pDrawable)) {\n    BoxRec box;\n    RegionRec fbreg;\n\n    // FIXME: We do a very crude bounding box around everything.\n    //        Might not be worth optimizing since this call is rarely\n    //        used.\n    box.x1 = SHRT_MAX;\n    box.y1 = SHRT_MAX;\n    box.x2 = 0;\n    box.y2 = 0;\n    for (int i = 0;i < ntri;i++) {\n      xFixed left, right, top, bottom;\n\n      left = min(min(tris[i].p1.x, tris[i].p2.x), tris[i].p3.x);\n      right = max(max(tris[i].p1.x, tris[i].p2.x), tris[i].p3.x);\n      top = min(min(tris[i].p1.y, tris[i].p2.y), tris[i].p3.y);\n      bottom = max(max(tris[i].p1.y, tris[i].p2.y), tris[i].p3.y);\n\n      if (FixedToShort(left) < box.x1)\n        box.x1 = FixedToShort(left);\n      if (FixedToShort(top) < box.y1)\n        box.y1 = FixedToShort(top);\n      if (FixedToShort(right) > box.x2)\n        box.x2 = FixedToShort(right);\n      if (FixedToShort(bottom) > box.y2)\n        box.y2 = FixedToShort(bottom);\n    }\n\n    box.x1 += pDst->pDrawable->x;\n    box.y1 += pDst->pDrawable->y;\n    box.x2 += pDst->pDrawable->x;\n    box.y2 += pDst->pDrawable->y;\n    RegionInitBoxes(&changed, &box, 1);\n\n    box.x1 = 0;\n    box.y1 = 0;\n    box.x2 = pScreen->width;\n    box.y2 = pScreen->height;\n    RegionInitBoxes(&fbreg, &box, 1);\n\n    RegionIntersect(&changed, &changed, &fbreg);\n\n    RegionUninit(&fbreg);\n  } else {\n    RegionNull(&changed);\n  }\n\n  (*ps->Triangles)(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);\n\n  add_changed(pScreen, &changed);\n\n  RegionUninit(&changed);\n\n  RENDER_EPILOGUE(Triangles);\n}\n\nstatic void vncHooksTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int npoint, xPointFixed * points)\n{\n  RegionRec changed;\n\n  RENDER_PROLOGUE(pDst->pDrawable->pScreen, TriStrip);\n\n  if (is_visible(pDst->pDrawable)) {\n    BoxRec box;\n    RegionRec fbreg;\n\n    // FIXME: We do a very crude bounding box around everything.\n    //        Might not be worth optimizing since this call is rarely\n    //        used.\n    box.x1 = SHRT_MAX;\n    box.y1 = SHRT_MAX;\n    box.x2 = 0;\n    box.y2 = 0;\n    for (int i = 0;i < npoint;i++) {\n      if (FixedToShort(points[i].x) < box.x1)\n        box.x1 = FixedToShort(points[i].x);\n      if (FixedToShort(points[i].y) < box.y1)\n        box.y1 = FixedToShort(points[i].y);\n      if (FixedToShort(points[i].x) > box.x2)\n        box.x2 = FixedToShort(points[i].x);\n      if (FixedToShort(points[i].y) > box.y2)\n        box.y2 = FixedToShort(points[i].y);\n    }\n\n    box.x1 += pDst->pDrawable->x;\n    box.y1 += pDst->pDrawable->y;\n    box.x2 += pDst->pDrawable->x;\n    box.y2 += pDst->pDrawable->y;\n    RegionInitBoxes(&changed, &box, 1);\n\n    box.x1 = 0;\n    box.y1 = 0;\n    box.x2 = pScreen->width;\n    box.y2 = pScreen->height;\n    RegionInitBoxes(&fbreg, &box, 1);\n\n    RegionIntersect(&changed, &changed, &fbreg);\n\n    RegionUninit(&fbreg);\n  } else {\n    RegionNull(&changed);\n  }\n\n  (*ps->TriStrip)(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, points);\n\n  add_changed(pScreen, &changed);\n\n  RegionUninit(&changed);\n\n  RENDER_EPILOGUE(TriStrip);\n}\n\nstatic void vncHooksTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,\n            PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,\n            int npoint, xPointFixed * points)\n{\n  RegionRec changed;\n\n  RENDER_PROLOGUE(pDst->pDrawable->pScreen, TriFan);\n\n  if (is_visible(pDst->pDrawable)) {\n    BoxRec box;\n    RegionRec fbreg;\n\n    // FIXME: We do a very crude bounding box around everything.\n    //        Might not be worth optimizing since this call is rarely\n    //        used.\n    box.x1 = SHRT_MAX;\n    box.y1 = SHRT_MAX;\n    box.x2 = 0;\n    box.y2 = 0;\n    for (int i = 0;i < npoint;i++) {\n      if (FixedToShort(points[i].x) < box.x1)\n        box.x1 = FixedToShort(points[i].x);\n      if (FixedToShort(points[i].y) < box.y1)\n        box.y1 = FixedToShort(points[i].y);\n      if (FixedToShort(points[i].x) > box.x2)\n        box.x2 = FixedToShort(points[i].x);\n      if (FixedToShort(points[i].y) > box.y2)\n        box.y2 = FixedToShort(points[i].y);\n    }\n\n    box.x1 += pDst->pDrawable->x;\n    box.y1 += pDst->pDrawable->y;\n    box.x2 += pDst->pDrawable->x;\n    box.y2 += pDst->pDrawable->y;\n    RegionInitBoxes(&changed, &box, 1);\n\n    box.x1 = 0;\n    box.y1 = 0;\n    box.x2 = pScreen->width;\n    box.y2 = pScreen->height;\n    RegionInitBoxes(&fbreg, &box, 1);\n\n    RegionIntersect(&changed, &changed, &fbreg);\n\n    RegionUninit(&fbreg);\n  } else {\n    RegionNull(&changed);\n  }\n\n  (*ps->TriFan)(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, points);\n\n  add_changed(pScreen, &changed);\n\n  RegionUninit(&changed);\n\n  RENDER_EPILOGUE(TriFan);\n}\n\n// Unwrap and rewrap helpers\n\n#define RANDR_PROLOGUE(field)                                             \\\n  rrScrPrivPtr rp = rrGetScrPriv(pScreen);                                \\\n  vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);      \\\n  unwrap(vncHooksScreen, rp, rr##field);                                  \\\n  DBGPRINT((stderr,\"vncHooksRandR\" #field \" called\\n\"));\n\n#define RANDR_EPILOGUE(field)                                             \\\n  wrap(vncHooksScreen, rp, rr##field, vncHooksRandR##field);              \\\n\n// RandRSetConfig - follow any framebuffer changes\n\nstatic Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation,\n                                   int rate, RRScreenSizePtr pSize)\n{\n  Bool ret;\n\n  RANDR_PROLOGUE(SetConfig);\n\n  vncPreScreenResize(pScreen->myNum);\n  ret = (*rp->rrSetConfig)(pScreen, rotation, rate, pSize);\n  vncPostScreenResize(pScreen->myNum, ret, pScreen->width, pScreen->height);\n\n  RANDR_EPILOGUE(SetConfig);\n\n  if (!ret)\n    return FALSE;\n\n  return TRUE;\n}\n\nstatic Bool vncHooksRandRScreenSetSize(ScreenPtr pScreen,\n                                       CARD16 width, CARD16 height,\n                                       CARD32 mmWidth, CARD32 mmHeight)\n{\n  Bool ret;\n\n  RANDR_PROLOGUE(ScreenSetSize);\n\n  vncPreScreenResize(pScreen->myNum);\n  ret = (*rp->rrScreenSetSize)(pScreen, width, height, mmWidth, mmHeight);\n  vncPostScreenResize(pScreen->myNum, ret, pScreen->width, pScreen->height);\n\n  RANDR_EPILOGUE(ScreenSetSize);\n\n  if (!ret)\n    return FALSE;\n\n  return TRUE;\n}\n\nstatic Bool vncHooksRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc,\n                                 RRModePtr mode, int x, int y,\n                                 Rotation rotation, int num_outputs,\n                                 RROutputPtr *outputs)\n{\n  Bool ret;\n\n  RANDR_PROLOGUE(CrtcSet);\n\n  ret = (*rp->rrCrtcSet)(pScreen, crtc, mode, x, y, rotation,\n                         num_outputs, outputs);\n\n  RANDR_EPILOGUE(CrtcSet);\n\n  if (!ret)\n    return FALSE;\n\n  vncRefreshScreenLayout(pScreen->myNum);\n\n  return TRUE;\n}\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Sprite functions\n//\n\n// Unwrap and rewrap helpers\n\n#define SPRITE_PROLOGUE(field)                                            \\\n  miPointerScreenPtr miPointerPriv =                                      \\\n    dixLookupPrivate(&screen->devPrivates, miPointerScreenKey);           \\\n  vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(screen);       \\\n  unwrap(vncHooksScreen, miPointerPriv, spriteFuncs);                     \\\n  DBGPRINT((stderr,\"vncHooks\" #field \" called\\n\"));\n\n#define SPRITE_EPILOGUE(field)                                            \\\n  wrap(vncHooksScreen, miPointerPriv, spriteFuncs, &vncHooksSpriteFuncs); \\\n\nstatic Bool vncHooksRealizeCursor(DeviceIntPtr dev, ScreenPtr screen,\n                                  CursorPtr cursor)\n{\n  Bool ret;\n  SPRITE_PROLOGUE(RealizeCursor);\n  ret = (*miPointerPriv->spriteFuncs->RealizeCursor)(dev, screen, cursor);\n  SPRITE_EPILOGUE();\n  return ret;\n}\n\nstatic Bool vncHooksUnrealizeCursor(DeviceIntPtr dev, ScreenPtr screen,\n                                    CursorPtr cursor)\n{\n  Bool ret;\n  SPRITE_PROLOGUE(UnrealizeCursor);\n  ret = (*miPointerPriv->spriteFuncs->UnrealizeCursor)(dev, screen, cursor);\n  SPRITE_EPILOGUE();\n  return ret;\n}\n\nstatic void vncHooksSetCursor(DeviceIntPtr dev, ScreenPtr screen,\n                              CursorPtr cursor, int x, int y)\n{\n  SPRITE_PROLOGUE(SetCursor);\n\n  (*miPointerPriv->spriteFuncs->SetCursor)(dev, screen, cursor, x, y);\n\n  if (cursor == NullCursor) {\n    vncSetCursorSprite(0, 0, 0, 0, NULL);\n  } else {\n    int width, height;\n    int hotX, hotY;\n\n    unsigned char *rgbaData;\n\n    width = cursor->bits->width;\n    height = cursor->bits->height;\n\n    hotX = cursor->bits->xhot;\n    hotY = cursor->bits->yhot;\n\n    rgbaData = malloc(width * height * 4);\n    if (rgbaData == NULL)\n      goto out;\n\n    if (cursor->bits->argb) {\n      unsigned char *out;\n      CARD32 *in;\n      int i;\n\n      in = cursor->bits->argb;\n      out = rgbaData;\n      for (i = 0; i < width*height; i++) {\n        out[0] = (*in >> 16) & 0xff;\n        out[1] = (*in >>  8) & 0xff;\n        out[2] = (*in >>  0) & 0xff;\n        out[3] = (*in >> 24) & 0xff;\n        out += 4;\n        in++;\n      }\n    } else {\n      unsigned char *out;\n      int xMaskBytesPerRow;\n\n      xMaskBytesPerRow = BitmapBytePad(width);\n\n      out = rgbaData;\n      for (int sy = 0; sy < height; sy++) {\n        for (int sx = 0; sx < width; sx++) {\n          int byte = sy * xMaskBytesPerRow + sx / 8;\n#if (BITMAP_BIT_ORDER == MSBFirst)\n          int bit = 7 - sx % 8;\n#else\n          int bit = sx % 8;\n#endif\n\n          if (cursor->bits->source[byte] & (1 << bit)) {\n            out[0] = cursor->foreRed;\n            out[1] = cursor->foreGreen;\n            out[2] = cursor->foreBlue;\n          } else {\n            out[0] = cursor->backRed;\n            out[1] = cursor->backGreen;\n            out[2] = cursor->backBlue;\n          }\n\n          if (cursor->bits->mask[byte] & (1 << bit))\n            out[3] = 0xff;\n          else\n            out[3] = 0x00;\n\n          out += 4;\n        }\n      }\n    }\n\n    vncSetCursorSprite(width, height, hotX, hotY, rgbaData);\n\n    free(rgbaData);\n  }\n\nout:\n  SPRITE_EPILOGUE();\n}\n\nstatic void vncHooksMoveCursor(DeviceIntPtr dev, ScreenPtr screen,\n                               int x, int y)\n{\n  SPRITE_PROLOGUE(MoveCursor);\n  (*miPointerPriv->spriteFuncs->MoveCursor)(dev, screen, x, y);\n  SPRITE_EPILOGUE();\n}\n\nstatic Bool vncHooksDeviceCursorInitialize(DeviceIntPtr dev,\n                                           ScreenPtr screen)\n{\n  Bool ret;\n  SPRITE_PROLOGUE(DeviceCursorInitialize);\n  ret = (*miPointerPriv->spriteFuncs->DeviceCursorInitialize)(dev, screen);\n  SPRITE_EPILOGUE();\n  return ret;\n}\n\nstatic void vncHooksDeviceCursorCleanup(DeviceIntPtr dev,\n                                        ScreenPtr screen)\n{\n  SPRITE_PROLOGUE(DeviceCursorCleanup);\n  (*miPointerPriv->spriteFuncs->DeviceCursorCleanup)(dev, screen);\n  SPRITE_EPILOGUE();\n}\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// GC \"funcs\"\n//\n\n// Unwrap and rewrap helpers\n\n#define GC_FUNC_PROLOGUE(pGC, name)\\\n    vncHooksGCPtr pGCPriv = vncHooksGCPrivate(pGC);\\\n    unwrap(pGCPriv, pGC, funcs);\\\n    if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)\\\n    DBGPRINT((stderr,\"vncHooks\" #name \" called\\n\"))\n\n#define GC_FUNC_EPILOGUE(pGC)\\\n    wrap(pGCPriv, pGC, funcs, &vncHooksGCFuncs);\\\n    if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &vncHooksGCOps)\n\n// ValidateGC - wrap the \"ops\" if the drawable is on screen\n\nstatic void vncHooksValidateGC(GCPtr pGC, unsigned long changes,\n                               DrawablePtr pDrawable)\n{\n  GC_FUNC_PROLOGUE(pGC, ValidateGC);\n  (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);\n  if (is_visible(pDrawable)) {\n    pGCPriv->ops = pGC->ops;\n    DBGPRINT((stderr,\"vncHooksValidateGC: Wrapped GC ops\\n\"));\n  } else {\n    pGCPriv->ops = NULL;\n  }\n  GC_FUNC_EPILOGUE(pGC);\n}\n\n// Other GC funcs - just unwrap and call on\n\nstatic void vncHooksChangeGC(GCPtr pGC, unsigned long mask) {\n  GC_FUNC_PROLOGUE(pGC, ChangeGC);\n  (*pGC->funcs->ChangeGC) (pGC, mask);\n  GC_FUNC_EPILOGUE(pGC);\n}\nstatic void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst) {\n  GC_FUNC_PROLOGUE(dst, CopyGC);\n  (*dst->funcs->CopyGC) (src, mask, dst);\n  GC_FUNC_EPILOGUE(dst);\n}\nstatic void vncHooksDestroyGC(GCPtr pGC) {\n  GC_FUNC_PROLOGUE(pGC, DestroyGC);\n  (*pGC->funcs->DestroyGC) (pGC);\n  GC_FUNC_EPILOGUE(pGC);\n}\nstatic void vncHooksChangeClip(GCPtr pGC, int type, void * pValue, int nrects)\n{\n  GC_FUNC_PROLOGUE(pGC, ChangeClip);\n  (*pGC->funcs->ChangeClip) (pGC, type, pValue, nrects);\n  GC_FUNC_EPILOGUE(pGC);\n}\nstatic void vncHooksDestroyClip(GCPtr pGC) {\n  GC_FUNC_PROLOGUE(pGC, DestroyClip);\n  (*pGC->funcs->DestroyClip) (pGC);\n  GC_FUNC_EPILOGUE(pGC);\n}\nstatic void vncHooksCopyClip(GCPtr dst, GCPtr src) {\n  GC_FUNC_PROLOGUE(dst, CopyClip);\n  (*dst->funcs->CopyClip) (dst, src);\n  GC_FUNC_EPILOGUE(dst);\n}\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// GC \"ops\"\n//\n\n// Unwrap and rewrap helpers\n\n#define GC_OP_PROLOGUE(pGC, name)\\\n    vncHooksGCPtr pGCPriv = vncHooksGCPrivate(pGC);\\\n    const GCFuncs *oldFuncs = pGC->funcs;\\\n    unwrap(pGCPriv, pGC, funcs);\\\n    unwrap(pGCPriv, pGC, ops);\\\n    DBGPRINT((stderr,\"vncHooks\" #name \" called\\n\"))\n\n#define GC_OP_EPILOGUE(pGC)\\\n    wrap(pGCPriv, pGC, funcs, oldFuncs); \\\n    wrap(pGCPriv, pGC, ops, &vncHooksGCOps)\n\n// FillSpans - assume the entire clip region is damaged. This is pessimistic,\n// but I believe this function is rarely used so it doesn't matter.\n\nstatic void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,\n                              DDXPointPtr pptInit, int *pwidthInit,\n                              int fSorted)\n{\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, FillSpans);\n\n  RegionNull(&reg);\n  RegionCopy(&reg, pGC->pCompositeClip);\n\n  if (pDrawable->type == DRAWABLE_WINDOW)\n    RegionIntersect(&reg, &reg, &((WindowPtr)pDrawable)->borderClip);\n\n  (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\n  GC_OP_EPILOGUE(pGC);\n}\n\n// SetSpans - assume the entire clip region is damaged.  This is pessimistic,\n// but I believe this function is rarely used so it doesn't matter.\n\nstatic void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,\n                             DDXPointPtr ppt, int *pwidth, int nspans,\n                             int fSorted)\n{\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, SetSpans);\n\n  RegionNull(&reg);\n  RegionCopy(&reg, pGC->pCompositeClip);\n\n  if (pDrawable->type == DRAWABLE_WINDOW)\n    RegionIntersect(&reg, &reg, &((WindowPtr)pDrawable)->borderClip);\n\n  (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\n  GC_OP_EPILOGUE(pGC);\n}\n\n// PutImage - changed region is the given rectangle, clipped by pCompositeClip\n\nstatic void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,\n                             int x, int y, int w, int h, int leftPad,\n                             int format, char *pBits)\n{\n  BoxRec box;\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, PutImage);\n\n  box.x1 = x + pDrawable->x;\n  box.y1 = y + pDrawable->y;\n  box.x2 = box.x1 + w;\n  box.y2 = box.y1 + h;\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format,\n                         pBits);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\n  GC_OP_EPILOGUE(pGC);\n}\n\n// CopyArea - destination of the copy is the dest rectangle, clipped by\n// pCompositeClip.  Any parts of the destination which cannot be copied from\n// the source (could be all of it) go into the changed region.\n\nstatic RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,\n                                  GCPtr pGC, int srcx, int srcy, int w, int h,\n                                  int dstx, int dsty)\n{\n  RegionRec dst, src, changed;\n\n  RegionPtr ret;\n\n  GC_OP_PROLOGUE(pGC, CopyArea);\n\n  // Apparently this happens now and then...\n  if ((w == 0) || (h == 0))\n    RegionNull(&dst);\n  else {\n    BoxRec box;\n\n    box.x1 = dstx + pDst->x;\n    box.y1 = dsty + pDst->y;\n    box.x2 = box.x1 + w;\n    box.y2 = box.y1 + h;\n\n    RegionInitBoxes(&dst, &box, 1);\n  }\n\n  RegionIntersect(&dst, &dst, pGC->pCompositeClip);\n\n  // The source of the data has to be something that's on screen.\n  if (is_visible(pSrc)) {\n    BoxRec box;\n\n    box.x1 = srcx + pSrc->x;\n    box.y1 = srcy + pSrc->y;\n    box.x2 = box.x1 + w;\n    box.y2 = box.y1 + h;\n\n    RegionInitBoxes(&src, &box, 1);\n\n    if ((pSrc->type == DRAWABLE_WINDOW) &&\n        RegionNotEmpty(&((WindowPtr)pSrc)->clipList)) {\n      RegionIntersect(&src, &src, &((WindowPtr)pSrc)->clipList);\n    }\n\n    RegionTranslate(&src,\n                     dstx + pDst->x - srcx - pSrc->x,\n                     dsty + pDst->y - srcy - pSrc->y);\n  } else {\n    RegionNull(&src);\n  }\n\n  RegionNull(&changed);\n\n  RegionSubtract(&changed, &dst, &src);\n  RegionIntersect(&dst, &dst, &src);\n\n  ret = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);\n\n  add_copied(pGC->pScreen, &dst,\n             dstx + pDst->x - srcx - pSrc->x,\n             dsty + pDst->y - srcy - pSrc->y);\n\n  add_changed(pGC->pScreen, &changed);\n\n  RegionUninit(&dst);\n  RegionUninit(&src);\n  RegionUninit(&changed);\n\n  GC_OP_EPILOGUE(pGC);\n\n  return ret;\n}\n\n\n// CopyPlane - changed region is the destination rectangle, clipped by\n// pCompositeClip\n\nstatic RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,\n                                   GCPtr pGC, int srcx, int srcy, int w, int h,\n                                   int dstx, int dsty, unsigned long plane)\n{\n  BoxRec box;\n  RegionRec reg;\n\n  RegionPtr ret;\n\n  GC_OP_PROLOGUE(pGC, CopyPlane);\n\n  box.x1 = dstx + pDst->x;\n  box.y1 = dsty + pDst->y;\n  box.x2 = box.x1 + w;\n  box.y2 = box.y1 + h;\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  ret = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,\n                                dstx, dsty, plane);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\n  GC_OP_EPILOGUE(pGC);\n\n  return ret;\n}\n\n// PolyPoint - changed region is the bounding rect, clipped by pCompositeClip\n\nstatic void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,\n                              int npt, xPoint *pts)\n{\n  int minX, minY, maxX, maxY;\n  int i;\n\n  BoxRec box;\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, PolyPoint);\n\n  if (npt == 0) {\n    (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);\n    goto out;\n  }\n\n  minX = pts[0].x;\n  maxX = pts[0].x;\n  minY = pts[0].y;\n  maxY = pts[0].y;\n\n  if (mode == CoordModePrevious) {\n    int x = pts[0].x;\n    int y = pts[0].y;\n\n    for (i = 1; i < npt; i++) {\n      x += pts[i].x;\n      y += pts[i].y;\n      if (x < minX) minX = x;\n      if (x > maxX) maxX = x;\n      if (y < minY) minY = y;\n      if (y > maxY) maxY = y;\n    }\n  } else {\n    for (i = 1; i < npt; i++) {\n      if (pts[i].x < minX) minX = pts[i].x;\n      if (pts[i].x > maxX) maxX = pts[i].x;\n      if (pts[i].y < minY) minY = pts[i].y;\n      if (pts[i].y > maxY) maxY = pts[i].y;\n    }\n  }\n\n  box.x1 = minX + pDrawable->x;\n  box.y1 = minY + pDrawable->y;\n  box.x2 = maxX + 1 + pDrawable->x;\n  box.y2 = maxY + 1 + pDrawable->y;\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// Polylines - changed region is the union of the bounding rects of each line,\n// clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP lines,\n// just use the bounding rect of all the lines.\n\nstatic void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,\n                              int npt, DDXPointPtr ppts)\n{\n  int nRegRects;\n  xRectangle regRects[MAX_RECTS_PER_OP];\n\n  int lw;\n\n  RegionPtr reg;\n\n  GC_OP_PROLOGUE(pGC, Polylines);\n\n  if (npt == 0) {\n    (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);\n    goto out;\n  }\n\n  nRegRects = npt - 1;\n\n  lw = pGC->lineWidth;\n  if (lw == 0)\n    lw = 1;\n\n  if (npt == 1)\n  {\n    // a single point\n    nRegRects = 1;\n    regRects[0].x = pDrawable->x + ppts[0].x - lw;\n    regRects[0].y = pDrawable->y + ppts[0].y - lw;\n    regRects[0].width = 2*lw;\n    regRects[0].height = 2*lw;\n  }\n  else\n  {\n    /*\n     * mitered joins can project quite a way from\n     * the line end; the 11 degree miter limit limits\n     * this extension to lw / (2 * tan(11/2)), rounded up\n     * and converted to int yields 6 * lw\n     */\n\n    int extra;\n\n    int prevX, prevY, curX, curY;\n    int rectX1, rectY1, rectX2, rectY2;\n    int minX, minY, maxX, maxY;\n\n    int i;\n\n    extra = lw / 2;\n    if (pGC->joinStyle == JoinMiter) {\n      extra = 6 * lw;\n    }\n\n    prevX = ppts[0].x + pDrawable->x;\n    prevY = ppts[0].y + pDrawable->y;\n    minX = maxX = prevX;\n    minY = maxY = prevY;\n\n    for (i = 0; i < nRegRects; i++) {\n      if (mode == CoordModeOrigin) {\n        curX = pDrawable->x + ppts[i+1].x;\n        curY = pDrawable->y + ppts[i+1].y;\n      } else {\n        curX = prevX + ppts[i+1].x;\n        curY = prevY + ppts[i+1].y;\n      }\n\n      if (prevX > curX) {\n        rectX1 = curX - extra;\n        rectX2 = prevX + extra + 1;\n      } else {\n        rectX1 = prevX - extra;\n        rectX2 = curX + extra + 1;\n      }\n\n      if (prevY > curY) {\n        rectY1 = curY - extra;\n        rectY2 = prevY + extra + 1;\n      } else {\n        rectY1 = prevY - extra;\n        rectY2 = curY + extra + 1;\n      }\n\n      if (nRegRects <= MAX_RECTS_PER_OP) {\n        regRects[i].x = rectX1;\n        regRects[i].y = rectY1;\n        regRects[i].width = rectX2 - rectX1;\n        regRects[i].height = rectY2 - rectY1;\n      } else {\n        if (rectX1 < minX) minX = rectX1;\n        if (rectY1 < minY) minY = rectY1;\n        if (rectX2 > maxX) maxX = rectX2;\n        if (rectY2 > maxY) maxY = rectY2;\n      }\n\n      prevX = curX;\n      prevY = curY;\n    }\n\n    if (nRegRects > MAX_RECTS_PER_OP) {\n      regRects[0].x = minX;\n      regRects[0].y = minY;\n      regRects[0].width = maxX - minX;\n      regRects[0].height = maxY - minY;\n      nRegRects = 1;\n    }\n  }\n\n  reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);\n  RegionIntersect(reg, reg, pGC->pCompositeClip);\n\n  (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);\n\n  add_changed(pGC->pScreen, reg);\n\n  RegionDestroy(reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// PolySegment - changed region is the union of the bounding rects of each\n// segment, clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP\n// segments, just use the bounding rect of all the segments.\n\nstatic void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,\n                                xSegment *segs)\n{\n  xRectangle regRects[MAX_RECTS_PER_OP];\n  int nRegRects;\n\n  int lw, extra;\n\n  int rectX1, rectY1, rectX2, rectY2;\n  int minX, minY, maxX, maxY;\n\n  int i;\n\n  RegionPtr reg;\n\n  GC_OP_PROLOGUE(pGC, PolySegment);\n\n  if (nseg == 0) {\n    (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);\n    goto out;\n  }\n\n  nRegRects = nseg;\n\n  lw = pGC->lineWidth;\n  extra = lw / 2;\n\n  minX = maxX = segs[0].x1;\n  minY = maxY = segs[0].y1;\n\n  for (i = 0; i < nseg; i++) {\n    if (segs[i].x1 > segs[i].x2) {\n      rectX1 = pDrawable->x + segs[i].x2 - extra;\n      rectX2 = pDrawable->x + segs[i].x1 + extra + 1;\n    } else {\n      rectX1 = pDrawable->x + segs[i].x1 - extra;\n      rectX2 = pDrawable->x + segs[i].x2 + extra + 1;\n    }\n\n    if (segs[i].y1 > segs[i].y2) {\n      rectY1 = pDrawable->y + segs[i].y2 - extra;\n      rectY2 = pDrawable->y + segs[i].y1 + extra + 1;\n    } else {\n      rectY1 = pDrawable->y + segs[i].y1 - extra;\n      rectY2 = pDrawable->y + segs[i].y2 + extra + 1;\n    }\n\n    if (nseg <= MAX_RECTS_PER_OP) {\n      regRects[i].x = rectX1;\n      regRects[i].y = rectY1;\n      regRects[i].width = rectX2 - rectX1;\n      regRects[i].height = rectY2 - rectY1;\n    } else {\n      if (rectX1 < minX) minX = rectX1;\n      if (rectY1 < minY) minY = rectY1;\n      if (rectX2 > maxX) maxX = rectX2;\n      if (rectY2 > maxY) maxY = rectY2;\n    }\n  }\n\n  if (nseg > MAX_RECTS_PER_OP) {\n    regRects[0].x = minX;\n    regRects[0].y = minY;\n    regRects[0].width = maxX - minX;\n    regRects[0].height = maxY - minY;\n    nRegRects = 1;\n  }\n\n  reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);\n  RegionIntersect(reg, reg, pGC->pCompositeClip);\n\n  (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);\n\n  add_changed(pGC->pScreen, reg);\n\n  RegionDestroy(reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// PolyRectangle - changed region is the union of the bounding rects around\n// each side of the outline rectangles, clipped by pCompositeClip.  If there\n// are more than MAX_RECTS_PER_OP rectangles, just use the bounding rect of all\n// the rectangles.\n\nstatic void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,\n                                  xRectangle *rects)\n{\n  xRectangle regRects[MAX_RECTS_PER_OP*4];\n  int nRegRects;\n\n  int lw, extra;\n\n  int rectX1, rectY1, rectX2, rectY2;\n  int minX, minY, maxX, maxY;\n\n  int i;\n\n  RegionPtr reg;\n\n  GC_OP_PROLOGUE(pGC, PolyRectangle);\n\n  if (nrects == 0) {\n    (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);\n    goto out;\n  }\n\n  nRegRects = nrects * 4;\n\n  lw = pGC->lineWidth;\n  extra = lw / 2;\n\n  minX = maxX = rects[0].x;\n  minY = maxY = rects[0].y;\n\n  for (i = 0; i < nrects; i++) {\n    if (nrects <= MAX_RECTS_PER_OP) {\n      regRects[i*4].x = rects[i].x - extra + pDrawable->x;\n      regRects[i*4].y = rects[i].y - extra + pDrawable->y;\n      regRects[i*4].width = rects[i].width + 1 + 2 * extra;\n      regRects[i*4].height = 1 + 2 * extra;\n\n      regRects[i*4+1].x = rects[i].x - extra + pDrawable->x;\n      regRects[i*4+1].y = rects[i].y - extra + pDrawable->y;\n      regRects[i*4+1].width = 1 + 2 * extra;\n      regRects[i*4+1].height = rects[i].height + 1 + 2 * extra;\n\n      regRects[i*4+2].x = rects[i].x + rects[i].width - extra + pDrawable->x;\n      regRects[i*4+2].y = rects[i].y - extra + pDrawable->y;\n      regRects[i*4+2].width = 1 + 2 * extra;\n      regRects[i*4+2].height = rects[i].height + 1 + 2 * extra;\n\n      regRects[i*4+3].x = rects[i].x - extra + pDrawable->x;\n      regRects[i*4+3].y = rects[i].y + rects[i].height - extra + pDrawable->y;\n      regRects[i*4+3].width = rects[i].width + 1 + 2 * extra;\n      regRects[i*4+3].height = 1 + 2 * extra;\n    } else {\n      rectX1 = pDrawable->x + rects[i].x - extra;\n      rectY1 = pDrawable->y + rects[i].y - extra;\n      rectX2 = pDrawable->x + rects[i].x + rects[i].width + extra+1;\n      rectY2 = pDrawable->y + rects[i].y + rects[i].height + extra+1;\n      if (rectX1 < minX) minX = rectX1;\n      if (rectY1 < minY) minY = rectY1;\n      if (rectX2 > maxX) maxX = rectX2;\n      if (rectY2 > maxY) maxY = rectY2;\n    }\n  }\n\n  if (nrects > MAX_RECTS_PER_OP) {\n    regRects[0].x = minX;\n    regRects[0].y = minY;\n    regRects[0].width = maxX - minX;\n    regRects[0].height = maxY - minY;\n    nRegRects = 1;\n  }\n\n  reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);\n  RegionIntersect(reg, reg, pGC->pCompositeClip);\n\n  (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);\n\n  add_changed(pGC->pScreen, reg);\n\n  RegionDestroy(reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// PolyArc - changed region is the union of bounding rects around each arc,\n// clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP\n// arcs, just use the bounding rect of all the arcs.\n\nstatic void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,\n                            xArc *arcs)\n{\n  xRectangle regRects[MAX_RECTS_PER_OP];\n  int nRegRects;\n\n  int lw, extra;\n\n  int rectX1, rectY1, rectX2, rectY2;\n  int minX, minY, maxX, maxY;\n\n  int i;\n\n  RegionPtr reg;\n\n  GC_OP_PROLOGUE(pGC, PolyArc);\n\n  if (narcs == 0) {\n    (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);\n    goto out;\n  }\n\n  nRegRects = narcs;\n\n  lw = pGC->lineWidth;\n  if (lw == 0)\n    lw = 1;\n  extra = lw / 2;\n\n  minX = maxX = arcs[0].x;\n  minY = maxY = arcs[0].y;\n\n  for (i = 0; i < narcs; i++) {\n    if (narcs <= MAX_RECTS_PER_OP) {\n      regRects[i].x = arcs[i].x - extra + pDrawable->x;\n      regRects[i].y = arcs[i].y - extra + pDrawable->y;\n      regRects[i].width = arcs[i].width + lw;\n      regRects[i].height = arcs[i].height + lw;\n    } else {\n      rectX1 = pDrawable->x + arcs[i].x - extra;\n      rectY1 = pDrawable->y + arcs[i].y - extra;\n      rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;\n      rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;\n      if (rectX1 < minX) minX = rectX1;\n      if (rectY1 < minY) minY = rectY1;\n      if (rectX2 > maxX) maxX = rectX2;\n      if (rectY2 > maxY) maxY = rectY2;\n    }\n  }\n\n  if (narcs > MAX_RECTS_PER_OP) {\n    regRects[0].x = minX;\n    regRects[0].y = minY;\n    regRects[0].width = maxX - minX;\n    regRects[0].height = maxY - minY;\n    nRegRects = 1;\n  }\n\n  reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);\n  RegionIntersect(reg, reg, pGC->pCompositeClip);\n\n  (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);\n\n  add_changed(pGC->pScreen, reg);\n\n  RegionDestroy(reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n\n// FillPolygon - changed region is the bounding rect around the polygon,\n// clipped by pCompositeClip\n\nstatic void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,\n                                int mode, int count, DDXPointPtr pts)\n{\n  int minX, minY, maxX, maxY;\n  int i;\n\n  BoxRec box;\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, FillPolygon);\n\n  if (count == 0) {\n    (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);\n    goto out;\n  }\n\n  minX = pts[0].x;\n  maxX = pts[0].x;\n  minY = pts[0].y;\n  maxY = pts[0].y;\n\n  if (mode == CoordModePrevious) {\n    int x = pts[0].x;\n    int y = pts[0].y;\n\n    for (i = 1; i < count; i++) {\n      x += pts[i].x;\n      y += pts[i].y;\n      if (x < minX) minX = x;\n      if (x > maxX) maxX = x;\n      if (y < minY) minY = y;\n      if (y > maxY) maxY = y;\n    }\n  } else {\n    for (i = 1; i < count; i++) {\n      if (pts[i].x < minX) minX = pts[i].x;\n      if (pts[i].x > maxX) maxX = pts[i].x;\n      if (pts[i].y < minY) minY = pts[i].y;\n      if (pts[i].y > maxY) maxY = pts[i].y;\n    }\n  }\n\n  box.x1 = minX + pDrawable->x;\n  box.y1 = minY + pDrawable->y;\n  box.x2 = maxX + 1 + pDrawable->x;\n  box.y2 = maxY + 1 + pDrawable->y;\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// PolyFillRect - changed region is the union of the rectangles, clipped by\n// pCompositeClip.  If there are more than MAX_RECTS_PER_OP rectangles, just\n// use the bounding rect of all the rectangles.\n\nstatic void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,\n                                 xRectangle *rects)\n{\n  xRectangle regRects[MAX_RECTS_PER_OP];\n  int nRegRects;\n  int rectX1, rectY1, rectX2, rectY2;\n  int minX, minY, maxX, maxY;\n  int i;\n\n  RegionPtr reg;\n\n  GC_OP_PROLOGUE(pGC, PolyFillRect);\n\n  if (nrects == 0) {\n    (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);\n    goto out;\n  }\n\n  nRegRects = nrects;\n  minX = maxX = rects[0].x;\n  minY = maxY = rects[0].y;\n\n  for (i = 0; i < nrects; i++) {\n    if (nrects <= MAX_RECTS_PER_OP) {\n      regRects[i].x = rects[i].x + pDrawable->x;\n      regRects[i].y = rects[i].y + pDrawable->y;\n      regRects[i].width = rects[i].width;\n      regRects[i].height = rects[i].height;\n    } else {\n      rectX1 = pDrawable->x + rects[i].x;\n      rectY1 = pDrawable->y + rects[i].y;\n      rectX2 = pDrawable->x + rects[i].x + rects[i].width;\n      rectY2 = pDrawable->y + rects[i].y + rects[i].height;\n      if (rectX1 < minX) minX = rectX1;\n      if (rectY1 < minY) minY = rectY1;\n      if (rectX2 > maxX) maxX = rectX2;\n      if (rectY2 > maxY) maxY = rectY2;\n    }\n  }\n\n  if (nrects > MAX_RECTS_PER_OP) {\n    regRects[0].x = minX;\n    regRects[0].y = minY;\n    regRects[0].width = maxX - minX;\n    regRects[0].height = maxY - minY;\n    nRegRects = 1;\n  }\n\n  reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);\n  RegionIntersect(reg, reg, pGC->pCompositeClip);\n\n  (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);\n\n  add_changed(pGC->pScreen, reg);\n\n  RegionDestroy(reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// PolyFillArc - changed region is the union of bounding rects around each arc,\n// clipped by pCompositeClip.  If there are more than MAX_RECTS_PER_OP arcs,\n// just use the bounding rect of all the arcs.\n\nstatic void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,\n                                xArc *arcs)\n{\n  xRectangle regRects[MAX_RECTS_PER_OP];\n  int nRegRects;\n\n  int lw, extra;\n\n  int rectX1, rectY1, rectX2, rectY2;\n  int minX, minY, maxX, maxY;\n\n  int i;\n\n  RegionPtr reg;\n\n  GC_OP_PROLOGUE(pGC, PolyFillArc);\n\n  if (narcs == 0) {\n    (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);\n    goto out;\n  }\n\n  nRegRects = narcs;\n\n  lw = pGC->lineWidth;\n  if (lw == 0)\n    lw = 1;\n  extra = lw / 2;\n\n  minX = maxX = arcs[0].x;\n  minY = maxY = arcs[0].y;\n\n  for (i = 0; i < narcs; i++) {\n    if (narcs <= MAX_RECTS_PER_OP) {\n      regRects[i].x = arcs[i].x - extra + pDrawable->x;\n      regRects[i].y = arcs[i].y - extra + pDrawable->y;\n      regRects[i].width = arcs[i].width + lw;\n      regRects[i].height = arcs[i].height + lw;\n    } else {\n      rectX1 = pDrawable->x + arcs[i].x - extra;\n      rectY1 = pDrawable->y + arcs[i].y - extra;\n      rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;\n      rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;\n      if (rectX1 < minX) minX = rectX1;\n      if (rectY1 < minY) minY = rectY1;\n      if (rectX2 > maxX) maxX = rectX2;\n      if (rectY2 > maxY) maxY = rectY2;\n    }\n  }\n\n  if (narcs > MAX_RECTS_PER_OP) {\n    regRects[0].x = minX;\n    regRects[0].y = minY;\n    regRects[0].width = maxX - minX;\n    regRects[0].height = maxY - minY;\n    nRegRects = 1;\n  }\n\n  reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);\n  RegionIntersect(reg, reg, pGC->pCompositeClip);\n\n  (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);\n\n  add_changed(pGC->pScreen, reg);\n\n  RegionDestroy(reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// GetTextBoundingRect - calculate a bounding rectangle around n chars of a\n// font.  Not particularly accurate, but good enough.\n\nstatic void GetTextBoundingRect(DrawablePtr pDrawable, FontPtr font, int x,\n                                int y, int nchars, BoxPtr box)\n{\n  int ascent = max(FONTASCENT(font), FONTMAXBOUNDS(font, ascent));\n  int descent = max(FONTDESCENT(font), FONTMAXBOUNDS(font, descent));\n  int charWidth = max(FONTMAXBOUNDS(font,rightSideBearing),\n                      FONTMAXBOUNDS(font,characterWidth));\n\n  box->x1 = pDrawable->x + x;\n  box->y1 = pDrawable->y + y - ascent;\n  box->x2 = box->x1 + charWidth * nchars;\n  box->y2 = box->y1 + ascent + descent;\n\n  if (FONTMINBOUNDS(font,leftSideBearing) < 0)\n    box->x1 += FONTMINBOUNDS(font,leftSideBearing);\n}\n\n// PolyText8 - changed region is bounding rect around count chars, clipped by\n// pCompositeClip\n\nstatic int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,\n                             int count, char *chars)\n{\n  int ret;\n  BoxRec box;\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, PolyText8);\n\n  if (count == 0) {\n    ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);\n    goto out;\n  }\n\n  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n\n  return ret;\n}\n\n// PolyText16 - changed region is bounding rect around count chars, clipped by\n// pCompositeClip\n\nstatic int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,\n                              int count, unsigned short *chars)\n{\n  int ret;\n  BoxRec box;\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, PolyText16);\n\n  if (count == 0) {\n    ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);\n    goto out;\n  }\n\n  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n\n  return ret;\n}\n\n// ImageText8 - changed region is bounding rect around count chars, clipped by\n// pCompositeClip\n\nstatic void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,\n                               int count, char *chars)\n{\n  BoxRec box;\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, ImageText8);\n\n  if (count == 0) {\n    (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);\n    goto out;\n  }\n\n  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// ImageText16 - changed region is bounding rect around count chars, clipped by\n// pCompositeClip\n\nstatic void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,\n                                int count, unsigned short *chars)\n{\n  BoxRec box;\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, ImageText16);\n\n  if (count == 0) {\n    (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);\n    goto out;\n  }\n\n  GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// ImageGlyphBlt - changed region is bounding rect around nglyph chars, clipped\n// by pCompositeClip\n\nstatic void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,\n                                  int y, unsigned int nglyph,\n                                  CharInfoPtr *ppci, void * pglyphBase)\n{\n  BoxRec box;\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, ImageGlyphBlt);\n\n  if (nglyph == 0) {\n    (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);\n    goto out;\n  }\n\n  GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// PolyGlyphBlt - changed region is bounding rect around nglyph chars, clipped\n// by pCompositeClip\n\nstatic void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,\n                                 int y, unsigned int nglyph,\n                                 CharInfoPtr *ppci, void * pglyphBase)\n{\n  BoxRec box;\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, PolyGlyphBlt);\n\n  if (nglyph == 0) {\n    (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);\n    goto out;\n  }\n\n  GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\nout:\n  GC_OP_EPILOGUE(pGC);\n}\n\n// PushPixels - changed region is the given rectangle, clipped by\n// pCompositeClip\n\nstatic void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,\n                               DrawablePtr pDrawable, int w, int h, int x,\n                               int y)\n{\n  BoxRec box;\n  RegionRec reg;\n\n  GC_OP_PROLOGUE(pGC, PushPixels);\n\n  box.x1 = x + pDrawable->x;\n  box.y1 = y + pDrawable->y;\n  box.x2 = box.x1 + w;\n  box.y2 = box.y1 + h;\n\n  RegionInitBoxes(&reg, &box, 1);\n  RegionIntersect(&reg, &reg, pGC->pCompositeClip);\n\n  (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);\n\n  add_changed(pGC->pScreen, &reg);\n\n  RegionUninit(&reg);\n\n  GC_OP_EPILOGUE(pGC);\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncHooks.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2009-2015 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __VNCHOOKS_H__\n#define __VNCHOOKS_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nint vncHooksInit(int scrIdx);\n\nvoid vncGetScreenImage(int scrIdx, int x, int y, int width, int height,\n                       char *buffer, int strideBytes);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncInput.c",
    "content": "/* Copyright (C) 2009 TightVNC Team\n * Copyright (C) 2009, 2014 Red Hat, Inc.\n * Copyright 2013-2015 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include \"xorg-version.h\"\n\n#include \"vncInput.h\"\n#include \"vncExtInit.h\"\n#include \"RFBGlue.h\"\n\n/* This is a C header, so safe to include */\n#include <rfb/KeysymStr.h>\n\n#include \"inputstr.h\"\n#include \"inpututils.h\"\n#include \"mi.h\"\n#include \"mipointer.h\"\n#include \"exevents.h\"\n#include \"scrnintstr.h\"\n#include \"xkbsrv.h\"\n#include \"xkbstr.h\"\n#include \"xserver-properties.h\"\nextern _X_EXPORT DevPrivateKey CoreDevicePrivateKey;\n#include <X11/keysym.h>\n#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n\nextern const unsigned short code_map_qnum_to_xorgevdev[];\nextern const unsigned int code_map_qnum_to_xorgevdev_len;\nextern const unsigned short code_map_qnum_to_xorgkbd[];\nextern const unsigned int code_map_qnum_to_xorgkbd_len;\n\n#define BUTTONS 9\n\nDeviceIntPtr vncKeyboardDev;\nDeviceIntPtr vncPointerDev;\n\nstatic int oldButtonMask;\nstatic int cursorPosX, cursorPosY;\n\nstatic const unsigned short *codeMap;\nstatic unsigned int codeMapLen;\n\nstatic KeySym pressedKeys[256];\n\nstatic int vncPointerProc(DeviceIntPtr pDevice, int onoff);\nstatic void vncKeyboardBell(int percent, DeviceIntPtr device,\n                            void * ctrl, int class);\nstatic int vncKeyboardProc(DeviceIntPtr pDevice, int onoff);\n\nstatic void vncKeysymKeyboardEvent(KeySym keysym, int down);\n\n#define LOG_NAME \"Input\"\n\n#define LOG_ERROR(...) vncLogError(LOG_NAME, __VA_ARGS__)\n#define LOG_STATUS(...) vncLogStatus(LOG_NAME, __VA_ARGS__)\n#define LOG_INFO(...) vncLogInfo(LOG_NAME, __VA_ARGS__)\n#define LOG_DEBUG(...) vncLogDebug(LOG_NAME, __VA_ARGS__)\n\n/*\n * Init input device.\n * This has to be called after core pointer/keyboard\n * initialization which unfortunately is after extensions\n * initialization (which means we cannot call it in\n * vncExtensionInit(). Check InitExtensions(),\n * InitCoreDevices() and InitInput() calls in dix/main.c.\n * Instead we call it from XserverDesktop at an appropriate\n * time.\n */\nvoid vncInitInputDevice(void)\n{\n\tint i, ret;\n\n\tif ((vncPointerDev != NULL) || (vncKeyboardDev != NULL))\n\t\treturn;\n\n\t/*\n\t * On Linux we try to provide the same key codes as Xorg with\n\t * the evdev driver. On other platforms we mimic the older\n\t * Xorg KBD driver.\n\t */\n#ifdef __linux__\n\tcodeMap = code_map_qnum_to_xorgevdev;\n\tcodeMapLen = code_map_qnum_to_xorgevdev_len;\n#else\n\tcodeMap = code_map_qnum_to_xorgkbd;\n\tcodeMapLen = code_map_qnum_to_xorgkbd_len;\n#endif\n\n\tfor (i = 0;i < 256;i++)\n\t\tpressedKeys[i] = NoSymbol;\n\n\tret = AllocDevicePair(serverClient, \"TigerVNC\",\n\t                      &vncPointerDev, &vncKeyboardDev,\n\t                      vncPointerProc, vncKeyboardProc,\n\t\t\t      FALSE);\n\n\tif (ret != Success)\n\t\tFatalError(\"Failed to initialize TigerVNC input devices\\n\");\n\n\tif (ActivateDevice(vncPointerDev, TRUE) != Success ||\n\t    ActivateDevice(vncKeyboardDev, TRUE) != Success)\n\t\tFatalError(\"Failed to activate TigerVNC devices\\n\");\n\n\tif (!EnableDevice(vncPointerDev, TRUE) ||\n\t    !EnableDevice(vncKeyboardDev, TRUE))\n\t\tFatalError(\"Failed to activate TigerVNC devices\\n\");\n\n\tvncPrepareInputDevices();\n}\n\nvoid vncPointerButtonAction(int buttonMask)\n{\n\tint i;\n\tValuatorMask mask;\n\n\tfor (i = 0; i < BUTTONS; i++) {\n\t\tif ((buttonMask ^ oldButtonMask) & (1 << i)) {\n\t\t\tint action = (buttonMask & (1<<i)) ?\n\t\t\t\t     ButtonPress : ButtonRelease;\n\t\t\tvaluator_mask_set_range(&mask, 0, 0, NULL);\n\t\t\tQueuePointerEvents(vncPointerDev, action, i + 1,\n\t\t\t\t\t   POINTER_RELATIVE, &mask);\n\t\t}\n\t}\n\n\toldButtonMask = buttonMask;\n}\n\nvoid vncPointerMove(int x, int y)\n{\n\tint valuators[2];\n\tValuatorMask mask;\n\n\tif (cursorPosX == x && cursorPosY == y)\n\t\treturn;\n\n\tvaluators[0] = x;\n\tvaluators[1] = y;\n\tvaluator_mask_set_range(&mask, 0, 2, valuators);\n\tQueuePointerEvents(vncPointerDev, MotionNotify, 0,\n\t                   POINTER_ABSOLUTE, &mask);\n\n\tcursorPosX = x;\n\tcursorPosY = y;\n}\n\nvoid vncGetPointerPos(int *x, int *y)\n{\n\tif ((vncPointerDev != NULL) && (vncPointerDev->public.on)) {\n\t\tScreenPtr ptrScreen;\n\n\t\tmiPointerGetPosition(vncPointerDev, &cursorPosX, &cursorPosY);\n\n\t\t/* Pointer coordinates are screen relative */\n\t\tptrScreen = miPointerGetScreen(vncPointerDev);\n\t\tcursorPosX += ptrScreen->x;\n\t\tcursorPosY += ptrScreen->y;\n\t}\n\n\t*x = cursorPosX;\n\t*y = cursorPosY;\n}\n\nstatic int vncPointerProc(DeviceIntPtr pDevice, int onoff)\n{\n\tBYTE map[BUTTONS + 1];\n\tDevicePtr pDev = (DevicePtr)pDevice;\n\tint i;\n\t/*\n\t * NOTE: map[] array is one element longer than btn_labels[] array. This\n\t * is not a bug.\n\t */\n\tAtom btn_labels[BUTTONS];\n\tAtom axes_labels[2];\n\n\tswitch (onoff) {\n\tcase DEVICE_INIT:\n\t\tfor (i = 0; i < BUTTONS + 1; i++)\n\t\t\tmap[i] = i;\n\n\t\tbtn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);\n\t\tbtn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);\n\t\tbtn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);\n\t\tbtn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);\n\t\tbtn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);\n\t\tbtn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);\n\t\tbtn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);\n\n\t\t/*\n\t\t * The labels BTN_LABEL_PROP_BTN_SIDE and BTN_LABEL_PROP_BTN_EXTRA\n\t\t * represent the side buttons on mice that are typically used to\n\t\t * navigate back/forward respectively in web browsers.\n\t\t *\n\t\t * In X11, these labels are mapped to the BTN_SIDE and BTN_EXTRA\n\t\t * input codes, which are mapped in the Linux HID driver. These\n\t\t * are not to be confused with the BTN_FORWARD and BTN_BACK input\n\t\t * codes, which some applications also use for back/forward\n\t\t * navigation.\n\t\t *\n\t\t * It seems like most mice have their side buttons mapped to\n\t\t * BTN_SIDE and BTN_EXTRA.\n\t\t */\n\t\tbtn_labels[7] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_SIDE);\n\t\tbtn_labels[8] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_EXTRA);\n\n\t\taxes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);\n\t\taxes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);\n\n\t\tInitPointerDeviceStruct(pDev, map, BUTTONS, btn_labels,\n\t\t\t\t\t(PtrCtrlProcPtr)NoopDDA,\n\t\t\t\t\tGetMotionHistorySize(),\n\t\t\t\t\t2, axes_labels);\n\t\tbreak;\n\tcase DEVICE_ON:\n\t\tpDev->on = TRUE;\n\t\tbreak;\n\tcase DEVICE_OFF:\n\t\tpDev->on = FALSE;\n\t\tbreak;\n\tcase DEVICE_CLOSE:\n\t\tvncPointerDev = NULL;\n\t\tbreak;\n\t}\n\n\treturn Success;\n}\n\nstatic void vncKeyboardBell(int percent, DeviceIntPtr device,\n                            void * ctrl, int class)\n{\n\tif (percent > 0)\n\t\tvncBell();\n}\n\nstatic void vncKeyboardCtrl(DeviceIntPtr pDevice, KeybdCtrl *ctrl)\n{\n\tvncSetLEDState(ctrl->leds);\n}\n\nstatic int vncKeyboardProc(DeviceIntPtr pDevice, int onoff)\n{\n\tDevicePtr pDev = (DevicePtr)pDevice;\n\n\tswitch (onoff) {\n\tcase DEVICE_INIT:\n\t\tInitKeyboardDeviceStruct(pDevice, NULL, vncKeyboardBell,\n\t\t\t\t\t vncKeyboardCtrl);\n\t\tbreak;\n\tcase DEVICE_ON:\n\t\tpDev->on = TRUE;\n\t\tbreak;\n\tcase DEVICE_OFF:\n\t\tpDev->on = FALSE;\n\t\tbreak;\n\tcase DEVICE_CLOSE:\n\t\tvncKeyboardDev = NULL;\n\t\tbreak;\n\t}\n\n\treturn Success;\n}\n\nstatic inline void pressKey(DeviceIntPtr dev, int kc, Bool down, const char *msg)\n{\n\tint action;\n\n\tif (msg != NULL)\n\t\tLOG_DEBUG(\"%s %d %s\", msg, kc, down ? \"down\" : \"up\");\n\n\taction = down ? KeyPress : KeyRelease;\n\tQueueKeyboardEvents(dev, action, kc);\n}\n\n/*\n * vncKeyboardEvent() - add X11 events for the given RFB key event\n */\nvoid vncKeyboardEvent(KeySym keysym, unsigned xtcode, int down)\n{\n\t/* Simple case: the client has specified the key */\n\tif (xtcode && xtcode < codeMapLen) {\n\t\tint keycode;\n\n\t\tkeycode = codeMap[xtcode];\n\t\tif (!keycode) {\n\t\t\t/*\n\t\t\t * Figure something out based on keysym if we\n\t\t\t * cannot find a mapping.\n\t\t\t */\n\t\t\tif (keysym)\n\t\t\t\tvncKeysymKeyboardEvent(keysym, down);\n\t\t\treturn;\n\t\t}\n\n\t\t/*\n\t\t * We update the state table in case we get a mix of\n\t\t * events with and without key codes.\n\t\t */\n\t\tif (down)\n\t\t\tpressedKeys[keycode] = keysym;\n\t\telse\n\t\t\tpressedKeys[keycode] = NoSymbol;\n\n\t\tpressKey(vncKeyboardDev, keycode, down, \"raw keycode\");\n\t\tmieqProcessInputEvents();\n\t\treturn;\n\t}\n\n\t/*\n\t * Advanced case: We have to figure out a sequence of keys that\n\t *                result in the given keysym\n\t */\n\tif (keysym)\n\t\tvncKeysymKeyboardEvent(keysym, down);\n}\n\n/* altKeysym is a table of alternative keysyms which have the same meaning. */\n\nstatic struct altKeysym_t {\n\tKeySym a, b;\n} altKeysym[] = {\n\t{ XK_Shift_L,\t\tXK_Shift_R },\n\t{ XK_Control_L,\t\tXK_Control_R },\n\t{ XK_Meta_L,\t\tXK_Meta_R },\n\t{ XK_Alt_L,\t\tXK_Alt_R },\n\t{ XK_Super_L,\t\tXK_Super_R },\n\t{ XK_Hyper_L,\t\tXK_Hyper_R },\n\t{ XK_KP_Space,\t\tXK_space },\n\t{ XK_KP_Tab,\t\tXK_Tab },\n\t{ XK_KP_Enter,\t\tXK_Return },\n\t{ XK_KP_F1,\t\tXK_F1 },\n\t{ XK_KP_F2,\t\tXK_F2 },\n\t{ XK_KP_F3,\t\tXK_F3 },\n\t{ XK_KP_F4,\t\tXK_F4 },\n\t{ XK_KP_Home,\t\tXK_Home },\n\t{ XK_KP_Left,\t\tXK_Left },\n\t{ XK_KP_Up,\t\tXK_Up },\n\t{ XK_KP_Right,\t\tXK_Right },\n\t{ XK_KP_Down,\t\tXK_Down },\n\t{ XK_KP_Page_Up,\tXK_Page_Up },\n\t{ XK_KP_Page_Down,\tXK_Page_Down },\n\t{ XK_KP_End,\t\tXK_End },\n\t{ XK_KP_Begin,\t\tXK_Begin },\n\t{ XK_KP_Insert,\t\tXK_Insert },\n\t{ XK_KP_Delete,\t\tXK_Delete },\n\t{ XK_KP_Equal,\t\tXK_equal },\n\t{ XK_KP_Multiply,\tXK_asterisk },\n\t{ XK_KP_Add,\t\tXK_plus },\n\t{ XK_KP_Separator,\tXK_comma },\n\t{ XK_KP_Subtract,\tXK_minus },\n\t{ XK_KP_Decimal,\tXK_period },\n\t{ XK_KP_Divide,\t\tXK_slash },\n\t{ XK_KP_0,\t\tXK_0 },\n\t{ XK_KP_1,\t\tXK_1 },\n\t{ XK_KP_2,\t\tXK_2 },\n\t{ XK_KP_3,\t\tXK_3 },\n\t{ XK_KP_4,\t\tXK_4 },\n\t{ XK_KP_5,\t\tXK_5 },\n\t{ XK_KP_6,\t\tXK_6 },\n\t{ XK_KP_7,\t\tXK_7 },\n\t{ XK_KP_8,\t\tXK_8 },\n\t{ XK_KP_9,\t\tXK_9 },\n\t{ XK_ISO_Level3_Shift,\tXK_Mode_switch },\n};\n\n/*\n * vncKeysymKeyboardEvent() - work out the best keycode corresponding\n * to the keysym sent by the viewer. This is basically impossible in\n * the general case, but we make a best effort by assuming that all\n * useful keysyms can be reached using just the Shift and\n * Level 3 (AltGr) modifiers. For core keyboards this is basically\n * always true, and should be true for most sane, western XKB layouts.\n */\nstatic void vncKeysymKeyboardEvent(KeySym keysym, int down)\n{\n\tint i;\n\tunsigned state, new_state;\n\tKeyCode keycode;\n\n\tunsigned level_three_mask;\n\tKeyCode shift_press, level_three_press;\n\tKeyCode shift_release[8], level_three_release[8];\n\tsize_t shift_release_count, level_three_release_count;\n\n\t/*\n\t * Release events must match the press event, so look up what\n\t * keycode we sent for the press.\n\t */\n\tif (!down) {\n\t\tfor (i = 0;i < 256;i++) {\n\t\t\tif (pressedKeys[i] == keysym) {\n\t\t\t\tpressedKeys[i] = NoSymbol;\n\t\t\t\tpressKey(vncKeyboardDev, i, FALSE, \"keycode\");\n\t\t\t\tmieqProcessInputEvents();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * This can happen quite often as we ignore some\n\t\t * key presses.\n\t\t */\n\t\tLOG_DEBUG(\"Unexpected release of keysym XK_%s (0x%04x)\",\n                          KeySymName(keysym), keysym);\n\t\treturn;\n\t}\n\n\t/* \n\t * Since we are checking the current state to determine if we need\n\t * to fake modifiers, we must make sure that everything put on the\n\t * input queue is processed before we start. Otherwise, shift may be\n\t * stuck down.\n\t */ \n\tmieqProcessInputEvents();\n\n\tstate = vncGetKeyboardState();\n\n\tkeycode = vncKeysymToKeycode(keysym, state, &new_state);\n\n\t/*\n\t * Shift+Alt is often mapped to Meta, so try that rather than\n\t * allocating a new entry, faking shift, or using the dummy\n\t * key entries that many layouts have.\n\t */\n\tif ((state & ShiftMask) &&\n\t    ((keysym == XK_Alt_L) || (keysym == XK_Alt_R))) {\n\t\tKeyCode alt, meta;\n\n\t\tif (keysym == XK_Alt_L) {\n\t\t\talt = vncKeysymToKeycode(XK_Alt_L, state & ~ShiftMask, NULL);\n\t\t\tmeta = vncKeysymToKeycode(XK_Meta_L, state, NULL);\n\t\t} else {\n\t\t\talt = vncKeysymToKeycode(XK_Alt_R, state & ~ShiftMask, NULL);\n\t\t\tmeta = vncKeysymToKeycode(XK_Meta_R, state, NULL);\n\t\t}\n\n\t\tif ((meta != 0) && (alt == meta)) {\n\t\t\tLOG_DEBUG(\"Replacing Shift+Alt with Shift+Meta\");\n\t\t\tkeycode = meta;\n\t\t\tnew_state = state;\n\t\t}\n\t}\n\n\t/* Try some equivalent keysyms if we couldn't find a perfect match */\n\tif (keycode == 0) {\n\t\tfor (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) {\n\t\t\tKeySym altsym;\n\n\t\t\tif (altKeysym[i].a == keysym)\n\t\t\t\taltsym = altKeysym[i].b;\n\t\t\telse if (altKeysym[i].b == keysym)\n\t\t\t\taltsym = altKeysym[i].a;\n\t\t\telse\n\t\t\t\tcontinue;\n\n\t\t\tkeycode = vncKeysymToKeycode(altsym, state, &new_state);\n\t\t\tif (keycode != 0)\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* No matches. Will have to add a new entry... */\n\tif (keycode == 0) {\n\t\tkeycode = vncAddKeysym(keysym, state);\n\t\tif (keycode == 0) {\n\t\t\tLOG_ERROR(\"Failure adding new keysym XK_%s (0x%x)\",\n                                  KeySymName(keysym), keysym);\n\t\t\treturn;\n\t\t}\n\n\t\tLOG_INFO(\"Added keysym XK_%s (0x%04x) to keycode %d\",\n\t\t         KeySymName(keysym), keysym, keycode);\n\n\t\t/*\n\t\t * The state given to addKeysym() is just a hint and\n\t\t * the actual result might still require some state\n\t\t * changes.\n\t\t */\n\t\tkeycode = vncKeysymToKeycode(keysym, state, &new_state);\n\t\tif (keycode == 0) {\n\t\t\tLOG_ERROR(\"Newly added keysym XK_%s (0x%x) cannot be generated\",\n                                  KeySymName(keysym), keysym);\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/*\n\t * X11 generally lets shift toggle the keys on the numeric pad\n\t * the same way NumLock does. This is however not the case on\n\t * other systems like Windows. As a result, some applications\n\t * get confused when we do a fake shift to get the same effect\n\t * that having NumLock active would produce.\n\t *\n\t * Not all clients have proper NumLock synchronisation (so we\n\t * can avoid faking shift) so we try to avoid the fake shifts\n\t * if we can use an alternative keysym.\n\t */\n\tif (((state & ShiftMask) != (new_state & ShiftMask)) &&\n\t    vncGetAvoidShiftNumLock() && vncIsAffectedByNumLock(keycode)) {\n\t    \tKeyCode keycode2;\n\t    \tunsigned new_state2;\n\n\t\tLOG_DEBUG(\"Finding alternative to keysym XK_%s (0x%x) to avoid fake shift for numpad\",\n                          KeySymName(keysym), keysym);\n\n\t\tfor (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) {\n\t\t\tKeySym altsym;\n\n\t\t\tif (altKeysym[i].a == keysym)\n\t\t\t\taltsym = altKeysym[i].b;\n\t\t\telse if (altKeysym[i].b == keysym)\n\t\t\t\taltsym = altKeysym[i].a;\n\t\t\telse\n\t\t\t\tcontinue;\n\n\t\t\tkeycode2 = vncKeysymToKeycode(altsym, state, &new_state2);\n\t\t\tif (keycode2 == 0)\n\t\t\t\tcontinue;\n\n\t\t\tif (((state & ShiftMask) != (new_state2 & ShiftMask)) &&\n\t\t\t    vncIsAffectedByNumLock(keycode2))\n\t\t\t\tcontinue;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tif (i == sizeof(altKeysym)/sizeof(altKeysym[0]))\n\t\t\tLOG_DEBUG(\"No alternative keysym found\");\n\t\telse {\n\t\t\tkeycode = keycode2;\n\t\t\tnew_state = new_state2;\n\t\t}\n\t}\n\n\t/*\n\t * \"Shifted Tab\" is a bit of a mess. Some systems have varying,\n\t * special keysyms for this symbol. VNC mandates that clients\n\t * should always send the plain XK_Tab keysym and the server\n\t * should deduce the meaning based on current Shift state.\n\t * To comply with this, we will find the keycode that sends\n\t * XK_Tab, and make sure that Shift isn't cleared. This can\n\t * possibly result in a different keysym than XK_Tab, but that\n\t * is the desired behaviour.\n\t *\n\t * Note: We never get ISO_Left_Tab here because it's already\n\t *       been translated in VNCSConnectionST.\n\t */\n\tif (keysym == XK_Tab && (state & ShiftMask))\n\t\tnew_state |= ShiftMask;\n\n\t/*\n\t * We need a bigger state change than just shift,\n\t * so we need to know what the mask is for level 3 shifts.\n\t */\n\tif ((new_state & ~ShiftMask) != (state & ~ShiftMask))\n\t\tlevel_three_mask = vncGetLevelThreeMask();\n\telse\n\t\tlevel_three_mask = 0;\n\n\tshift_press = level_three_press = 0;\n\tshift_release_count = level_three_release_count = 0;\n\n\t/* Need a fake press or release of shift? */\n\tif (!(state & ShiftMask) && (new_state & ShiftMask)) {\n\t\tshift_press = vncPressShift();\n\t\tif (shift_press == 0) {\n\t\t\tLOG_ERROR(\"Unable to find a modifier key for Shift\");\n\t\t\treturn;\n\t\t}\n\n\t\tpressKey(vncKeyboardDev, shift_press, TRUE, \"temp shift\");\n\t} else if ((state & ShiftMask) && !(new_state & ShiftMask)) {\n\t\tshift_release_count = vncReleaseShift(shift_release,\n\t\t                                      sizeof(shift_release)/sizeof(*shift_release));\n\t\tif (shift_release_count == 0) {\n\t\t\tLOG_ERROR(\"Unable to find the modifier key(s) for releasing Shift\");\n\t\t\treturn;\n\t\t}\n\n\t\tfor (i = 0;i < shift_release_count;i++)\n\t\t\tpressKey(vncKeyboardDev, shift_release[i], FALSE, \"temp shift\");\n\t}\n\n\t/* Need a fake press or release of level three shift? */\n\tif (!(state & level_three_mask) && (new_state & level_three_mask)) {\n\t\tlevel_three_press = vncPressLevelThree();\n\t\tif (level_three_press == 0) {\n\t\t\tLOG_ERROR(\"Unable to find a modifier key for ISO_Level3_Shift/Mode_Switch\");\n\t\t\treturn;\n\t\t}\n\n\t\tpressKey(vncKeyboardDev, level_three_press, TRUE, \"temp level 3 shift\");\n\t} else if ((state & level_three_mask) && !(new_state & level_three_mask)) {\n\t\tlevel_three_release_count = vncReleaseLevelThree(level_three_release,\n\t\t                                                 sizeof(level_three_release)/sizeof(*level_three_release));\n\t\tif (level_three_release_count == 0) {\n\t\t\tLOG_ERROR(\"Unable to find the modifier key(s) for releasing ISO_Level3_Shift/Mode_Switch\");\n\t\t\treturn;\n\t\t}\n\n\t\tfor (i = 0;i < level_three_release_count;i++)\n\t\t\tpressKey(vncKeyboardDev, level_three_release[i], FALSE, \"temp level 3 shift\");\n\t}\n\n\t/* Now press the actual key */\n\tpressKey(vncKeyboardDev, keycode, TRUE, \"keycode\");\n\n\tif(down)\n\t\tvncOnKeyUsed(keycode);\n\n\t/* And store the mapping so that we can do a proper release later */\n\tfor (i = 0;i < 256;i++) {\n\t\tif (i == keycode)\n\t\t\tcontinue;\n\t\tif (pressedKeys[i] == keysym) {\n\t\t\tLOG_ERROR(\"Keysym XK_%s (0x%04x) generated by both keys %d and %d\",\n                                  KeySymName(keysym), keysym, i, keycode);\n\t\t\tpressedKeys[i] = NoSymbol;\n\t\t}\n\t}\n\n\tpressedKeys[keycode] = keysym;\n\n\t/* Undo any fake level three shift */\n\tif (level_three_press != 0)\n\t\tpressKey(vncKeyboardDev, level_three_press, FALSE, \"temp level 3 shift\");\n\telse if (level_three_release_count != 0) {\n\t\tfor (i = 0;i < level_three_release_count;i++)\n\t\t\tpressKey(vncKeyboardDev, level_three_release[i], TRUE, \"temp level 3 shift\");\n\t}\n\n\t/* Undo any fake shift */\n\tif (shift_press != 0)\n\t\tpressKey(vncKeyboardDev, shift_press, FALSE, \"temp shift\");\n\telse if (shift_release_count != 0) {\n\t\tfor (i = 0;i < shift_release_count;i++)\n\t\t\tpressKey(vncKeyboardDev, shift_release[i], TRUE, \"temp shift\");\n\t}\n\n\t/*\n\t * When faking a modifier we are putting a keycode (which can\n\t * currently activate the desired modifier) on the input\n\t * queue. A future modmap change can change the mapping so\n\t * that this keycode means something else entirely. Guard\n\t * against this by processing the queue now.\n\t */\n\tmieqProcessInputEvents();\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncInput.h",
    "content": "/* Copyright (C) 2009 TightVNC Team\n * Copyright (C) 2009, 2010 Red Hat, Inc.\n * Copyright (C) 2009, 2010 TigerVNC Team\n * Copyright 2013-2015 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __VNCINPUT_H__\n#define __VNCINPUT_H__\n\n#include <stdlib.h>\n#include <X11/X.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid vncInitInputDevice(void);\n\nvoid vncPointerButtonAction(int buttonMask);\nvoid vncPointerMove(int x, int y);\nvoid vncGetPointerPos(int *x, int *y);\n\nvoid vncKeyboardEvent(KeySym keysym, unsigned xtcode, int down);\n\n/* Backend dependent functions below here */\n\nvoid vncPrepareInputDevices(void);\n\nunsigned vncGetKeyboardState(void);\nunsigned vncGetLevelThreeMask(void);\n\nKeyCode vncPressShift(void);\nsize_t vncReleaseShift(KeyCode *keys, size_t maxKeys);\n\nKeyCode vncPressLevelThree(void);\nsize_t vncReleaseLevelThree(KeyCode *keys, size_t maxKeys);\n\nKeyCode vncKeysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state);\n\nint vncIsAffectedByNumLock(KeyCode keycode);\n\nKeyCode vncAddKeysym(KeySym keysym, unsigned state);\nvoid vncOnKeyUsed(KeyCode usedKeycode);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncInputXKB.c",
    "content": "/* Copyright (C) 2009 TightVNC Team\n * Copyright (C) 2009 Red Hat, Inc.\n * Copyright 2013-2018 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include \"xorg-version.h\"\n\n#include <stdio.h>\n\n#include <X11/keysym.h>\n#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n\n#include \"list.h\"\n#include \"xkbsrv.h\"\n#include \"xkbstr.h\"\n#include \"eventstr.h\"\n#include \"scrnintstr.h\"\n#include \"mi.h\"\n\n#include \"vncInput.h\"\n\n#ifndef KEYBOARD_OR_FLOAT\n#define KEYBOARD_OR_FLOAT MASTER_KEYBOARD\n#endif\n\nextern DeviceIntPtr vncKeyboardDev;\n\nstatic const KeyCode fakeKeys[] = {\n#ifdef __linux__\n    92, 203, 204, 205, 206, 207\n#else\n    8, 124, 125, 156, 127, 128\n#endif\n    };\n\ntypedef struct\n{\n\tKeySym keysym;\n\tKeyCode keycode;\n\tstruct xorg_list entry;\n} AddedKeySym;\n\n/*\n * If a KeySym recieved from client is not mapped to any KeyCode, it needs to be\n * mapped to an unused KeyCode to generate required key events.\n *\n * This list tracks such assignments. A KeyCode from this list can be reused if\n * we run out of unused KeyCodes.\n *\n * Items in this list are maintained in LRU order, with most recently used key\n * in front.\n */\nstatic struct xorg_list addedKeysyms;\n\nstatic void vncXkbProcessDeviceEvent(int screenNum,\n                                     InternalEvent *event,\n                                     DeviceIntPtr dev);\n\n/* Stolen from libX11 */\nstatic Bool\nXkbTranslateKeyCode(register XkbDescPtr xkb, KeyCode key,\n                    register unsigned int mods, unsigned int *mods_rtrn,\n                    KeySym *keysym_rtrn)\n{\n\tXkbKeyTypeRec *type;\n\tint col,nKeyGroups;\n\tunsigned preserve,effectiveGroup;\n\tKeySym *syms;\n\n\tif (mods_rtrn!=NULL)\n\t\t*mods_rtrn = 0;\n\n\tnKeyGroups= XkbKeyNumGroups(xkb,key);\n\tif ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {\n\t\tif (keysym_rtrn!=NULL)\n\t\t\t*keysym_rtrn = NoSymbol;\n\t\treturn False;\n\t}\n\n\tsyms = XkbKeySymsPtr(xkb,key);\n\n\t/* find the offset of the effective group */\n\tcol = 0;\n\teffectiveGroup= XkbGroupForCoreState(mods);\n\tif ( effectiveGroup>=nKeyGroups ) {\n\t\tunsigned groupInfo= XkbKeyGroupInfo(xkb,key);\n\t\tswitch (XkbOutOfRangeGroupAction(groupInfo)) {\n\t\tdefault:\n\t\t\teffectiveGroup %= nKeyGroups;\n\t\t\tbreak;\n\t\tcase XkbClampIntoRange:\n\t\t\teffectiveGroup = nKeyGroups-1;\n\t\t\tbreak;\n\t\tcase XkbRedirectIntoRange:\n\t\t\teffectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);\n\t\t\tif (effectiveGroup>=nKeyGroups)\n\t\t\t\teffectiveGroup= 0;\n\t\t\tbreak;\n\t\t}\n\t}\n\tcol= effectiveGroup*XkbKeyGroupsWidth(xkb,key);\n\ttype = XkbKeyKeyType(xkb,key,effectiveGroup);\n\n\tpreserve= 0;\n\tif (type->map) { /* find the column (shift level) within the group */\n\t\tregister int i;\n\t\tregister XkbKTMapEntryPtr entry;\n\t\tfor (i=0,entry=type->map;i<type->map_count;i++,entry++) {\n\t\t\tif ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {\n\t\t\t\tcol+= entry->level;\n\t\t\t\tif (type->preserve)\n\t\t\t\t\tpreserve= type->preserve[i].mask;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (keysym_rtrn!=NULL)\n\t\t*keysym_rtrn= syms[col];\n\tif (mods_rtrn)\n\t\t*mods_rtrn= type->mods.mask&(~preserve);\n\n\treturn (syms[col]!=NoSymbol);\n}\n\nstatic XkbAction *XkbKeyActionPtr(XkbDescPtr xkb, KeyCode key, unsigned int mods)\n{\n\tXkbKeyTypeRec *type;\n\tint col,nKeyGroups;\n\tunsigned effectiveGroup;\n\tXkbAction *acts;\n\n\tif (!XkbKeyHasActions(xkb, key))\n\t\treturn NULL;\n\n\tnKeyGroups= XkbKeyNumGroups(xkb,key);\n\tif ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0))\n\t\treturn NULL;\n\n\tacts = XkbKeyActionsPtr(xkb,key);\n\n\t/* find the offset of the effective group */\n\tcol = 0;\n\teffectiveGroup= XkbGroupForCoreState(mods);\n\tif ( effectiveGroup>=nKeyGroups ) {\n\t\tunsigned groupInfo= XkbKeyGroupInfo(xkb,key);\n\t\tswitch (XkbOutOfRangeGroupAction(groupInfo)) {\n\t\tdefault:\n\t\t\teffectiveGroup %= nKeyGroups;\n\t\t\tbreak;\n\t\tcase XkbClampIntoRange:\n\t\t\teffectiveGroup = nKeyGroups-1;\n\t\t\tbreak;\n\t\tcase XkbRedirectIntoRange:\n\t\t\teffectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);\n\t\t\tif (effectiveGroup>=nKeyGroups)\n\t\t\t\teffectiveGroup= 0;\n\t\t\tbreak;\n\t\t}\n\t}\n\tcol= effectiveGroup*XkbKeyGroupsWidth(xkb,key);\n\ttype = XkbKeyKeyType(xkb,key,effectiveGroup);\n\n\tif (type->map) { /* find the column (shift level) within the group */\n\t\tregister int i;\n\t\tregister XkbKTMapEntryPtr entry;\n\t\tfor (i=0,entry=type->map;i<type->map_count;i++,entry++) {\n\t\t\tif ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {\n\t\t\t\tcol+= entry->level;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn &acts[col];\n}\n\nstatic unsigned XkbKeyEffectiveGroup(XkbDescPtr xkb, KeyCode key, unsigned int mods)\n{\n\tint nKeyGroups;\n\tunsigned effectiveGroup;\n\n\tnKeyGroups= XkbKeyNumGroups(xkb,key);\n\tif ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0))\n\t\treturn 0;\n\n\teffectiveGroup= XkbGroupForCoreState(mods);\n\tif ( effectiveGroup>=nKeyGroups ) {\n\t\tunsigned groupInfo= XkbKeyGroupInfo(xkb,key);\n\t\tswitch (XkbOutOfRangeGroupAction(groupInfo)) {\n\t\tdefault:\n\t\t\teffectiveGroup %= nKeyGroups;\n\t\t\tbreak;\n\t\tcase XkbClampIntoRange:\n\t\t\teffectiveGroup = nKeyGroups-1;\n\t\t\tbreak;\n\t\tcase XkbRedirectIntoRange:\n\t\t\teffectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);\n\t\t\tif (effectiveGroup>=nKeyGroups)\n\t\t\t\teffectiveGroup= 0;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn effectiveGroup;\n}\n\nvoid vncPrepareInputDevices(void)\n{\n\t/*\n\t * Not ideal since these callbacks do not stack, but it's the only\n\t * decent way we can reliably catch events for both the slave and\n\t * master device.\n\t */\n\tmieqSetHandler(ET_KeyPress, vncXkbProcessDeviceEvent);\n\tmieqSetHandler(ET_KeyRelease, vncXkbProcessDeviceEvent);\n\n\txorg_list_init(&addedKeysyms);\n}\n\nunsigned vncGetKeyboardState(void)\n{\n\tDeviceIntPtr master;\n\n\tmaster = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);\n\treturn XkbStateFieldFromRec(&master->key->xkbInfo->state);\n}\n\nunsigned vncGetLevelThreeMask(void)\n{\n\tunsigned state;\n\tKeyCode keycode;\n\tXkbDescPtr xkb;\n\tXkbAction *act;\n\n\t/* Group state is still important */\n\tstate = vncGetKeyboardState();\n\tstate &= ~0xff;\n\n\tkeycode = vncKeysymToKeycode(XK_ISO_Level3_Shift, state, NULL);\n\tif (keycode == 0) {\n\t\tkeycode = vncKeysymToKeycode(XK_Mode_switch, state, NULL);\n\t\tif (keycode == 0)\n\t\t\treturn 0;\n\t}\n\n\txkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;\n\n\tact = XkbKeyActionPtr(xkb, keycode, state);\n\tif (act == NULL)\n\t\treturn 0;\n\tif (act->type != XkbSA_SetMods)\n\t\treturn 0;\n\n\tif (act->mods.flags & XkbSA_UseModMapMods)\n\t\treturn xkb->map->modmap[keycode];\n\telse\n\t\treturn act->mods.mask;\n}\n\nKeyCode vncPressShift(void)\n{\n\tunsigned state;\n\n\tXkbDescPtr xkb;\n\tunsigned int key;\n\n\tstate = vncGetKeyboardState();\n\tif (state & ShiftMask)\n\t\treturn 0;\n\n\txkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;\n\tfor (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {\n\t\tXkbAction *act;\n\t\tunsigned char mask;\n\n\t\tact = XkbKeyActionPtr(xkb, key, state);\n\t\tif (act == NULL)\n\t\t\tcontinue;\n\n\t\tif (act->type != XkbSA_SetMods)\n\t\t\tcontinue;\n\n\t\tif (act->mods.flags & XkbSA_UseModMapMods)\n\t\t\tmask = xkb->map->modmap[key];\n\t\telse\n\t\t\tmask = act->mods.mask;\n\n\t\tif ((mask & ShiftMask) == ShiftMask)\n\t\t\treturn key;\n\t}\n\n\treturn 0;\n}\n\nsize_t vncReleaseShift(KeyCode *keys, size_t maxKeys)\n{\n\tsize_t count;\n\n\tunsigned state;\n\n\tDeviceIntPtr master;\n\tXkbDescPtr xkb;\n\tunsigned int key;\n\n\tstate = vncGetKeyboardState();\n\tif (!(state & ShiftMask))\n\t\treturn 0;\n\n\tcount = 0;\n\n\tmaster = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);\n\txkb = master->key->xkbInfo->desc;\n\tfor (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {\n\t\tXkbAction *act;\n\t\tunsigned char mask;\n\n\t\tif (!key_is_down(master, key, KEY_PROCESSED))\n\t\t\tcontinue;\n\n\t\tact = XkbKeyActionPtr(xkb, key, state);\n\t\tif (act == NULL)\n\t\t\tcontinue;\n\n\t\tif (act->type != XkbSA_SetMods)\n\t\t\tcontinue;\n\n\t\tif (act->mods.flags & XkbSA_UseModMapMods)\n\t\t\tmask = xkb->map->modmap[key];\n\t\telse\n\t\t\tmask = act->mods.mask;\n\n\t\tif (!(mask & ShiftMask))\n\t\t\tcontinue;\n\n\t\tif (count >= maxKeys)\n\t\t\treturn 0;\n\n\t\tkeys[count++] = key;\n\t}\n\n\treturn count;\n}\n\nKeyCode vncPressLevelThree(void)\n{\n\tunsigned state, mask;\n\n\tKeyCode keycode;\n\tXkbDescPtr xkb;\n\tXkbAction *act;\n\n\tmask = vncGetLevelThreeMask();\n\tif (mask == 0)\n\t\treturn 0;\n\n\tstate = vncGetKeyboardState();\n\tif (state & mask)\n\t\treturn 0;\n\n\tkeycode = vncKeysymToKeycode(XK_ISO_Level3_Shift, state, NULL);\n\tif (keycode == 0) {\n\t\tkeycode = vncKeysymToKeycode(XK_Mode_switch, state, NULL);\n\t\tif (keycode == 0)\n\t\t\treturn 0;\n\t}\n\n\txkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;\n\n\tact = XkbKeyActionPtr(xkb, keycode, state);\n\tif (act == NULL)\n\t\treturn 0;\n\tif (act->type != XkbSA_SetMods)\n\t\treturn 0;\n\n\treturn keycode;\n}\n\nsize_t vncReleaseLevelThree(KeyCode *keys, size_t maxKeys)\n{\n\tsize_t count;\n\n\tunsigned state, mask;\n\n\tDeviceIntPtr master;\n\tXkbDescPtr xkb;\n\tunsigned int key;\n\n\tmask = vncGetLevelThreeMask();\n\tif (mask == 0)\n\t\treturn 0;\n\n\tstate = vncGetKeyboardState();\n\tif (!(state & mask))\n\t\treturn 0;\n\n\tcount = 0;\n\n\tmaster = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);\n\txkb = master->key->xkbInfo->desc;\n\tfor (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {\n\t\tXkbAction *act;\n\t\tunsigned char key_mask;\n\n\t\tif (!key_is_down(master, key, KEY_PROCESSED))\n\t\t\tcontinue;\n\n\t\tact = XkbKeyActionPtr(xkb, key, state);\n\t\tif (act == NULL)\n\t\t\tcontinue;\n\n\t\tif (act->type != XkbSA_SetMods)\n\t\t\tcontinue;\n\n\t\tif (act->mods.flags & XkbSA_UseModMapMods)\n\t\t\tkey_mask = xkb->map->modmap[key];\n\t\telse\n\t\t\tkey_mask = act->mods.mask;\n\n\t\tif (!(key_mask & mask))\n\t\t\tcontinue;\n\n\t\tif (count >= maxKeys)\n\t\t\treturn 0;\n\n\t\tkeys[count++] = key;\n\t}\n\n\treturn count;\n}\n\nKeyCode vncKeysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state)\n{\n\tXkbDescPtr xkb;\n\tunsigned int key; // KeyCode has insufficient range for the loop\n\tKeyCode fallback;\n\tKeySym ks;\n\tunsigned level_three_mask;\n\n\tif (new_state != NULL)\n\t\t*new_state = state;\n\n\tfallback = 0;\n\txkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;\n\tfor (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {\n\t\tunsigned int state_out;\n\t\tKeySym dummy;\n\t\tsize_t fakeIdx;\n\n\t\tXkbTranslateKeyCode(xkb, key, state, &state_out, &ks);\n\t\tif (ks == NoSymbol)\n\t\t\tcontinue;\n\n\t\t/*\n\t\t * Despite every known piece of documentation on\n\t\t * XkbTranslateKeyCode() stating that mods_rtrn returns\n\t\t * the unconsumed modifiers, in reality it always\n\t\t * returns the _potentially consumed_ modifiers.\n\t\t */\n\t\tstate_out = state & ~state_out;\n\t\tif (state_out & LockMask)\n\t\t\tXkbConvertCase(ks, &dummy, &ks);\n\n\t\tif (ks != keysym)\n\t\t\tcontinue;\n\n\t\t/*\n\t\t * Some keys are never sent by a real keyboard and are\n\t\t * used in the default layouts as a fallback for\n\t\t * modifiers. Make sure we use them last as some\n\t\t * applications can be confused by these normally\n\t\t * unused keys.\n\t\t */\n\t\tfor (fakeIdx = 0;\n\t\t     fakeIdx < sizeof(fakeKeys)/sizeof(fakeKeys[0]);\n\t\t     fakeIdx++) {\n\t\t\tif (key == fakeKeys[fakeIdx]) {\n\t\t\t\tif (fallback == 0)\n\t\t\t\t\tfallback = key;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (fakeIdx < sizeof(fakeKeys)/sizeof(fakeKeys[0]))\n\t\t\tcontinue;\n\n\t\treturn key;\n\t}\n\n\t/* Use the fallback key, if one was found */\n\tif (fallback != 0)\n\t\treturn fallback;\n\n\tif (new_state == NULL)\n\t\treturn 0;\n\n\t*new_state = (state & ~ShiftMask) |\n\t             ((state & ShiftMask) ? 0 : ShiftMask);\n\tkey = vncKeysymToKeycode(keysym, *new_state, NULL);\n\tif (key != 0)\n\t\treturn key;\n\n\tlevel_three_mask = vncGetLevelThreeMask();\n\tif (level_three_mask == 0)\n\t\treturn 0;\n\n\t*new_state = (state & ~level_three_mask) | \n\t             ((state & level_three_mask) ? 0 : level_three_mask);\n\tkey = vncKeysymToKeycode(keysym, *new_state, NULL);\n\tif (key != 0)\n\t\treturn key;\n\n\t*new_state = (state & ~(ShiftMask | level_three_mask)) | \n\t             ((state & ShiftMask) ? 0 : ShiftMask) |\n\t             ((state & level_three_mask) ? 0 : level_three_mask);\n\tkey = vncKeysymToKeycode(keysym, *new_state, NULL);\n\tif (key != 0)\n\t\treturn key;\n\n\treturn 0;\n}\n\nint vncIsAffectedByNumLock(KeyCode keycode)\n{\n\tunsigned state;\n\n\tKeyCode numlock_keycode;\n\tunsigned numlock_mask;\n\n\tXkbDescPtr xkb;\n\tXkbAction *act;\n\n\tunsigned group;\n\tXkbKeyTypeRec *type;\n\n\t/* Group state is still important */\n\tstate = vncGetKeyboardState();\n\tstate &= ~0xff;\n\n\t/*\n\t * Not sure if hunting for a virtual modifier called \"NumLock\",\n\t * or following the keysym Num_Lock is the best approach. We\n\t * try the latter.\n\t */\n\tnumlock_keycode = vncKeysymToKeycode(XK_Num_Lock, state, NULL);\n\tif (numlock_keycode == 0)\n\t\treturn 0;\n\n\txkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;\n\n\tact = XkbKeyActionPtr(xkb, numlock_keycode, state);\n\tif (act == NULL)\n\t\treturn 0;\n\tif (act->type != XkbSA_LockMods)\n\t\treturn 0;\n\n\tif (act->mods.flags & XkbSA_UseModMapMods)\n\t\tnumlock_mask = xkb->map->modmap[keycode];\n\telse\n\t\tnumlock_mask = act->mods.mask;\n\n\tgroup = XkbKeyEffectiveGroup(xkb, keycode, state);\n\ttype = XkbKeyKeyType(xkb, keycode, group);\n\tif ((type->mods.mask & numlock_mask) == 0)\n\t\treturn 0;\n\n\treturn 1;\n}\n\nstatic void saveAddedKeysym(KeyCode code, KeySym sym)\n{\n\tAddedKeySym* item;\n\n\titem = malloc(sizeof(AddedKeySym));\n\tif (!item)\n\t\treturn;\n\n\titem->keycode = code;\n\titem->keysym = sym;\n\txorg_list_add(&item->entry, &addedKeysyms);\n}\n\n/*\n * Keeps the list in LRU order by moving the used key to front of the list.\n */\nvoid vncOnKeyUsed(KeyCode usedKeycode)\n{\n\tAddedKeySym* it;\n\n\tif (xorg_list_is_empty(&addedKeysyms))\n\t\treturn;\n\n\tit = xorg_list_first_entry(&addedKeysyms, AddedKeySym, entry);\n\tif (it->keycode == usedKeycode)\n\t\treturn;\n\n\txorg_list_for_each_entry(it, &addedKeysyms, entry) {\n\t\tif (it->keycode == usedKeycode) {\n\t\t\txorg_list_del(&it->entry);\n\t\t\txorg_list_add(&it->entry, &addedKeysyms);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/*\n * Returns keycode of oldest item from list of manually added keysyms.\n * The item is removed from the list.\n * Returns 0 if no usable keycode is found.\n */\nstatic KeyCode getReusableKeycode(XkbDescPtr xkb)\n{\n\tAddedKeySym* last;\n\tKeyCode result;\n\n\tresult = 0;\n\twhile (result == 0 && !xorg_list_is_empty(&addedKeysyms)) {\n\t\tlast = xorg_list_last_entry(&addedKeysyms, AddedKeySym, entry);\n\n\t\t// Make sure someone else hasn't modified the key\n\t\tif (XkbKeyNumGroups(xkb, last->keycode) > 0 &&\n\t\t\tXkbKeySymsPtr(xkb, last->keycode)[0] == last->keysym &&\n\t\t\t(xkb->names == NULL || xkb->names->keys[last->keycode].name[0] == 'T'))\n\t\t\tresult = last->keycode;\n\n\t\txorg_list_del(&last->entry);\n\t\tfree(last);\n\t}\n\treturn result;\n}\n\nKeyCode vncAddKeysym(KeySym keysym, unsigned state)\n{\n\tDeviceIntPtr master;\n\tXkbDescPtr xkb;\n\tunsigned int key;\n\n\tXkbEventCauseRec cause;\n\tXkbChangesRec changes;\n\n\tint types[1];\n\tKeySym *syms;\n\tKeySym upper, lower;\n\n\tmaster = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);\n\txkb = master->key->xkbInfo->desc;\n\tfor (key = xkb->max_key_code; key >= xkb->min_key_code; key--) {\n\t\tif (XkbKeyNumGroups(xkb, key) == 0)\n\t\t\tbreak;\n\t}\n\n\tif (key < xkb->min_key_code)\n\t\tkey = getReusableKeycode(xkb);\n\n\tif (!key)\n\t\treturn 0;\n\n\tmemset(&changes, 0, sizeof(changes));\n\tmemset(&cause, 0, sizeof(cause));\n\n\tXkbSetCauseUnknown(&cause);\n\n\t/*\n\t * Tools like xkbcomp get confused if there isn't a name\n\t * assigned to the keycode we're trying to use.\n\t */\n\tif (xkb->names && xkb->names->keys) {\n\t\txkb->names->keys[key].name[0] = 'T';\n\t\txkb->names->keys[key].name[1] = '0' + (key / 100) % 10;\n\t\txkb->names->keys[key].name[2] = '0' + (key /  10) % 10;\n\t\txkb->names->keys[key].name[3] = '0' + (key /   1) % 10;\n\n\t\tchanges.names.changed |= XkbKeyNamesMask;\n\t\tchanges.names.first_key = key;\n\t\tchanges.names.num_keys = 1;\n\t}\n\n\t/* FIXME: Verify that ONE_LEVEL/ALPHABETIC isn't screwed up */\n\n\t/*\n\t * For keysyms that are affected by Lock, we are better off\n\t * using ALPHABETIC rather than ONE_LEVEL as the latter\n\t * generally cannot produce lower case when Lock is active.\n\t */\n\tXkbConvertCase(keysym, &lower, &upper);\n\tif (upper == lower)\n\t\ttypes[XkbGroup1Index] = XkbOneLevelIndex;\n\telse\n\t\ttypes[XkbGroup1Index] = XkbAlphabeticIndex;\n\n\tXkbChangeTypesOfKey(xkb, key, 1, XkbGroup1Mask, types, &changes.map);\n\n\tsyms = XkbKeySymsPtr(xkb,key);\n\tif (upper == lower)\n\t\tsyms[0] = keysym;\n\telse {\n\t\tsyms[0] = lower;\n\t\tsyms[1] = upper;\n\t}\n\n\tchanges.map.changed |= XkbKeySymsMask;\n\tchanges.map.first_key_sym = key;\n\tchanges.map.num_key_syms = 1;\n\n\tXkbSendNotification(master, &changes, &cause);\n\n\tsaveAddedKeysym(key, syms[0]);\n\n\treturn key;\n}\n\nstatic void vncXkbProcessDeviceEvent(int screenNum,\n                                     InternalEvent *event,\n                                     DeviceIntPtr dev)\n{\n\tunsigned int backupctrls;\n\tXkbControlsPtr ctrls;\n\n\tif (event->device_event.sourceid != vncKeyboardDev->id) {\n\t\tdev->public.processInputProc(event, dev);\n\t\treturn;\n\t}\n\n\t/*\n\t * We need to bypass AccessX since it is timing sensitive and\n\t * the network can cause fake event delays.\n\t */\n\tctrls = dev->key->xkbInfo->desc->ctrls;\n\tbackupctrls = ctrls->enabled_ctrls;\n\tctrls->enabled_ctrls &= ~XkbAllFilteredEventsMask;\n\n\t/*\n\t * This flag needs to be set for key repeats to be properly\n\t * respected.\n\t */\n\tif ((event->device_event.type == ET_KeyPress) &&\n\t    key_is_down(dev, event->device_event.detail.key, KEY_PROCESSED))\n\t\tevent->device_event.key_repeat = TRUE;\n\n\tdev->public.processInputProc(event, dev);\n\n\tctrls->enabled_ctrls = backupctrls;\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncModule.c",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2015 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n/*  This is the xf86 module code for the vnc extension.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include \"opaque.h\"\n#include \"randrstr.h\"\n\n#include \"xorg-version.h\"\n\n#include \"xf86.h\"\n#include \"xf86Module.h\"\n\n#include \"vncExtInit.h\"\n#include \"RFBGlue.h\"\n#include \"XorgGlue.h\"\n#include \"RandrGlue.h\"\n\nstatic void vncModuleInit(void);\n\nstatic MODULESETUPPROTO(vncSetup);\n\nExtensionModule vncExt =\n{\n    vncModuleInit,\n    \"VNC\",\n    NULL\n};\n\nstatic XF86ModuleVersionInfo vncVersRec =\n{\n    \"vnc\",\n    \"TigerVNC\",\n    MODINFOSTRING1,\n    MODINFOSTRING2,\n    VENDOR_RELEASE,\n    1, 0, 0,\n    ABI_CLASS_EXTENSION,         /* needs the server extension ABI */\n    ABI_EXTENSION_VERSION,\n    MOD_CLASS_EXTENSION,\n    {0,0,0,0}\n};\n\n_X_EXPORT XF86ModuleData vncModuleData = { &vncVersRec, vncSetup, NULL };\n\nstatic void *\nvncSetup(void * module, void * opts, int *errmaj, int *errmin) {\n    LoadExtensionList(&vncExt, 1, FALSE);\n    /* Need a non-NULL return value to indicate success */\n    return (void *)1;\n}\n\nstatic void vncModuleInit(void)\n{\n  static char once = 0;\n\n  if (!once) {\n    once++;\n\n    vncInitRFB();\n\n    for (int scr = 0; scr < screenInfo.numScreens; scr++) {\n      ScrnInfoPtr pScrn;\n      XF86OptionPtr option;\n\n      pScrn = xf86Screens[scr];\n      option = pScrn->options;\n      while (option != NULL) {\n        vncSetParam(xf86OptionName(option), xf86OptionValue(option));\n        option = xf86NextOption(option);\n      }\n    }\n  }\n\n  vncExtensionInit();\n}\n\nvoid vncClientGone(int fd)\n{\n}\n\nint vncRandRCanCreateScreenOutputs(int scrIdx, int extraOutputs)\n{\n  return 0;\n}\n\nint vncRandRCreateScreenOutputs(int scrIdx, int extraOutputs)\n{\n  return 0;\n}\n\nint vncRandRCanCreateModes(void)\n{\n  return 0;\n}\n\nvoid* vncRandRCreateMode(void* output, int width, int height)\n{\n  return 0;\n}\n\nvoid* vncRandRSetPreferredMode(void* output, void* mode)\n{\n  /*\n   * We're not going to change which modes are preferred,\n   * so just return the incoming mode.\n   */\n  return mode;\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncPresent.c",
    "content": "/* Copyright 2024 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include \"vncExtInit.h\"\n#include \"vncPresent.h\"\n\n#include <present.h>\n\nstatic RRCrtcPtr vncPresentGetCrtc(WindowPtr window)\n{\n  ScreenPtr pScreen = window->drawable.pScreen;\n  rrScrPrivPtr rp = rrGetScrPriv(pScreen);\n\n  /* All output is synchronized, so just pick the first active crtc */\n  for (int c = 0; c < rp->numCrtcs; c++) {\n    RRCrtcPtr crtc;\n\n    crtc = rp->crtcs[c];\n    if (crtc->mode == NULL)\n      continue;\n\n    return crtc;\n  }\n\n  return NULL;\n}\n\nstatic int vncPresentGetUstMsc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)\n{\n  *ust = GetTimeInMicros();\n  *msc = vncGetMsc(crtc->pScreen->myNum);\n\n  return Success;\n}\n\nstatic int vncPresentQueueVBlank(RRCrtcPtr crtc, uint64_t event_id,\n                                 uint64_t msc)\n{\n  vncQueueMsc(crtc->pScreen->myNum, event_id, msc);\n  return Success;\n}\n\nvoid vncPresentMscEvent(uint64_t id, uint64_t msc)\n{\n  present_event_notify(id, GetTimeInMicros(), msc);\n}\n\nstatic void vncPresentAbortVBlank(RRCrtcPtr crtc, uint64_t event_id,\n                                  uint64_t msc)\n{\n  vncAbortMsc(crtc->pScreen->myNum, event_id);\n}\n\nstatic void vncPresentFlush(WindowPtr window)\n{\n}\n\nstatic present_screen_info_rec vncPresentScreenInfo = {\n  .version = PRESENT_SCREEN_INFO_VERSION,\n\n  .get_crtc = vncPresentGetCrtc,\n  .get_ust_msc = vncPresentGetUstMsc,\n  .queue_vblank = vncPresentQueueVBlank,\n  .abort_vblank = vncPresentAbortVBlank,\n  .flush = vncPresentFlush,\n\n  .capabilities = PresentCapabilityNone,\n};\n\nBool\nvncPresentInit(ScreenPtr screen)\n{\n  return present_screen_init(screen, &vncPresentScreenInfo);\n}"
  },
  {
    "path": "unix/xserver/hw/vnc/vncPresent.h",
    "content": "/* Copyright 2024 Pierre Ossman for Cendio AB\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __PRESENT_H__\n#define __PRESENT_H__\n\n#include <dix.h>\n\nBool vncPresentInit(ScreenPtr screen);\nvoid vncPresentMscEvent(uint64_t id, uint64_t msc);\n\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncSelection.c",
    "content": "/* Copyright 2016-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include <X11/Xatom.h>\n\n#include \"propertyst.h\"\n#include \"scrnintstr.h\"\n#include \"selection.h\"\n#include \"windowstr.h\"\n#include \"xace.h\"\n\n#include \"xorg-version.h\"\n\n#include \"vncExtInit.h\"\n#include \"vncSelection.h\"\n#include \"RFBGlue.h\"\n\n#define LOG_NAME \"Selection\"\n\n#define LOG_ERROR(...) vncLogError(LOG_NAME, __VA_ARGS__)\n#define LOG_STATUS(...) vncLogStatus(LOG_NAME, __VA_ARGS__)\n#define LOG_INFO(...) vncLogInfo(LOG_NAME, __VA_ARGS__)\n#define LOG_DEBUG(...) vncLogDebug(LOG_NAME, __VA_ARGS__)\n\nstatic Atom xaPRIMARY, xaCLIPBOARD;\nstatic Atom xaTARGETS, xaTIMESTAMP, xaSTRING, xaTEXT, xaUTF8_STRING;\n\nstatic WindowPtr pWindow;\nstatic Window wid;\n\nstatic Bool probing;\nstatic Atom activeSelection = None;\n\nstatic char* cachedData = NULL;\n\nstruct VncDataTarget {\n  ClientPtr client;\n  Atom selection;\n  Atom target;\n  Atom property;\n  Window requestor;\n  CARD32 time;\n  struct VncDataTarget* next;\n};\n\nstatic struct VncDataTarget* vncDataTargetHead;\n\nstatic int vncCreateSelectionWindow(void);\nstatic int vncOwnSelection(Atom selection);\nstatic int vncConvertSelection(ClientPtr client, Atom selection,\n                               Atom target, Atom property,\n                               Window requestor, CARD32 time,\n                               const char* data);\nstatic int vncProcConvertSelection(ClientPtr client);\nstatic void vncSelectionRequest(Atom selection, Atom target);\nstatic int vncProcSendEvent(ClientPtr client);\nstatic void vncSelectionCallback(CallbackListPtr *callbacks,\n                                 void * data, void * args);\nstatic void vncClientStateCallback(CallbackListPtr * l,\n                                   void * d, void * p);\n\nstatic int (*origProcConvertSelection)(ClientPtr);\nstatic int (*origProcSendEvent)(ClientPtr);\n\nvoid vncSelectionInit(void)\n{\n  xaPRIMARY = MakeAtom(\"PRIMARY\", 7, TRUE);\n  xaCLIPBOARD = MakeAtom(\"CLIPBOARD\", 9, TRUE);\n\n  xaTARGETS = MakeAtom(\"TARGETS\", 7, TRUE);\n  xaTIMESTAMP = MakeAtom(\"TIMESTAMP\", 9, TRUE);\n  xaSTRING = MakeAtom(\"STRING\", 6, TRUE);\n  xaTEXT = MakeAtom(\"TEXT\", 4, TRUE);\n  xaUTF8_STRING = MakeAtom(\"UTF8_STRING\", 11, TRUE);\n\n  /* There are no hooks for when these are internal windows, so\n   * override the relevant handlers. */\n  origProcConvertSelection = ProcVector[X_ConvertSelection];\n  ProcVector[X_ConvertSelection] = vncProcConvertSelection;\n  origProcSendEvent = ProcVector[X_SendEvent];\n  ProcVector[X_SendEvent] = vncProcSendEvent;\n\n  if (!AddCallback(&SelectionCallback, vncSelectionCallback, 0))\n    FatalError(\"Add VNC SelectionCallback failed\\n\");\n  if (!AddCallback(&ClientStateCallback, vncClientStateCallback, 0))\n    FatalError(\"Add VNC ClientStateCallback failed\\n\");\n}\n\nvoid vncHandleClipboardRequest(void)\n{\n  if (activeSelection == None) {\n    LOG_DEBUG(\"Got request for local clipboard although no clipboard is active\");\n    return;\n  }\n\n  LOG_DEBUG(\"Got request for local clipboard, re-probing formats\");\n\n  probing = FALSE;\n  vncSelectionRequest(activeSelection, xaTARGETS);\n}\n\nvoid vncHandleClipboardAnnounce(int available)\n{\n  /* The data has changed in some way, so whatever is in our cache is\n   * now stale */\n  free(cachedData);\n  cachedData = NULL;\n\n  if (available) {\n    int rc;\n\n    LOG_DEBUG(\"Remote clipboard announced, grabbing local ownership\");\n\n    if (vncGetSetPrimary()) {\n      rc = vncOwnSelection(xaPRIMARY);\n      if (rc != Success)\n        LOG_ERROR(\"Could not set PRIMARY selection\");\n    }\n\n    rc = vncOwnSelection(xaCLIPBOARD);\n    if (rc != Success)\n      LOG_ERROR(\"Could not set CLIPBOARD selection\");\n  } else {\n    struct VncDataTarget* next;\n\n    if (pWindow == NULL)\n      return;\n\n    LOG_DEBUG(\"Remote clipboard lost, removing local ownership\");\n\n    DeleteWindowFromAnySelections(pWindow);\n\n    /* Abort any pending transfer */\n    while (vncDataTargetHead != NULL) {\n      xEvent event;\n\n      event.u.u.type = SelectionNotify;\n      event.u.selectionNotify.time = vncDataTargetHead->time;\n      event.u.selectionNotify.requestor = vncDataTargetHead->requestor;\n      event.u.selectionNotify.selection = vncDataTargetHead->selection;\n      event.u.selectionNotify.target = vncDataTargetHead->target;\n      event.u.selectionNotify.property = None;\n      WriteEventsToClient(vncDataTargetHead->client, 1, &event);\n\n      next = vncDataTargetHead->next;\n      free(vncDataTargetHead);\n      vncDataTargetHead = next;\n    }\n  }\n}\n\nvoid vncHandleClipboardData(const char* data)\n{\n  struct VncDataTarget* next;\n\n  LOG_DEBUG(\"Got remote clipboard data, sending to X11 clients\");\n\n  free(cachedData);\n  cachedData = strdup(data);\n\n  while (vncDataTargetHead != NULL) {\n    int rc;\n    xEvent event;\n\n    rc = vncConvertSelection(vncDataTargetHead->client,\n                             vncDataTargetHead->selection,\n                             vncDataTargetHead->target,\n                             vncDataTargetHead->property,\n                             vncDataTargetHead->requestor,\n                             vncDataTargetHead->time,\n                             cachedData);\n    if (rc != Success) {\n      event.u.u.type = SelectionNotify;\n      event.u.selectionNotify.time = vncDataTargetHead->time;\n      event.u.selectionNotify.requestor = vncDataTargetHead->requestor;\n      event.u.selectionNotify.selection = vncDataTargetHead->selection;\n      event.u.selectionNotify.target = vncDataTargetHead->target;\n      event.u.selectionNotify.property = None;\n      WriteEventsToClient(vncDataTargetHead->client, 1, &event);\n    }\n\n    next = vncDataTargetHead->next;\n    free(vncDataTargetHead);\n    vncDataTargetHead = next;\n  }\n}\n\nstatic int vncCreateSelectionWindow(void)\n{\n  ScreenPtr pScreen;\n  int result;\n\n  if (pWindow != NULL)\n    return Success;\n\n  pScreen = screenInfo.screens[0];\n\n  wid = FakeClientID(0);\n  pWindow = CreateWindow(wid, pScreen->root,\n                         0, 0, 100, 100, 0, InputOnly,\n                         0, NULL, 0, serverClient,\n                         CopyFromParent, &result);\n  if (!pWindow)\n    return result;\n\n  if (!AddResource(pWindow->drawable.id, RT_WINDOW, pWindow))\n      return BadAlloc;\n\n  LOG_DEBUG(\"Created selection window\");\n\n  return Success;\n}\n\nstatic int vncOwnSelection(Atom selection)\n{\n  Selection *pSel;\n  int rc;\n\n  SelectionInfoRec info;\n\n  rc = vncCreateSelectionWindow();\n  if (rc != Success)\n    return rc;\n\n  rc = dixLookupSelection(&pSel, selection, serverClient, DixSetAttrAccess);\n  if (rc == Success) {\n    if (pSel->client && (pSel->client != serverClient)) {\n      xEvent event = {\n        .u.selectionClear.time = currentTime.milliseconds,\n        .u.selectionClear.window = pSel->window,\n        .u.selectionClear.atom = pSel->selection\n      };\n      event.u.u.type = SelectionClear;\n      WriteEventsToClient(pSel->client, 1, &event);\n    }\n  } else if (rc == BadMatch) {\n    pSel = dixAllocateObjectWithPrivates(Selection, PRIVATE_SELECTION);\n    if (!pSel)\n      return BadAlloc;\n\n    pSel->selection = selection;\n\n    rc = XaceHookSelectionAccess(serverClient, &pSel,\n                                 DixCreateAccess | DixSetAttrAccess);\n    if (rc != Success) {\n        free(pSel);\n        return rc;\n    }\n\n    pSel->next = CurrentSelections;\n    CurrentSelections = pSel;\n  }\n  else\n      return rc;\n\n  pSel->lastTimeChanged = currentTime;\n  pSel->window = wid;\n  pSel->pWin = pWindow;\n  pSel->client = serverClient;\n\n  LOG_DEBUG(\"Grabbed %s selection\", NameForAtom(selection));\n\n  info.selection = pSel;\n  info.client = serverClient;\n  info.kind = SelectionSetOwner;\n  CallCallbacks(&SelectionCallback, &info);\n\n  return Success;\n}\n\nstatic Bool vncWeAreOwner(Atom selection)\n{\n  Selection *pSel;\n  int rc;\n\n  rc = dixLookupSelection(&pSel, selection, serverClient, DixReadAccess);\n  if (rc != Success)\n    return FALSE;\n\n  if (pSel->client != serverClient)\n    return FALSE;\n\n  if (pSel->window != wid)\n    return FALSE;\n\n  return TRUE;\n}\n\nstatic void vncMaybeRequestCache(void)\n{\n  /* Telling a client that we have clipboard data will likely mean that\n   * we can no longer request its clipboard data. This is a problem as\n   * we might initially own multiple selections and we now just lost\n   * one, and we still want to be able to service the other one. Solve\n   * this by requesting the data from the client when we can't affort to\n   * lose it and cache it. */\n\n  /* Already cached? */\n  if (cachedData != NULL)\n    return;\n\n  if (!vncWeAreOwner(xaCLIPBOARD)) {\n    if (!vncGetSetPrimary())\n      return;\n    if (!vncWeAreOwner(xaPRIMARY))\n      return;\n  }\n\n  LOG_DEBUG(\"Requesting clipboard data from client for caching\");\n\n  vncRequestClipboard();\n}\n\nstatic int vncConvertSelection(ClientPtr client, Atom selection,\n                               Atom target, Atom property,\n                               Window requestor, CARD32 time,\n                               const char* data)\n{\n  Selection *pSel;\n  WindowPtr pWin;\n  int rc;\n\n  Atom realProperty;\n\n  xEvent event;\n\n  if (data == NULL) {\n    LOG_DEBUG(\"Selection request for %s (type %s)\",\n              NameForAtom(selection), NameForAtom(target));\n  } else {\n    LOG_DEBUG(\"Sending data for selection request for %s (type %s)\",\n              NameForAtom(selection), NameForAtom(target));\n  }\n\n  rc = dixLookupSelection(&pSel, selection, client, DixGetAttrAccess);\n  if (rc != Success)\n    return rc;\n\n  /* We do not validate the time argument because neither does\n   * dix/selection.c and some clients (e.g. Qt) relies on this */\n\n  rc = dixLookupWindow(&pWin, requestor, client, DixSetAttrAccess);\n  if (rc != Success)\n    return rc;\n\n  if (property != None)\n    realProperty = property;\n  else\n    realProperty = target;\n\n  /* FIXME: MULTIPLE target */\n\n  if (target == xaTARGETS) {\n    Atom targets[] = { xaTARGETS, xaTIMESTAMP,\n                       xaSTRING, xaTEXT, xaUTF8_STRING };\n\n    rc = dixChangeWindowProperty(serverClient, pWin, realProperty,\n                                 XA_ATOM, 32, PropModeReplace,\n                                 sizeof(targets)/sizeof(targets[0]),\n                                 targets, TRUE);\n    if (rc != Success)\n      return rc;\n  } else if (target == xaTIMESTAMP) {\n    rc = dixChangeWindowProperty(serverClient, pWin, realProperty,\n                                 XA_INTEGER, 32, PropModeReplace, 1,\n                                 &pSel->lastTimeChanged.milliseconds,\n                                 TRUE);\n    if (rc != Success)\n      return rc;\n  } else {\n    if (data == NULL) {\n      struct VncDataTarget* vdt;\n\n      if ((target != xaSTRING) && (target != xaTEXT) &&\n          (target != xaUTF8_STRING))\n        return BadMatch;\n\n      vdt = calloc(1, sizeof(struct VncDataTarget));\n      if (vdt == NULL)\n        return BadAlloc;\n\n      vdt->client = client;\n      vdt->selection = selection;\n      vdt->target = target;\n      vdt->property = property;\n      vdt->requestor = requestor;\n      vdt->time = time;\n\n      vdt->next = vncDataTargetHead;\n      vncDataTargetHead = vdt;\n\n      LOG_DEBUG(\"Requesting clipboard data from client\");\n\n      vncRequestClipboard();\n\n      return Success;\n    } else {\n      if ((target == xaSTRING) || (target == xaTEXT)) {\n        char* latin1;\n\n        latin1 = vncUTF8ToLatin1(data, (size_t)-1);\n        if (latin1 == NULL)\n          return BadAlloc;\n\n        rc = dixChangeWindowProperty(serverClient, pWin, realProperty,\n                                     XA_STRING, 8, PropModeReplace,\n                                     strlen(latin1), latin1, TRUE);\n\n        free(latin1);\n\n        if (rc != Success)\n          return rc;\n      } else if (target == xaUTF8_STRING) {\n        rc = dixChangeWindowProperty(serverClient, pWin, realProperty,\n                                     xaUTF8_STRING, 8, PropModeReplace,\n                                     strlen(data), data, TRUE);\n        if (rc != Success)\n          return rc;\n      } else {\n        return BadMatch;\n      }\n    }\n  }\n\n  event.u.u.type = SelectionNotify;\n  event.u.selectionNotify.time = time;\n  event.u.selectionNotify.requestor = requestor;\n  event.u.selectionNotify.selection = selection;\n  event.u.selectionNotify.target = target;\n  event.u.selectionNotify.property = property;\n  WriteEventsToClient(client, 1, &event);\n  return Success;\n}\n\nstatic int vncProcConvertSelection(ClientPtr client)\n{\n  Bool paramsOkay;\n  WindowPtr pWin;\n  Selection *pSel;\n  int rc;\n\n  REQUEST(xConvertSelectionReq);\n  REQUEST_SIZE_MATCH(xConvertSelectionReq);\n\n  rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess);\n  if (rc != Success)\n    return rc;\n\n  paramsOkay = ValidAtom(stuff->selection) && ValidAtom(stuff->target);\n  paramsOkay &= (stuff->property == None) || ValidAtom(stuff->property);\n  if (!paramsOkay) {\n    client->errorValue = stuff->property;\n    return BadAtom;\n  }\n\n  /* Do we own this selection? */\n  rc = dixLookupSelection(&pSel, stuff->selection, client, DixReadAccess);\n  if (rc == Success && pSel->client == serverClient &&\n      pSel->window == wid) {\n    /* cachedData will be NULL for the first request, but can then be\n     * reused once we've gotten the data once from the client */\n    rc = vncConvertSelection(client, stuff->selection,\n                             stuff->target, stuff->property,\n                             stuff->requestor, stuff->time,\n                             cachedData);\n    if (rc != Success) {\n      xEvent event;\n\n      memset(&event, 0, sizeof(xEvent));\n      event.u.u.type = SelectionNotify;\n      event.u.selectionNotify.time = stuff->time;\n      event.u.selectionNotify.requestor = stuff->requestor;\n      event.u.selectionNotify.selection = stuff->selection;\n      event.u.selectionNotify.target = stuff->target;\n      event.u.selectionNotify.property = None;\n      WriteEventsToClient(client, 1, &event);\n    }\n\n    return Success;\n  }\n\n  return origProcConvertSelection(client);\n}\n\nstatic void vncSelectionRequest(Atom selection, Atom target)\n{\n  Selection *pSel;\n  xEvent event;\n  int rc;\n\n  rc = vncCreateSelectionWindow();\n  if (rc != Success)\n    return;\n\n  LOG_DEBUG(\"Requesting %s for %s selection\",\n            NameForAtom(target), NameForAtom(selection));\n\n  rc = dixLookupSelection(&pSel, selection, serverClient, DixGetAttrAccess);\n  if (rc != Success)\n    return;\n\n  event.u.u.type = SelectionRequest;\n  event.u.selectionRequest.owner = pSel->window;\n  event.u.selectionRequest.time = currentTime.milliseconds;\n  event.u.selectionRequest.requestor = wid;\n  event.u.selectionRequest.selection = selection;\n  event.u.selectionRequest.target = target;\n  event.u.selectionRequest.property = target;\n  WriteEventsToClient(pSel->client, 1, &event);\n}\n\nstatic Bool vncHasAtom(Atom atom, const Atom list[], size_t size)\n{\n  size_t i;\n\n  for (i = 0;i < size;i++) {\n    if (list[i] == atom)\n      return TRUE;\n  }\n\n  return FALSE;\n}\n\nstatic void vncHandleSelection(Atom selection, Atom target,\n                               Atom property, Atom requestor,\n                               TimeStamp time)\n{\n  PropertyPtr prop;\n  int rc;\n\n  rc = dixLookupProperty(&prop, pWindow, property,\n                         serverClient, DixReadAccess);\n  if (rc != Success)\n    return;\n\n  LOG_DEBUG(\"Selection notification for %s (target %s, property %s, type %s)\",\n            NameForAtom(selection), NameForAtom(target),\n            NameForAtom(property), NameForAtom(prop->type));\n\n  if (target != property)\n    return;\n\n  if (target == xaTARGETS) {\n    if (prop->format != 32)\n      return;\n    if (prop->type != XA_ATOM)\n      return;\n\n    if (probing) {\n      if (vncHasAtom(xaSTRING, (const Atom*)prop->data, prop->size) ||\n          vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size)) {\n        vncMaybeRequestCache();\n        LOG_DEBUG(\"Compatible format found, notifying clients\");\n        activeSelection = selection;\n        vncAnnounceClipboard(TRUE);\n      }\n    } else {\n      if (vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size))\n        vncSelectionRequest(selection, xaUTF8_STRING);\n      else if (vncHasAtom(xaSTRING, (const Atom*)prop->data, prop->size))\n        vncSelectionRequest(selection, xaSTRING);\n    }\n  } else if (target == xaSTRING) {\n    char* filtered;\n    char* utf8;\n\n    if (prop->format != 8)\n      return;\n    if (prop->type != xaSTRING)\n      return;\n\n    filtered = vncConvertLF(prop->data, prop->size);\n    if (filtered == NULL)\n      return;\n\n    utf8 = vncLatin1ToUTF8(filtered, (size_t)-1);\n    free(filtered);\n    if (utf8 == NULL)\n      return;\n\n    LOG_DEBUG(\"Sending clipboard to clients (%d bytes)\",\n              (int)strlen(utf8));\n\n    vncSendClipboardData(utf8);\n\n    free(utf8);\n  } else if (target == xaUTF8_STRING) {\n    char *filtered;\n\n    if (prop->format != 8)\n      return;\n    if (prop->type != xaUTF8_STRING)\n      return;\n\n    if (!vncIsValidUTF8(prop->data, prop->size)) {\n      LOG_ERROR(\"Invalid UTF-8 sequence in clipboard\");\n      return;\n    }\n\n    filtered = vncConvertLF(prop->data, prop->size);\n    if (filtered == NULL)\n      return;\n\n    LOG_DEBUG(\"Sending clipboard to clients (%d bytes)\",\n              (int)strlen(filtered));\n\n    vncSendClipboardData(filtered);\n\n    free(filtered);\n  }\n}\n\n#define SEND_EVENT_BIT 0x80\n\nstatic int vncProcSendEvent(ClientPtr client)\n{\n  REQUEST(xSendEventReq);\n  REQUEST_SIZE_MATCH(xSendEventReq);\n\n  stuff->event.u.u.type &= ~(SEND_EVENT_BIT);\n\n  if (stuff->event.u.u.type == SelectionNotify &&\n      stuff->event.u.selectionNotify.requestor == wid) {\n    TimeStamp time;\n    time = ClientTimeToServerTime(stuff->event.u.selectionNotify.time);\n    vncHandleSelection(stuff->event.u.selectionNotify.selection,\n                       stuff->event.u.selectionNotify.target,\n                       stuff->event.u.selectionNotify.property,\n                       stuff->event.u.selectionNotify.requestor,\n                       time);\n  }\n\n  return origProcSendEvent(client);\n}\n\nstatic void vncSelectionCallback(CallbackListPtr *callbacks,\n                                 void * data, void * args)\n{\n  SelectionInfoRec *info = (SelectionInfoRec *) args;\n\n  if (info->selection->selection == activeSelection) {\n    vncMaybeRequestCache();\n    LOG_DEBUG(\"Local clipboard lost, notifying clients\");\n    activeSelection = None;\n    vncAnnounceClipboard(FALSE);\n  }\n\n  if (info->kind != SelectionSetOwner)\n    return;\n  if (info->client == serverClient)\n    return;\n\n  LOG_DEBUG(\"Selection owner change for %s\",\n            NameForAtom(info->selection->selection));\n\n  if ((info->selection->selection != xaPRIMARY) &&\n      (info->selection->selection != xaCLIPBOARD))\n    return;\n\n  if ((info->selection->selection == xaPRIMARY) &&\n      !vncGetSendPrimary())\n    return;\n\n  LOG_DEBUG(\"Got clipboard notification, probing for formats\");\n\n  probing = TRUE;\n  vncSelectionRequest(info->selection->selection, xaTARGETS);\n}\n\nstatic void vncClientStateCallback(CallbackListPtr * l,\n                                   void * d, void * p)\n{\n  ClientPtr client = ((NewClientInfoRec*)p)->client;\n  if (client->clientState == ClientStateGone) {\n    struct VncDataTarget** nextPtr = &vncDataTargetHead;\n    for (struct VncDataTarget* cur = vncDataTargetHead; cur; cur = *nextPtr) {\n      if (cur->client == client) {\n        *nextPtr = cur->next;\n        free(cur);\n        continue;\n      }\n      nextPtr = &cur->next;\n    }\n  }\n}\n"
  },
  {
    "path": "unix/xserver/hw/vnc/vncSelection.h",
    "content": "/* Copyright 2016-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef __SELECTION_H__\n#define __SELECTION_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid vncSelectionInit(void);\n\nvoid vncHandleClipboardRequest(void);\nvoid vncHandleClipboardAnnounce(int available);\nvoid vncHandleClipboardData(const char* data);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/xorg-version.h",
    "content": "/* Copyright (C) 2009 TightVNC Team\n * Copyright (C) 2009 Red Hat, Inc.\n *\n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef XORG_VERSION_H\n#define XORG_VERSION_H\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include <version-config.h>\n\n#define XORG_AT_LEAST(major, minor, patch) \\\n    (VENDOR_RELEASE >= ((major * 10000000) + (minor * 100000) + (patch * 1000)))\n#define XORG_OLDER_THAN(major, minor, patch) \\\n    (VENDOR_RELEASE < ((major * 10000000) + (minor * 100000) + (patch * 1000)))\n\n#if XORG_OLDER_THAN(1, 20, 0)\n#error \"X.Org older than 1.20 is not supported\"\n#endif\n\n#if XORG_AT_LEAST(1, 22, 0)\n#error \"X.Org newer than 1.21 is not supported\"\n#endif\n\n#endif\n"
  },
  {
    "path": "unix/xserver/hw/vnc/xvnc.c",
    "content": "/* Copyright (c) 1993  X Consortium\n   Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n   Copyright 2009-2024 Pierre Ossman for Cendio AB\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nExcept as contained in this notice, the name of the X Consortium shall\nnot be used in advertising or otherwise to promote the sale, use or\nother dealings in this Software without prior written authorization\nfrom the X Consortium.\n\n*/\n\n#ifdef HAVE_DIX_CONFIG_H\n#include <dix-config.h>\n#endif\n\n#include \"vncExtInit.h\"\n#include \"RFBGlue.h\"\n#include \"XorgGlue.h\"\n#include \"RandrGlue.h\"\n#include \"vncDRI3.h\"\n#include \"vncPresent.h\"\n#include \"xorg-version.h\"\n\n#include <stdio.h>\n#ifdef HAVE_LIBXCVT\n#include <libxcvt/libxcvt.h>\n#endif\n#include <X11/X.h>\n#include <X11/Xproto.h>\n#include <X11/Xos.h>\n#include \"scrnintstr.h\"\n#include \"servermd.h\"\n#include \"fb.h\"\n#include \"mi.h\"\n#include \"gcstruct.h\"\n#include \"input.h\"\n#include \"mipointer.h\"\n#include \"micmap.h\"\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <errno.h>\n#include <sys/param.h>\n#include \"dix.h\"\n#include \"os.h\"\n#include \"miline.h\"\n#include \"glx_extinit.h\"\n#include \"inputstr.h\"\n#include \"randrstr.h\"\n#ifdef DPMSExtension\n#include \"dpmsproc.h\"\n#endif\n#include <X11/keysym.h>\nextern char buildtime[];\n\n#include \"version-config.h\"\n\n#define XVNCVERSION \"TigerVNC 1.16.80\"\n#define XVNCCOPYRIGHT (\"Copyright (C) 1999-2026 TigerVNC team and many others (see README.rst)\\n\" \\\n                       \"See https://www.tigervnc.org for information on TigerVNC.\\n\")\n\n#define VNC_DEFAULT_WIDTH  1024\n#define VNC_DEFAULT_HEIGHT 768\n#define VNC_DEFAULT_DEPTH  24\n\ntypedef struct {\n    int width;\n    int paddedBytesWidth;\n    int paddedWidth;\n    int height;\n    int depth;\n    int bitsPerPixel;\n    void *pfbMemory;\n} VncFramebufferInfo, *VncFramebufferInfoPtr;\n\ntypedef struct {\n    VncFramebufferInfo fb;\n\n    Bool pixelFormatDefined;\n    Bool rgbNotBgr;\n    int redBits, greenBits, blueBits;\n} VncScreenInfo, *VncScreenInfoPtr;\n\nstatic VncScreenInfo vncScreenInfo = {\n    .fb.width = VNC_DEFAULT_WIDTH,\n    .fb.height = VNC_DEFAULT_HEIGHT,\n    .fb.depth = VNC_DEFAULT_DEPTH,\n    .fb.pfbMemory = NULL,\n    .pixelFormatDefined = FALSE,\n};\n\nstatic Bool vncPixmapDepths[33];\nstatic Bool Render = TRUE;\n\nstatic char displayNumStr[16];\n\nstatic int vncVerbose = 0;\n\nstatic void\nvncPrintBanner(void)\n{\n    ErrorF(\"\\nXvnc %s - built %s\\n%s\", XVNCVERSION, buildtime, XVNCCOPYRIGHT);\n    ErrorF(\"Underlying X server release %d\\n\\n\", VENDOR_RELEASE);\n}\n\nstatic void\nvncInitializePixmapDepths(void)\n{\n    int i;\n\n    vncPixmapDepths[1] = TRUE;  /* always need bitmaps */\n    for (i = 2; i <= 32; i++)\n        vncPixmapDepths[i] = FALSE;\n}\n\nstatic int\nvncBitsPerPixel(int depth)\n{\n    if (depth == 1)\n        return 1;\n    else if (depth <= 8)\n        return 8;\n    else if (depth <= 16)\n        return 16;\n    else\n        return 32;\n}\n\nstatic void vncFreeFramebufferMemory(VncFramebufferInfoPtr pfb);\n\nvoid\nddxGiveUp(enum ExitCode error)\n{\n    /* clean up the framebuffers */\n    vncFreeFramebufferMemory(&vncScreenInfo.fb);\n}\n\n#if XORG_OLDER_THAN(1, 21, 1)\nvoid\nAbortDDX(enum ExitCode error)\n{\n    ddxGiveUp(error);\n}\n#endif\n\nvoid\nOsVendorInit(void)\n{\n    /* At this point, display has been set, so we can use it to\n     * initialize UnixPasswordValidator */\n    vncSetDisplayName(display);\n}\n\nvoid\nOsVendorFatalError(const char *f, va_list args)\n{\n}\n\n#ifdef DDXBEFORERESET\nvoid\nddxBeforeReset(void)\n{\n    return;\n}\n#endif\n\n#if INPUTTHREAD\n#if XORG_AT_LEAST(1, 20, 7)\n/** This function is called in Xserver/os/inputthread.c when starting\n    the input thread. */\nvoid\nddxInputThreadInit(void)\n{\n}\n#endif\n#endif\n\nvoid\nddxUseMsg(void)\n{\n    ErrorF(\"-pixdepths list-of-int support given pixmap depths\\n\");\n    ErrorF(\"+/-render\t\t   turn on/off RENDER extension support\"\n           \"(default on)\\n\");\n\n    ErrorF(\"-geometry WxH          set screen 0's width, height\\n\");\n    ErrorF(\"-depth D               set screen 0's depth\\n\");\n    ErrorF(\"-pixelformat fmt       set pixel format (rgbNNN or bgrNNN)\\n\");\n    ErrorF(\"-inetd                 has been launched from inetd\\n\");\n    ErrorF\n        (\"-noclipboard           disable clipboard settings modification via vncconfig utility\\n\");\n#ifdef DRI3\n    ErrorF(\"-rendernode PATH       DRM render node to use for DRI3\\n\");\n#endif\n    ErrorF(\"-verbose [n]           verbose startup messages\\n\");\n    ErrorF(\"-quiet                 minimal startup messages\\n\");\n    ErrorF(\"-version               show the server version\\n\");\n    ErrorF(\"\\nVNC parameters:\\n\");\n\n    fprintf(stderr, \"\\n\"\n            \"Parameters can be turned on with -<param> or off with -<param>=0\\n\"\n            \"Parameters which take a value can be specified as \"\n            \"-<param> <value>\\n\"\n            \"Other valid forms are <param>=<value> -<param>=<value> \"\n            \"--<param>=<value>\\n\"\n            \"Parameter names are case-insensitive.  The parameters are:\\n\\n\");\n    vncListParams(79, 14);\n}\n\nstatic Bool\ndisplayNumFree(int num)\n{\n    char file[256];\n\n    if (vncIsTCPPortUsed(6000 + num))\n        return FALSE;\n    sprintf(file, \"/tmp/.X%d-lock\", num);\n    if (access(file, F_OK) == 0)\n        return FALSE;\n    sprintf(file, \"/tmp/.X11-unix/X%d\", num);\n    if (access(file, F_OK) == 0)\n        return FALSE;\n    sprintf(file, \"/usr/spool/sockets/X11/%d\", num);\n    if (access(file, F_OK) == 0)\n        return FALSE;\n    return TRUE;\n}\n\nint\nddxProcessArgument(int argc, char *argv[], int i)\n{\n    static Bool firstTime = TRUE;\n\n    if (firstTime) {\n        /* Force -noreset as default until we properly handle resets */\n        dispatchExceptionAtReset = 0;\n\n        vncInitializePixmapDepths();\n        firstTime = FALSE;\n        vncInitRFB();\n    }\n\n    if (argv[i][0] == ':')\n        return 0;\n\n#if XORG_OLDER_THAN(1, 21, 1)\n#define CHECK_FOR_REQUIRED_ARGUMENTS(num) \\\n    if (((i + num) >= argc) || (!argv[i + num])) {                      \\\n      ErrorF(\"Required argument to %s not specified\\n\", argv[i]);       \\\n      UseMsg();                                                         \\\n      FatalError(\"Required argument to %s not specified\\n\", argv[i]);   \\\n    }\n#endif\n\n    if (strcmp(argv[i], \"-pixdepths\") == 0) {   /* -pixdepths list-of-depth */\n        int depth, ret = 1;\n\n        CHECK_FOR_REQUIRED_ARGUMENTS(1);\n        ++i;\n        while ((i < argc) && (depth = atoi(argv[i++])) != 0) {\n            if (depth < 0 || depth > 32) {\n                ErrorF(\"Invalid pixmap depth %d\\n\", depth);\n                UseMsg();\n                FatalError(\"Invalid pixmap depth %d passed to -pixdepths\\n\",\n                           depth);\n            }\n            vncPixmapDepths[depth] = TRUE;\n            ret++;\n        }\n        return ret;\n    }\n\n    if (strcmp(argv[i], \"+render\") == 0) {      /* +render */\n        Render = TRUE;\n        return 1;\n    }\n\n    if (strcmp(argv[i], \"-render\") == 0) {      /* -render */\n        Render = FALSE;\n        return 1;\n    }\n\n    if (strcmp(argv[i], \"-geometry\") == 0) {\n        CHECK_FOR_REQUIRED_ARGUMENTS(1);\n        ++i;\n        if (sscanf(argv[i], \"%dx%d\", &vncScreenInfo.fb.width,\n                   &vncScreenInfo.fb.height) != 2) {\n            ErrorF(\"Invalid geometry %s\\n\", argv[i]);\n            UseMsg();\n            FatalError(\"Invalid geometry %s passed to -geometry\\n\",\n                       argv[i]);\n        }\n        return 2;\n    }\n\n    if (strcmp(argv[i], \"-depth\") == 0) {\n        CHECK_FOR_REQUIRED_ARGUMENTS(1);\n        ++i;\n        vncScreenInfo.fb.depth = atoi(argv[i]);\n        return 2;\n    }\n\n    if (strcmp(argv[i], \"-pixelformat\") == 0) {\n        char rgbbgr[4];\n        int bits1, bits2, bits3;\n\n        CHECK_FOR_REQUIRED_ARGUMENTS(1);\n        ++i;\n        if (sscanf(argv[i], \"%3s%1d%1d%1d\", rgbbgr, &bits1, &bits2, &bits3) < 4) {\n            ErrorF(\"Invalid pixel format %s\\n\", argv[i]);\n            UseMsg();\n            FatalError(\"Invalid pixel format %s passed to -pixelformat\\n\",\n                       argv[i]);\n        }\n\n        vncScreenInfo.pixelFormatDefined = TRUE;\n        vncScreenInfo.fb.depth = bits1 + bits2 + bits3;\n        vncScreenInfo.greenBits = bits2;\n        if (strcasecmp(rgbbgr, \"bgr\") == 0) {\n            vncScreenInfo.rgbNotBgr = FALSE;\n            vncScreenInfo.redBits = bits3;\n            vncScreenInfo.blueBits = bits1;\n        } else if (strcasecmp(rgbbgr, \"rgb\") == 0) {\n            vncScreenInfo.rgbNotBgr = TRUE;\n            vncScreenInfo.redBits = bits1;\n            vncScreenInfo.blueBits = bits3;\n        } else {\n            ErrorF(\"Invalid pixel format %s\\n\", argv[i]);\n            UseMsg();\n            FatalError(\"Invalid pixel format %s passed to -pixelformat\\n\",\n                       argv[i]);\n        }\n\n        return 2;\n    }\n\n    if (strcmp(argv[i], \"-inetd\") == 0) {\n        int nullfd;\n\n        if ((vncInetdSock = dup(0)) == -1)\n            FatalError\n                (\"Xvnc error: Failed to allocate a new file descriptor for -inetd: %s\\n\", strerror(errno));\n\n\n        /* Avoid xserver >= 1.19's epoll-fd becoming fd 2 / stderr only to be\n           replaced by /dev/null by OsInit() because the pollfd is not\n           writable, breaking ospoll_wait(). */\n        nullfd = open(\"/dev/null\", O_WRONLY);\n        dup2(nullfd, 2);\n        close(nullfd);\n\n        if (!explicit_display) {\n            int port = vncGetSocketPort(vncInetdSock);\n            int displayNum = port - 5900;\n\n            if (displayNum < 0 || displayNum > 99 ||\n                !displayNumFree(displayNum)) {\n                for (displayNum = 1; displayNum < 100; displayNum++)\n                    if (displayNumFree(displayNum))\n                        break;\n\n                if (displayNum == 100)\n                    FatalError\n                        (\"Xvnc error: No free display number for -inetd\\n\");\n            }\n            sprintf(displayNumStr, \"%d\", displayNum);\n            display = displayNumStr;\n            explicit_display = TRUE;\n        }\n\n        return 1;\n    }\n\n    if (strcmp(argv[i], \"-noclipboard\") == 0) {\n        vncNoClipboard = 1;\n        return 1;\n    }\n\n#ifdef DRI3\n    if (strcmp(argv[i], \"-rendernode\") == 0) {\n        CHECK_FOR_REQUIRED_ARGUMENTS(1);\n        ++i;\n        renderNode = argv[i];\n        return 2;\n    }\n#endif\n\n    if (!strcmp(argv[i], \"-verbose\")) {\n        if (++i < argc && argv[i]) {\n            char *end;\n            long val;\n\n            val = strtol(argv[i], &end, 0);\n            if (*end == '\\0') {\n                vncVerbose = val;\n                LogSetParameter(XLOG_VERBOSITY, vncVerbose);\n                return 2;\n            }\n        }\n        vncVerbose++;\n        LogSetParameter(XLOG_VERBOSITY, vncVerbose);\n        return 1;\n    }\n\n    if (!strcmp(argv[i], \"-quiet\")) {\n        vncVerbose = -1;\n        LogSetParameter(XLOG_VERBOSITY, vncVerbose);\n        return 1;\n    }\n\n    if (!strcmp(argv[i], \"-showconfig\") || !strcmp(argv[i], \"-version\")) {\n        vncPrintBanner();\n        exit(0);\n    }\n\n    return vncHandleParamArg(argc, argv, i);\n}\n\nstatic Bool\nvncSaveScreen(ScreenPtr pScreen, int on)\n{\n    return TRUE;\n}\n\nstatic void *\nvncAllocateFramebufferMemory(VncFramebufferInfoPtr pfb)\n{\n    size_t sizeInBytes;\n\n    if (pfb->pfbMemory != NULL)\n        return pfb->pfbMemory;  /* already done */\n\n    /* Compute memory layout */\n    pfb->paddedBytesWidth = PixmapBytePad(pfb->width, pfb->depth);\n    pfb->bitsPerPixel = vncBitsPerPixel(pfb->depth);\n    pfb->paddedWidth = pfb->paddedBytesWidth * 8 / pfb->bitsPerPixel;\n\n    /* And allocate buffer */\n    sizeInBytes = pfb->paddedBytesWidth * pfb->height;\n    pfb->pfbMemory = malloc(sizeInBytes);\n\n    /* This will be NULL if the above failed */\n    return pfb->pfbMemory;\n}\n\nstatic void\nvncFreeFramebufferMemory(VncFramebufferInfoPtr pfb)\n{\n    if ((pfb == NULL) || (pfb->pfbMemory == NULL))\n        return;\n\n    free(pfb->pfbMemory);\n    pfb->pfbMemory = NULL;\n}\n\nstatic Bool\nvncCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)\n{\n    return FALSE;\n}\n\nstatic void\nvncCrossScreen(ScreenPtr pScreen, Bool entering)\n{\n}\n\nstatic Bool\nvncRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)\n{\n    return TRUE;\n}\n\nstatic Bool\nvncUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)\n{\n    return TRUE;\n}\n\nstatic void\nvncSetCursor(DeviceIntPtr pDev,\n             ScreenPtr pScreen, CursorPtr pCursor, int x, int y)\n{\n}\n\nstatic void\nvncMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)\n{\n}\n\nstatic Bool\nvncDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)\n{\n    return TRUE;\n}\n\nstatic void\nvncDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)\n{\n}\n\nstatic miPointerSpriteFuncRec vncPointerSpriteFuncs = {\n    vncRealizeCursor,\n    vncUnrealizeCursor,\n    vncSetCursor,\n    vncMoveCursor,\n    vncDeviceCursorInitialize,\n    vncDeviceCursorCleanup\n};\n\nstatic miPointerScreenFuncRec vncPointerCursorFuncs = {\n    vncCursorOffScreen,\n    vncCrossScreen,\n    miPointerWarpCursor\n};\n\nstatic Bool\nvncRandRGetInfo(ScreenPtr pScreen, Rotation * rotations)\n{\n    // We update all information right away, so there is nothing to\n    // do here.\n    return TRUE;\n}\n\nstatic Bool vncRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc, RRModePtr mode,\n                            int x, int y, Rotation rotation, int num_outputs,\n                            RROutputPtr * outputs);\nstatic RRModePtr vncRandRModeGet(int width, int height);\n\nstatic Bool\nvncRandRScreenSetSize(ScreenPtr pScreen,\n                      CARD16 width, CARD16 height,\n                      CARD32 mmWidth, CARD32 mmHeight)\n{\n    VncFramebufferInfo fb;\n    rrScrPrivPtr rp = rrGetScrPriv(pScreen);\n    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);\n    void *pbits;\n    Bool ret;\n    int oldwidth, oldheight, oldmmWidth, oldmmHeight;\n\n    /* Prevent updates while we fiddle */\n    SetRootClip(pScreen, ROOT_CLIP_NONE);\n\n    /* Store current state in case we fail */\n    oldwidth = pScreen->width;\n    oldheight = pScreen->height;\n    oldmmWidth = pScreen->mmWidth;\n    oldmmHeight = pScreen->mmHeight;\n\n    /* Then set the new dimensions */\n    pScreen->width = width;\n    pScreen->height = height;\n    pScreen->mmWidth = mmWidth;\n    pScreen->mmHeight = mmHeight;\n\n    /* Allocate a new framebuffer */\n    memset(&fb, 0, sizeof(VncFramebufferInfo));\n\n    fb.width = pScreen->width;\n    fb.height = pScreen->height;\n    fb.depth = vncScreenInfo.fb.depth;\n\n    pbits = vncAllocateFramebufferMemory(&fb);\n    if (!pbits) {\n        /* Allocation failed. Restore old state */\n        pScreen->width = oldwidth;\n        pScreen->height = oldheight;\n        pScreen->mmWidth = oldmmWidth;\n        pScreen->mmHeight = oldmmHeight;\n\n        SetRootClip(pScreen, ROOT_CLIP_FULL);\n\n        return FALSE;\n    }\n\n    /* Update root pixmap with the new dimensions and buffer */\n    ret = pScreen->ModifyPixmapHeader(rootPixmap, fb.width, fb.height,\n                                      -1, -1, fb.paddedBytesWidth, pbits);\n    if (!ret) {\n        /* Update failed. Free the new framebuffer and restore old state */\n        vncFreeFramebufferMemory(&fb);\n\n        pScreen->width = oldwidth;\n        pScreen->height = oldheight;\n        pScreen->mmWidth = oldmmWidth;\n        pScreen->mmHeight = oldmmHeight;\n\n        SetRootClip(pScreen, ROOT_CLIP_FULL);\n\n        return FALSE;\n    }\n\n    /* Free the old framebuffer and keep the info about the new one */\n    vncFreeFramebufferMemory(&vncScreenInfo.fb);\n    vncScreenInfo.fb = fb;\n\n    /* Let VNC get the new framebuffer (actual update is in vncHooks.cc) */\n    vncFbptr[pScreen->myNum] = pbits;\n    vncFbstride[pScreen->myNum] = fb.paddedWidth;\n\n    /* Restore ability to update screen, now with new dimensions */\n    SetRootClip(pScreen, ROOT_CLIP_FULL);\n\n    /*\n     * Let RandR know we changed something (it doesn't assume that\n     * TRUE means something changed for some reason...).\n     */\n    RRScreenSizeNotify(pScreen);\n\n    /* Crop all CRTCs to the new screen */\n    for (int i = 0; i < rp->numCrtcs; i++) {\n        RRCrtcPtr crtc;\n        RRModePtr mode;\n\n        crtc = rp->crtcs[i];\n\n        /* Disabled? */\n        if (crtc->mode == NULL)\n            continue;\n\n        /* Fully inside? */\n        if ((crtc->x + crtc->mode->mode.width <= width) &&\n            (crtc->y + crtc->mode->mode.height <= height))\n            continue;\n\n        /* Fully outside? */\n        if ((crtc->x >= width) || (crtc->y >= height)) {\n            /* Disable it */\n            ret = vncRandRCrtcSet(pScreen, crtc, NULL,\n                                  crtc->x, crtc->y, crtc->rotation, 0, NULL);\n            if (!ret)\n                ErrorF(\"Warning: Unable to disable CRTC that is outside of new screen dimensions\\n\");\n            continue;\n        }\n\n        /* Just needs to be resized to a temporary mode */\n        mode = vncRandRModeGet(width - crtc->x, height - crtc->y);\n        if (mode == NULL) {\n            ErrorF(\"Warning: Unable to create custom mode for %dx%d\\n\",\n                   width - crtc->x, height - crtc->y);\n            continue;\n        }\n\n        ret = vncRandRCrtcSet(pScreen, crtc, mode,\n                              crtc->x, crtc->y, crtc->rotation,\n                              crtc->numOutputs, crtc->outputs);\n        RRModeDestroy(mode);\n        if (!ret)\n            ErrorF(\"Warning: Unable to crop CRTC to new screen dimensions\\n\");\n    }\n\n    return TRUE;\n}\n\nstatic Bool\nvncRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc, RRModePtr mode,\n                int x, int y, Rotation rotation, int num_outputs,\n                RROutputPtr * outputs)\n{\n    Bool ret;\n    int i;\n\n    /*\n     * Some applications get confused by a connected output without a\n     * mode or CRTC, so we need to fiddle with the connection state as well.\n     */\n    for (i = 0; i < crtc->numOutputs; i++)\n        RROutputSetConnection(crtc->outputs[i], RR_Disconnected);\n\n    for (i = 0; i < num_outputs; i++) {\n        if (mode != NULL)\n            RROutputSetConnection(outputs[i], RR_Connected);\n        else\n            RROutputSetConnection(outputs[i], RR_Disconnected);\n    }\n\n    /* Let RandR know we approve, and let it update its internal state */\n    ret = RRCrtcNotify(crtc, mode, x, y, rotation, NULL, num_outputs, outputs);\n    if (!ret)\n        return FALSE;\n\n    return TRUE;\n}\n\nstatic Bool\nvncRandROutputValidateMode(ScreenPtr pScreen,\n                           RROutputPtr output, RRModePtr mode)\n{\n    /* We have no hardware so any mode works */\n    return TRUE;\n}\n\nstatic void\nvncRandRModeDestroy(ScreenPtr pScreen, RRModePtr mode)\n{\n    /* We haven't allocated anything so nothing to destroy */\n}\n\nstatic const int vncRandRWidths[] =\n    { 1920, 1920, 1600, 1680, 1400, 1360, 1280, 1280, 1280, 1280, 1024, 800, 640 };\nstatic const int vncRandRHeights[] =\n    { 1200, 1080, 1200, 1050, 1050,  768, 1024,  960,  800,  720,  768, 600, 480 };\n\nstatic int vncRandRIndex = 0;\n\nstatic RRModePtr\nvncRandRModeGet(int width, int height)\n{\n    xRRModeInfo modeInfo;\n    char name[100];\n    RRModePtr mode;\n#ifdef HAVE_LIBXCVT\n    struct libxcvt_mode_info *cvtMode;\n#endif\n\n    memset(&modeInfo, 0, sizeof(modeInfo));\n\n#ifdef HAVE_LIBXCVT\n    cvtMode = libxcvt_gen_mode_info(width, height, 60.0, false, false);\n\n    modeInfo.width      = cvtMode->hdisplay;\n    modeInfo.height     = cvtMode->vdisplay;\n    modeInfo.dotClock   = cvtMode->dot_clock * 1000.0;\n    modeInfo.hSyncStart = cvtMode->hsync_start;\n    modeInfo.hSyncEnd   = cvtMode->hsync_end;\n    modeInfo.hTotal     = cvtMode->htotal;\n    modeInfo.vSyncStart = cvtMode->vsync_start;\n    modeInfo.vSyncEnd   = cvtMode->vsync_end;\n    modeInfo.vTotal     = cvtMode->vtotal;\n    modeInfo.modeFlags  = cvtMode->mode_flags;\n\n    free(cvtMode);\n\n    /* libxcvt rounds up to multiples of 8, so override them here */\n    modeInfo.width = width;\n    modeInfo.height = height;\n#else\n    modeInfo.width = width;\n    modeInfo.height = height;\n    modeInfo.hTotal = width;\n    modeInfo.vTotal = height;\n    modeInfo.dotClock = ((CARD32) width * (CARD32) height * 60);\n#endif\n\n    sprintf(name, \"%dx%d\", width, height);\n    modeInfo.nameLength = strlen(name);\n    mode = RRModeGet(&modeInfo, name);\n    if (mode == NULL)\n        return NULL;\n\n    return mode;\n}\n\nstatic void\nvncRandRSetModes(RROutputPtr output, int pref_width, int pref_height)\n{\n    RRModePtr mode;\n    RRModePtr *modes;\n    int i, num_modes, num_pref;\n\n    num_modes = sizeof(vncRandRWidths) / sizeof(*vncRandRWidths) + 1;\n    modes = malloc(sizeof(RRModePtr) * num_modes);\n    if (modes == NULL)\n        return;\n\n    num_modes = 0;\n    num_pref = 0;\n\n    if ((pref_width > 0) && (pref_height > 0)) {\n        mode = vncRandRModeGet(pref_width, pref_height);\n        if (mode != NULL) {\n            modes[num_modes] = mode;\n            num_modes++;\n            num_pref++;\n        }\n    }\n\n    for (i = 0; i < sizeof(vncRandRWidths) / sizeof(*vncRandRWidths); i++) {\n        if ((vncRandRWidths[i] == pref_width) &&\n            (vncRandRHeights[i] == pref_height))\n            continue;\n        mode = vncRandRModeGet(vncRandRWidths[i], vncRandRHeights[i]);\n        if (mode != NULL) {\n            modes[num_modes] = mode;\n            num_modes++;\n        }\n    }\n\n    RROutputSetModes(output, modes, num_modes, num_pref);\n\n    free(modes);\n}\n\nstatic RRCrtcPtr\nvncRandRCrtcCreate(ScreenPtr pScreen)\n{\n    RRCrtcPtr crtc;\n    RROutputPtr output;\n    char name[100];\n\n    /* First we create the CRTC... */\n    crtc = RRCrtcCreate(pScreen, NULL);\n\n    /* We don't actually support gamma, but xrandr complains when it is missing */\n    RRCrtcGammaSetSize(crtc, 256);\n\n    /* Then we create a dummy output for it... */\n    sprintf(name, \"VNC-%d\", vncRandRIndex);\n    vncRandRIndex++;\n\n    output = RROutputCreate(pScreen, name, strlen(name), NULL);\n\n    RROutputSetCrtcs(output, &crtc, 1);\n    RROutputSetConnection(output, RR_Disconnected);\n\n    /* Make sure the CRTC has this output set */\n    vncRandRCrtcSet(pScreen, crtc, NULL, 0, 0, RR_Rotate_0, 1, &output);\n\n    /* Populate a list of default modes */\n    vncRandRSetModes(output, -1, -1);\n\n    return crtc;\n}\n\n/* Used from XserverDesktop when it needs more outputs... */\n\nint\nvncRandRCanCreateScreenOutputs(int scrIdx, int extraOutputs)\n{\n    return 1;\n}\n\nint\nvncRandRCreateScreenOutputs(int scrIdx, int extraOutputs)\n{\n    RRCrtcPtr crtc;\n\n    while (extraOutputs > 0) {\n        crtc = vncRandRCrtcCreate(screenInfo.screens[scrIdx]);\n        if (crtc == NULL)\n            return 0;\n        extraOutputs--;\n    }\n\n    return 1;\n}\n\n/* Creating and modifying modes, used by XserverDesktop and init here */\n\nint\nvncRandRCanCreateModes(void)\n{\n    return 1;\n}\n\nvoid *\nvncRandRCreateMode(void *out, int width, int height)\n{\n    RROutputPtr output;\n\n    output = out;\n\n    /* Do we already have the mode? */\n    for (int i = 0; i < output->numModes; i++) {\n        if ((output->modes[i]->mode.width == width) &&\n            (output->modes[i]->mode.height == height))\n            return output->modes[i];\n    }\n\n    /* Just recreate the entire list */\n    vncRandRSetModes(output, width, height);\n\n    /* Find the new mode */\n    for (int i = 0; i < output->numModes; i++) {\n        if ((output->modes[i]->mode.width == width) &&\n            (output->modes[i]->mode.height == height))\n            return output->modes[i];\n    }\n\n    /* Something went horribly wrong */\n    return NULL;\n}\n\nvoid *\nvncRandRSetPreferredMode(void *out, void *m)\n{\n    RRModePtr mode;\n    RROutputPtr output;\n    int width, height;\n\n    mode = m;\n    output = out;\n\n    width = mode->mode.width;\n    height = mode->mode.height;\n\n    /* Already the preferred mode? */\n    if ((output->numModes >= 1) && (output->numPreferred == 1) &&\n        (output->modes[0] == mode))\n        return mode;\n\n    /* Recreate the list, with the mode we want as preferred */\n    vncRandRSetModes(output, width, height);\n\n    /* Sanity check */\n    if ((output->numModes >= 1) && (output->numPreferred == 1) &&\n        (output->modes[0]->mode.width == width) &&\n        (output->modes[0]->mode.height == height))\n        return output->modes[0];\n\n    /* Something went horribly wrong */\n    return NULL;\n}\n\nstatic Bool\nvncRandRInit(ScreenPtr pScreen)\n{\n    rrScrPrivPtr pScrPriv;\n    RRCrtcPtr crtc;\n    RRModePtr mode;\n    Bool ret;\n\n    if (!RRScreenInit(pScreen))\n        return FALSE;\n\n    pScrPriv = rrGetScrPriv(pScreen);\n\n    pScrPriv->rrGetInfo = vncRandRGetInfo;\n    pScrPriv->rrSetConfig = NULL;\n    pScrPriv->rrScreenSetSize = vncRandRScreenSetSize;\n    pScrPriv->rrCrtcSet = vncRandRCrtcSet;\n    pScrPriv->rrOutputValidateMode = vncRandROutputValidateMode;\n    pScrPriv->rrModeDestroy = vncRandRModeDestroy;\n\n    /* These are completely arbitrary */\n    RRScreenSetSizeRange(pScreen, 32, 32, 32768, 32768);\n\n    /*\n     * Start with a single CRTC with a single output. More will be\n     * allocated as needed...\n     */\n    crtc = vncRandRCrtcCreate(pScreen);\n\n    /* Make sure the current screen size is the active mode */\n    mode = vncRandRCreateMode(crtc->outputs[0],\n                              pScreen->width, pScreen->height);\n    if (mode == NULL)\n        return FALSE;\n    mode = vncRandRSetPreferredMode(crtc->outputs[0], mode);\n    if (mode == NULL)\n        return FALSE;\n\n    ret = vncRandRCrtcSet(pScreen, crtc, mode, 0, 0, RR_Rotate_0,\n                          crtc->numOutputs, crtc->outputs);\n    if (!ret)\n        return FALSE;\n\n    return TRUE;\n}\n\nstatic Bool\nvncScreenInit(ScreenPtr pScreen, int argc, char **argv)\n{\n    int dpi;\n    int ret;\n    void *pbits;\n\n    /* 96 is the default used by most other systems */\n    dpi = 96;\n    if (monitorResolution)\n        dpi = monitorResolution;\n\n    pbits = vncAllocateFramebufferMemory(&vncScreenInfo.fb);\n    if (!pbits)\n        return FALSE;\n    vncFbptr[0] = pbits;\n    vncFbstride[0] = vncScreenInfo.fb.paddedWidth;\n\n    switch (vncScreenInfo.fb.depth) {\n    case 16:\n        miSetVisualTypesAndMasks(16,\n                                 ((1 << TrueColor) |\n                                  (1 << DirectColor)),\n                                 8, TrueColor, 0xf800, 0x07e0, 0x001f);\n        break;\n    case 24:\n        miSetVisualTypesAndMasks(24,\n                                 ((1 << TrueColor) |\n                                  (1 << DirectColor)),\n                                 8, TrueColor, 0xff0000, 0x00ff00, 0x0000ff);\n        break;\n    case 32:\n        miSetVisualTypesAndMasks(32,\n                                 ((1 << TrueColor) |\n                                  (1 << DirectColor)),\n                                 8, TrueColor, 0xff000000, 0x00ff0000,\n                                 0x0000ff00);\n        break;\n    default:\n        return FALSE;\n    }\n\n    miSetPixmapDepths();\n\n    ret = fbScreenInit(pScreen, pbits,\n                       vncScreenInfo.fb.width, vncScreenInfo.fb.height,\n                       dpi, dpi, vncScreenInfo.fb.paddedWidth,\n                       vncScreenInfo.fb.bitsPerPixel);\n\n    if (ret && Render)\n        ret = fbPictureInit(pScreen, 0, 0);\n\n    if (!ret)\n        return FALSE;\n\n    ret = vncRandRInit(pScreen);\n    if (!ret)\n        return FALSE;\n\n    pScreen->SaveScreen = vncSaveScreen;\n\n    miPointerInitialize(pScreen, &vncPointerSpriteFuncs, &vncPointerCursorFuncs,\n                        FALSE);\n\n    if (!vncScreenInfo.pixelFormatDefined) {\n        switch (vncScreenInfo.fb.depth) {\n        case 16:\n            vncScreenInfo.pixelFormatDefined = TRUE;\n            vncScreenInfo.rgbNotBgr = TRUE;\n            vncScreenInfo.blueBits = vncScreenInfo.redBits = 5;\n            vncScreenInfo.greenBits = 6;\n            break;\n        case 24:\n        case 32:\n            vncScreenInfo.pixelFormatDefined = TRUE;\n            vncScreenInfo.rgbNotBgr = TRUE;\n            vncScreenInfo.blueBits = vncScreenInfo.redBits = vncScreenInfo.greenBits = 8;\n            break;\n        }\n    }\n\n    if (vncScreenInfo.pixelFormatDefined) {\n        VisualPtr vis = pScreen->visuals;\n\n        for (int i = 0; i < pScreen->numVisuals; i++) {\n            if (vncScreenInfo.rgbNotBgr) {\n                vis->offsetBlue = 0;\n                vis->blueMask = (1 << vncScreenInfo.blueBits) - 1;\n                vis->offsetGreen = vncScreenInfo.blueBits;\n                vis->greenMask =\n                    ((1 << vncScreenInfo.greenBits) - 1) << vis->offsetGreen;\n                vis->offsetRed = vis->offsetGreen + vncScreenInfo.greenBits;\n                vis->redMask = ((1 << vncScreenInfo.redBits) - 1) << vis->offsetRed;\n            }\n            else {\n                vis->offsetRed = 0;\n                vis->redMask = (1 << vncScreenInfo.redBits) - 1;\n                vis->offsetGreen = vncScreenInfo.redBits;\n                vis->greenMask =\n                    ((1 << vncScreenInfo.greenBits) - 1) << vis->offsetGreen;\n                vis->offsetBlue = vis->offsetGreen + vncScreenInfo.greenBits;\n                vis->blueMask = ((1 << vncScreenInfo.blueBits) - 1) << vis->offsetBlue;\n            }\n            vis++;\n        }\n    }\n\n    ret = fbCreateDefColormap(pScreen);\n    if (!ret)\n        return FALSE;\n\n    ret = vncPresentInit(pScreen);\n    if (!ret)\n        ErrorF(\"Failed to initialize Present extension\\n\");\n\n#ifdef DRI3\n    ret = vncDRI3Init(pScreen);\n    if (!ret)\n        ErrorF(\"Failed to initialize DRI3 extension\\n\");\n#endif\n\n    return TRUE;\n\n}                               /* end vncScreenInit */\n\nstatic void\nvncClientStateChange(CallbackListPtr *a, void *b, void *c)\n{\n    if (dispatchException & DE_RESET) {\n        ErrorF(\"Warning: VNC extension does not support -reset, terminating instead. Use -noreset to prevent termination.\\n\");\n\n        dispatchException |= DE_TERMINATE;\n        dispatchException &= ~DE_RESET;\n    }\n}\n\nstatic const ExtensionModule vncExtensions[] = {\n    {vncExtensionInit, \"TIGERVNC\", NULL},\n};\n\nvoid\nInitOutput(ScreenInfo * scrInfo, int argc, char **argv)\n{\n    int i;\n    int NumFormats = 0;\n\n    if (serverGeneration == 1) {\n        vncPrintBanner();\n\n        LoadExtensionList(vncExtensions, ARRAY_SIZE(vncExtensions), TRUE);\n    }\n\n    xorgGlxCreateVendor();\n\n    /* initialize pixmap formats */\n\n    /* must have a pixmap depth to match every screen depth */\n    vncPixmapDepths[vncScreenInfo.fb.depth] = TRUE;\n\n    /* RENDER needs a good set of pixmaps. */\n    if (Render) {\n        vncPixmapDepths[1] = TRUE;\n        vncPixmapDepths[4] = TRUE;\n        vncPixmapDepths[8] = TRUE;\n/*\tvncPixmapDepths[15] = TRUE; */\n        vncPixmapDepths[16] = TRUE;\n        vncPixmapDepths[24] = TRUE;\n        vncPixmapDepths[32] = TRUE;\n    }\n\n    for (i = 1; i <= 32; i++) {\n        if (vncPixmapDepths[i]) {\n            if (NumFormats >= MAXFORMATS)\n                FatalError(\"MAXFORMATS is too small for this server\\n\");\n            scrInfo->formats[NumFormats].depth = i;\n            scrInfo->formats[NumFormats].bitsPerPixel = vncBitsPerPixel(i);\n            scrInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;\n            NumFormats++;\n        }\n    }\n\n    scrInfo->imageByteOrder = IMAGE_BYTE_ORDER;\n    scrInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;\n    scrInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;\n    scrInfo->bitmapBitOrder = BITMAP_BIT_ORDER;\n    scrInfo->numPixmapFormats = NumFormats;\n\n    /* initialize screen */\n\n    if (AddScreen(vncScreenInit, argc, argv) == -1) {\n        FatalError(\"Couldn't add screen\\n\");\n    }\n\n    if (!AddCallback(&ClientStateCallback, vncClientStateChange, 0)) {\n        FatalError(\"AddCallback failed\\n\");\n    }\n}                               /* end InitOutput */\n\nvoid\nDDXRingBell(int percent, int pitch, int duration)\n{\n    if (percent > 0)\n        vncBell();\n}\n\n#if XORG_OLDER_THAN(1, 21, 1)\nBool\nLegalModifier(unsigned int key, DeviceIntPtr pDev)\n{\n    return TRUE;\n}\n#endif\n\nvoid\nProcessInputEvents(void)\n{\n    mieqProcessInputEvents();\n}\n\nvoid\nInitInput(int argc, char *argv[])\n{\n    mieqInit();\n}\n\nvoid\nCloseInput(void)\n{\n}\n\nvoid\nvncClientGone(int fd)\n{\n    if (fd == vncInetdSock) {\n        ErrorF(\"inetdSock client gone\\n\");\n        GiveUp(0);\n    }\n}\n\nint\nmain(int argc, char *argv[], char *envp[])\n{\n    return dix_main(argc, argv, envp);\n}\n"
  },
  {
    "path": "unix/xserver120.patch",
    "content": "diff --git a/configure.ac b/configure.ac\nindex 0909cc5b4..c01873200 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -74,6 +74,7 @@ dnl forcing an entire recompile.x\n AC_CONFIG_HEADERS(include/version-config.h)\n \n AM_PROG_AS\n+AC_PROG_CXX\n AC_PROG_LN_S\n LT_PREREQ([2.2])\n LT_INIT([disable-static win32-dll])\n@@ -1735,6 +1736,19 @@ if test \"x$XVFB\" = xyes; then\n \tAC_SUBST([XVFB_SYS_LIBS])\n fi\n \n+dnl Xvnc DDX\n+AC_SUBST([XVNC_LIBS], [\"$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB\"])\n+AC_SUBST([XVNC_SYS_LIBS], [\"$GLX_SYS_LIBS\"])\n+\n+PKG_CHECK_MODULES(GBM, \"$LIBGBM\", [GBM=yes], [GBM=no])\n+if test \"x$GBM\" = xyes; then\n+\tAC_DEFINE(HAVE_GBM, 1, [Have GBM support])\n+fi\n+\n+PKG_CHECK_MODULES(LIBXCVT, \"libxcvt\", [XCVT=yes], [XCVT=no])\n+if test \"x$XCVT\" = xyes; then\n+\tAC_DEFINE(HAVE_LIBXCVT, 1, [Have libxcvt support])\n+fi\n \n dnl Xnest DDX\n \n@@ -2058,7 +2067,6 @@ if test \"x$GLAMOR\" = xyes; then\n \t\t\t [AC_DEFINE(GLAMOR_HAS_EGL_QUERY_DRIVER, 1, [Have GLAMOR_HAS_EGL_QUERY_DRIVER])],\n \t\t\t [])\n \n-\tPKG_CHECK_MODULES(GBM, \"$LIBGBM\", [GBM=yes], [GBM=no])\n \tif test \"x$GBM\" = xyes; then\n \t\tAC_DEFINE(GLAMOR_HAS_GBM, 1,\n \t\t\t  [Build glamor with GBM-based EGL support])\n@@ -2523,6 +2531,7 @@ hw/dmx/Makefile\n hw/dmx/man/Makefile\n hw/vfb/Makefile\n hw/vfb/man/Makefile\n+hw/vnc/Makefile\n hw/xnest/Makefile\n hw/xnest/man/Makefile\n hw/xwin/Makefile\ndiff --git a/dri3/Makefile.am b/dri3/Makefile.am\nindex e47a734e0..99c3718a5 100644\n--- a/dri3/Makefile.am\n+++ b/dri3/Makefile.am\n@@ -1,7 +1,7 @@\n noinst_LTLIBRARIES = libdri3.la\n AM_CFLAGS = \\\n-\t-DHAVE_XORG_CONFIG_H \\\n-\t@DIX_CFLAGS@ @XORG_CFLAGS@\n+\t@DIX_CFLAGS@ \\\n+\t@LIBDRM_CFLAGS@\n\n libdri3_la_SOURCES = \\\n \tdri3.h \\\ndiff --git a/dri3/dri3.c b/dri3/dri3.c\nindex ba32facd7..191252969 100644\n--- a/dri3/dri3.c\n+++ b/dri3/dri3.c\n@@ -20,10 +20,6 @@\n  * OF THIS SOFTWARE.\n  */\n \n-#ifdef HAVE_XORG_CONFIG_H\n-#include <xorg-config.h>\n-#endif\n-\n #include \"dri3_priv.h\"\n \n #include <drm_fourcc.h>\ndiff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h\nindex b087a9529..f319d1770 100644\n--- a/dri3/dri3_priv.h\n+++ b/dri3/dri3_priv.h\n@@ -23,6 +23,7 @@\n #ifndef _DRI3PRIV_H_\n #define _DRI3PRIV_H_\n \n+#include \"dix-config.h\"\n #include <X11/X.h>\n #include \"scrnintstr.h\"\n #include \"misc.h\"\ndiff --git a/dri3/dri3_request.c b/dri3/dri3_request.c\nindex 958877efa..687168930 100644\n--- a/dri3/dri3_request.c\n+++ b/dri3/dri3_request.c\n@@ -20,10 +20,6 @@\n  * OF THIS SOFTWARE.\n  */\n \n-#ifdef HAVE_XORG_CONFIG_H\n-#include <xorg-config.h>\n-#endif\n-\n #include \"dri3_priv.h\"\n #include <syncsrv.h>\n #include <unistd.h>\ndiff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c\nindex b98259753..3c7e5bf60 100644\n--- a/dri3/dri3_screen.c\n+++ b/dri3/dri3_screen.c\n@@ -20,10 +20,6 @@\n  * OF THIS SOFTWARE.\n  */\n \n-#ifdef HAVE_XORG_CONFIG_H\n-#include <xorg-config.h>\n-#endif\n-\n #include \"dri3_priv.h\"\n #include <syncsdk.h>\n #include <misync.h>\ndiff --git a/hw/Makefile.am b/hw/Makefile.am\nindex 19895dc77..3ecfa8b7a 100644\n--- a/hw/Makefile.am\n+++ b/hw/Makefile.am\n@@ -44,3 +44,5 @@ DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland\n \n relink:\n \t$(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done\n+\n+SUBDIRS += vnc\ndiff --git a/include/dix-config.h.in b/include/dix-config.h.in\nindex f8fc67067..d53c4e72f 100644\n--- a/include/dix-config.h.in\n+++ b/include/dix-config.h.in\n@@ -63,6 +63,9 @@\n /* Has libunwind support */\n #undef HAVE_LIBUNWIND\n\n+/* Have libxcvt support */\n+#undef HAVE_LIBXCVT\n+\n /* Define to 1 if you have the `cbrt' function. */\n #undef HAVE_CBRT\n\n@@ -83,6 +83,9 @@\n /* Define to 1 if you have the <fcntl.h> header file. */\n #undef HAVE_FCNTL_H\n \n+/* Have GBM support */\n+#undef HAVE_GBM\n+\n /* Define to 1 if you have the `getdtablesize' function. */\n #undef HAVE_GETDTABLESIZE\n \n"
  },
  {
    "path": "unix/xserver21.patch",
    "content": "diff --git a/configure.ac b/configure.ac\nindex fad7b5769..2c167de3d 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -72,6 +72,7 @@ dnl forcing an entire recompile.x\n AC_CONFIG_HEADERS(include/version-config.h)\n \n AM_PROG_AS\n+AC_PROG_CXX\n AC_PROG_LN_S\n LT_PREREQ([2.2])\n LT_INIT([disable-static win32-dll])\n@@ -1720,6 +1721,19 @@ if test \"x$XVFB\" = xyes; then\n \tAC_SUBST([XVFB_SYS_LIBS])\n fi\n \n+dnl Xvnc DDX\n+AC_SUBST([XVNC_LIBS], [\"$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB\"])\n+AC_SUBST([XVNC_SYS_LIBS], [\"$GLX_SYS_LIBS\"])\n+\n+PKG_CHECK_MODULES(GBM, \"$LIBGBM\", [GBM=yes], [GBM=no])\n+if test \"x$GBM\" = xyes; then\n+\tAC_DEFINE(HAVE_GBM, 1, [Have GBM support])\n+fi\n+\n+PKG_CHECK_MODULES(LIBXCVT, \"$LIBXCVT\", [XCVT=yes], [XCVT=no])\n+if test \"x$XCVT\" = xyes; then\n+\tAC_DEFINE(HAVE_LIBXCVT, 1, [Have libxcvt support])\n+fi\n \n dnl Xnest DDX\n \n@@ -2038,7 +2047,6 @@ if test \"x$GLAMOR\" = xyes; then\n \t\t\t [AC_DEFINE(GLAMOR_HAS_EGL_QUERY_DRIVER, 1, [Have GLAMOR_HAS_EGL_QUERY_DRIVER])],\n \t\t\t [])\n \n-\tPKG_CHECK_MODULES(GBM, \"$LIBGBM\", [GBM=yes], [GBM=no])\n \tif test \"x$GBM\" = xyes; then\n \t\tAC_DEFINE(GLAMOR_HAS_GBM, 1,\n \t\t\t  [Build glamor with GBM-based EGL support])\n@@ -2346,6 +2354,7 @@ hw/xfree86/utils/man/Makefile\n hw/xfree86/utils/gtf/Makefile\n hw/vfb/Makefile\n hw/vfb/man/Makefile\n+hw/vnc/Makefile\n hw/xnest/Makefile\n hw/xnest/man/Makefile\n hw/xwin/Makefile\ndiff --git a/hw/Makefile.am b/hw/Makefile.am\nindex 1749018fa..1172cd59b 100644\n--- a/hw/Makefile.am\n+++ b/hw/Makefile.am\n@@ -34,3 +34,5 @@ DIST_SUBDIRS = xfree86 vfb xnest xwin xquartz kdrive\n \n relink:\n \t$(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done\n+\n+SUBDIRS += vnc\ndiff --git a/include/dix-config.h.in b/include/dix-config.h.in\nindex 382d70609..04a4fd263 100644\n--- a/include/dix-config.h.in\n+++ b/include/dix-config.h.in\n@@ -63,6 +63,9 @@\n /* Has libunwind support */\n #undef HAVE_LIBUNWIND\n\n+/* Have libxcvt support */\n+#undef HAVE_LIBXCVT\n+\n /* Define to 1 if you have the `cbrt' function. */\n #undef HAVE_CBRT\n\n@@ -77,6 +77,9 @@\n /* Define to 1 if you have the <fcntl.h> header file. */\n #undef HAVE_FCNTL_H\n \n+/* Have GBM support */\n+#undef HAVE_GBM\n+\n /* Define to 1 if you have the `getdtablesize' function. */\n #undef HAVE_GETDTABLESIZE\n \n"
  },
  {
    "path": "win/CMakeLists.txt",
    "content": "if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)\n  message(FATAL_ERROR \"cmake must be invoked with the top level directory\")\nendif()\n\ninclude_directories(${CMAKE_SOURCE_DIR}/common ${CMAKE_SOURCE_DIR}/win)\n\nconfigure_file(resdefs.h.in ${CMAKE_CURRENT_BINARY_DIR}/resdefs.h)\n\nadd_subdirectory(rfb_win32)\n\nif(BUILD_WINVNC)\nadd_subdirectory(vncconfig)\nadd_subdirectory(winvnc)\nadd_subdirectory(wm_hooks)\nendif()\n"
  },
  {
    "path": "win/logmessages/messages.h",
    "content": "//\n//  Values are 32 bit values layed out as follows:\n//\n//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1\n//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0\n//  +---+-+-+-----------------------+-------------------------------+\n//  |Sev|C|R|     Facility          |               Code            |\n//  +---+-+-+-----------------------+-------------------------------+\n//\n//  where\n//\n//      Sev - is the severity code\n//\n//          00 - Success\n//          01 - Informational\n//          10 - Warning\n//          11 - Error\n//\n//      C - is the Customer code flag\n//\n//      R - is a reserved bit\n//\n//      Facility - is the facility code\n//\n//      Code - is the facility's status code\n//\n//\n// Define the facility codes\n//\n\n\n//\n// Define the severity codes\n//\n\n\n//\n// MessageId: VNC4LogMessage\n//\n// MessageText:\n//\n//  %1: %2\n//  \n//  \n//\n#define VNC4LogMessage                   0x00000001L\n\n"
  },
  {
    "path": "win/logmessages/messages.mc",
    "content": "MessageId=0x1\nSeverity=Success\nSymbolicName=VNC4LogMessage\nLanguage=English\n%1: %2\n\n\n"
  },
  {
    "path": "win/logmessages/messages.rc",
    "content": "LANGUAGE 0x9,0x1\n1 11 MSG00001.bin\n"
  },
  {
    "path": "win/resdefs.h.in",
    "content": "#define __VERSIONSTR \"@VERSION@\\0\"\n#define __RCVERSION @RCVERSION@\n#define __RCVERSIONSTR \"@RCVERSION@\\0\"\n"
  },
  {
    "path": "win/rfb_win32/AboutDialog.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/AboutDialog.h>\n#include <rfb_win32/Win32Util.h>\n\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic core::LogWriter vlog(\"AboutDialog\");\n\nAboutDialog AboutDialog::instance;\n\n\nAboutDialog::AboutDialog() : Dialog(GetModuleHandle(nullptr)) {\n}\n\nbool AboutDialog::showDialog() {\n  return Dialog::showDialog(MAKEINTRESOURCE(DialogId));\n}\n\nvoid AboutDialog::initDialog() {\n  // Set the build time field\n  SetWindowText(GetDlgItem(handle, BuildTime), buildTime);\n\n  // Get our executable's version info\n  FileVersionInfo verInfo;\n\n  SetWindowText(GetDlgItem(handle, Version), verInfo.getVerString(\"ProductVersion\"));\n  SetWindowText(GetDlgItem(handle, Copyright), verInfo.getVerString(\"LegalCopyright\"));\n  SetWindowText(GetDlgItem(handle, Description), verInfo.getVerString(\"ProductName\"));\n}\n"
  },
  {
    "path": "win/rfb_win32/AboutDialog.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- AboutDialog.h\n\n#ifndef __RFB_WIN32_ABOUT_DIALOG_H__\n#define __RFB_WIN32_ABOUT_DIALOG_H__\n\n#include <rfb_win32/Dialog.h>\n\nextern const char* buildTime;\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class AboutDialog : Dialog {\n    public:\n      AboutDialog();\n      virtual bool showDialog();\n      void initDialog() override;\n\n      static AboutDialog instance;\n\n      typedef WORD LabelId;\n      static const LabelId DialogId;    // Resource ID of the About dialog\n      static const LabelId BuildTime;   // Resource ID of the BuildTime label in the dialog\n      static const LabelId Version;     // etc...\n      static const LabelId Copyright;\n      static const LabelId Description;\n    protected:\n      WORD dialogId;\n    };\n\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/BitmapInfo.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_WIN32_BITMAP_INFO_H__\n#define __RFB_WIN32_BITMAP_INFO_H__\n\n#include <windows.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    struct BitmapInfo {\n      BITMAPINFOHEADER bmiHeader;\n      union {\n        struct {\n          DWORD red;\n          DWORD green;\n          DWORD blue;\n        } mask;\n        RGBQUAD color[256];\n      };\n    };\n\n    inline void initMaxAndShift(DWORD mask, int* max, int* shift) {\n      for ((*shift) = 0; (mask & 1) == 0; (*shift)++) mask >>= 1;\n        (*max) = (uint16_t)mask;\n    }\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/CMakeLists.txt",
    "content": "add_library(rfb_win32 STATIC\n  AboutDialog.cxx\n  Clipboard.cxx\n  CurrentUser.cxx\n  DeviceContext.cxx\n  DeviceFrameBuffer.cxx\n  Dialog.cxx\n  DIBSectionBuffer.cxx\n  EventManager.cxx\n  LaunchProcess.cxx\n  ListViewControl.cxx\n  MonitorInfo.cxx\n  MsgWindow.cxx\n  RegConfig.cxx\n  Registry.cxx\n  SecurityPage.cxx\n  SDisplayCorePolling.cxx\n  SDisplayCoreWMHooks.cxx\n  SDisplay.cxx\n  Security.cxx\n  Service.cxx\n  SInput.cxx\n  SocketManager.cxx\n  TsSessions.cxx\n  Win32Util.cxx\n  WMCursor.cxx\n  WMHooks.cxx\n  WMNotifier.cxx\n  WMPoller.cxx\n  WMShatter.cxx\n  WMWindowCopyRect.cxx)\n\nif(BUILD_WINVNC)\n  target_sources(rfb_win32 PRIVATE ${RFB_WIN32_SOURCES} CleanDesktop.cxx)\nendif()\n\ntarget_link_libraries(rfb_win32 user32.lib comctl32.lib wtsapi32.lib version.lib)\n"
  },
  {
    "path": "win/rfb_win32/CleanDesktop.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- CleanDesktop.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <windows.h>\n#include <wininet.h>\n#include <shlobj.h>\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/CleanDesktop.h>\n#include <rfb_win32/CurrentUser.h>\n#include <rfb_win32/Registry.h>\n\n#include <set>\n\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic core::LogWriter vlog(\"CleanDesktop\");\n\n\nstruct ActiveDesktop {\n  ActiveDesktop() : handle(nullptr) {\n    // - Contact Active Desktop\n    HRESULT result = CoCreateInstance(CLSID_ActiveDesktop, nullptr, CLSCTX_INPROC_SERVER,\n                                      IID_IActiveDesktop, (PVOID*)&handle);\n    if (result != S_OK)\n      throw core::win32_error(\"Failed to contact Active Desktop\", HRESULT_CODE(result));\n  }\n  ~ActiveDesktop() {\n    if (handle)\n      handle->Release();\n  }\n\n  // enableItem\n  //   enables or disables the Nth Active Desktop item\n  bool enableItem(int i, bool enable_) {\n    COMPONENT item;\n    memset(&item, 0, sizeof(item));\n    item.dwSize = sizeof(item);\n\n    HRESULT hr = handle->GetDesktopItem(i, &item, 0);\n    if (hr != S_OK) {\n      vlog.error(\"Unable to GetDesktopItem %d: %ld\", i, hr);\n      return false;\n    }\n    item.fChecked = enable_;\n\n    hr = handle->ModifyDesktopItem(&item, COMP_ELEM_CHECKED);\n    return hr == S_OK;\n  }\n  \n  // enable\n  //   Attempts to enable/disable Active Desktop, returns true if the setting changed,\n  //   false otherwise.\n  //   If Active Desktop *can* be enabled/disabled then that is done.\n  //   If Active Desktop is always on (XP/2K3) then instead the individual items are\n  //   disabled, and true is returned to indicate that they need to be restored later.\n  bool enable(bool enable_) {\n    bool modifyComponents = false;\n\n    vlog.debug(\"ActiveDesktop::enable\");\n\n    // - Firstly, try to disable Active Desktop entirely\n    HRESULT hr;\n    COMPONENTSOPT adOptions;\n    memset(&adOptions, 0, sizeof(adOptions));\n    adOptions.dwSize = sizeof(adOptions);\n\n    // Attempt to actually disable/enable AD\n    hr = handle->GetDesktopItemOptions(&adOptions, 0);\n    if (hr == S_OK) {\n      // If Active Desktop is already in the desired state then return false (no change)\n      // NB: If AD is enabled AND restoreItems is set then we regard it as disabled...\n      if (((adOptions.fActiveDesktop==0) && restoreItems.empty()) == (enable_==false))\n        return false;\n      adOptions.fActiveDesktop = enable_;\n      hr = handle->SetDesktopItemOptions(&adOptions, 0);\n    }\n    // Apply the change, then test whether it actually took effect\n    if (hr == S_OK)\n      hr = handle->ApplyChanges(AD_APPLY_REFRESH);\n    if (hr == S_OK)\n      hr = handle->GetDesktopItemOptions(&adOptions, 0);\n    if (hr == S_OK)\n      modifyComponents = (adOptions.fActiveDesktop==0) != (enable_==false);\n    if (hr != S_OK) {\n      vlog.error(\"Failed to get/set Active Desktop options: %ld\", hr);\n      return false;\n    }\n\n    if (enable_) {\n      // - We are re-enabling Active Desktop.  If there are components in restoreItems\n      //   then restore them!\n      std::set<int>::const_iterator i;\n      for (i=restoreItems.begin(); i!=restoreItems.end(); i++) {\n        enableItem(*i, true);\n      }\n      restoreItems.clear();\n    } else if (modifyComponents) {\n      // - Disable all currently enabled items, and add the disabled ones to restoreItems\n      int itemCount = 0;\n      hr = handle->GetDesktopItemCount(&itemCount, 0);\n      if (hr != S_OK) {\n        vlog.error(\"Failed to get desktop item count: %ld\", hr);\n        return false;\n      }\n      for (int i=0; i<itemCount; i++) {\n        if (enableItem(i, false))\n          restoreItems.insert(i);\n      }\n    }\n\n    // - Apply whatever changes we have made, but DON'T save them!\n    hr = handle->ApplyChanges(AD_APPLY_REFRESH);\n    return hr == S_OK;\n  }\n  IActiveDesktop* handle;\n  std::set<int> restoreItems;\n};\n\n\nDWORD SysParamsInfo(UINT action, UINT param, PVOID ptr, UINT ini) {\n  DWORD r = ERROR_SUCCESS;\n  if (!SystemParametersInfo(action, param, ptr, ini)) {\n    r = GetLastError();\n    vlog.info(\"SPI error: %lu\", r);\n  }\n  return r;\n}\n\n\nCleanDesktop::CleanDesktop() : restoreActiveDesktop(false),\n                               restoreWallpaper(false),\n                               restoreEffects(false) {\n  CoInitialize(nullptr);\n}\n\nCleanDesktop::~CleanDesktop() {\n  enableEffects();\n  enableWallpaper();\n  CoUninitialize();\n}\n\nvoid CleanDesktop::disableWallpaper() {\n  try {\n    ImpersonateCurrentUser icu;\n\n    vlog.debug(\"Disable desktop wallpaper/Active Desktop\");\n\n    // -=- First attempt to remove the wallpaper using Active Desktop\n    try {\n      ActiveDesktop ad;\n      if (ad.enable(false))\n        restoreActiveDesktop = true;\n    } catch (std::exception& e) {\n      vlog.error(\"%s\", e.what());\n    }\n\n    // -=- Switch of normal wallpaper and notify apps\n    SysParamsInfo(SPI_SETDESKWALLPAPER, 0, (PVOID) \"\", SPIF_SENDCHANGE);\n    restoreWallpaper = true;\n\n  } catch (std::exception& e) {\n    vlog.info(\"%s\", e.what());\n  }\n}\n\nvoid CleanDesktop::enableWallpaper() {\n  try {\n    ImpersonateCurrentUser icu;\n\n    if (restoreActiveDesktop) {\n      vlog.debug(\"Restore Active Desktop\");\n\n      // -=- First attempt to re-enable Active Desktop\n      try {\n        ActiveDesktop ad;\n        ad.enable(true);\n        restoreActiveDesktop = false;\n      } catch (std::exception& e) {\n        vlog.error(\"%s\", e.what());\n      }\n    }\n\n    if (restoreWallpaper) {\n      vlog.debug(\"Restore desktop wallpaper\");\n\n      // -=- Then restore the standard wallpaper if required\n\t    SysParamsInfo(SPI_SETDESKWALLPAPER, 0, nullptr, SPIF_SENDCHANGE);\n      restoreWallpaper = false;\n    }\n\n  } catch (std::exception& e) {\n    vlog.info(\"%s\", e.what());\n  }\n}\n\n\nvoid CleanDesktop::disableEffects() {\n  try {\n    ImpersonateCurrentUser icu;\n\n    vlog.debug(\"Disable desktop effects\");\n\n    SysParamsInfo(SPI_SETFONTSMOOTHING, FALSE, nullptr, SPIF_SENDCHANGE);\n    if (SysParamsInfo(SPI_GETUIEFFECTS, 0, &uiEffects, 0) == ERROR_CALL_NOT_IMPLEMENTED) {\n      SysParamsInfo(SPI_GETCOMBOBOXANIMATION, 0, &comboBoxAnim, 0);\n      SysParamsInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradientCaptions, 0);\n      SysParamsInfo(SPI_GETHOTTRACKING, 0, &hotTracking, 0);\n      SysParamsInfo(SPI_GETLISTBOXSMOOTHSCROLLING, 0, &listBoxSmoothScroll, 0);\n      SysParamsInfo(SPI_GETMENUANIMATION, 0, &menuAnim, 0);\n      SysParamsInfo(SPI_SETCOMBOBOXANIMATION, 0, (PVOID)FALSE, SPIF_SENDCHANGE);\n      SysParamsInfo(SPI_SETGRADIENTCAPTIONS, 0, (PVOID)FALSE, SPIF_SENDCHANGE);\n      SysParamsInfo(SPI_SETHOTTRACKING, 0, (PVOID)FALSE, SPIF_SENDCHANGE);\n      SysParamsInfo(SPI_SETLISTBOXSMOOTHSCROLLING, 0, (PVOID)FALSE, SPIF_SENDCHANGE);\n      SysParamsInfo(SPI_SETMENUANIMATION, 0, (PVOID)FALSE, SPIF_SENDCHANGE);\n    } else {\n      SysParamsInfo(SPI_SETUIEFFECTS, 0, (PVOID)FALSE, SPIF_SENDCHANGE);\n\n      // We *always* restore UI effects overall, since there is no Windows GUI to do it\n      uiEffects = TRUE;\n    }\n    restoreEffects = true;\n\n  } catch (std::exception& e) {\n    vlog.info(\"%s\", e.what());\n  }\n}\n\nvoid CleanDesktop::enableEffects() {\n  try {\n    if (restoreEffects) {\n      ImpersonateCurrentUser icu;\n\n      vlog.debug(\"Restore desktop effects\");\n\n      RegKey desktopCfg;\n      desktopCfg.openKey(HKEY_CURRENT_USER, \"Control Panel\\\\Desktop\");\n      SysParamsInfo(SPI_SETFONTSMOOTHING, desktopCfg.getInt(\"FontSmoothing\", 0) != 0, nullptr, SPIF_SENDCHANGE);\n      if (SysParamsInfo(SPI_SETUIEFFECTS, 0, (void*)(intptr_t)uiEffects, SPIF_SENDCHANGE) == ERROR_CALL_NOT_IMPLEMENTED) {\n        SysParamsInfo(SPI_SETCOMBOBOXANIMATION, 0, (void*)(intptr_t)comboBoxAnim, SPIF_SENDCHANGE);\n        SysParamsInfo(SPI_SETGRADIENTCAPTIONS, 0, (void*)(intptr_t)gradientCaptions, SPIF_SENDCHANGE);\n        SysParamsInfo(SPI_SETHOTTRACKING, 0, (void*)(intptr_t)hotTracking, SPIF_SENDCHANGE);\n        SysParamsInfo(SPI_SETLISTBOXSMOOTHSCROLLING, 0, (void*)(intptr_t)listBoxSmoothScroll, SPIF_SENDCHANGE);\n        SysParamsInfo(SPI_SETMENUANIMATION, 0, (void*)(intptr_t)menuAnim, SPIF_SENDCHANGE);\n      }\n      restoreEffects = false;\n    }\n\n  } catch (std::exception& e) {\n    vlog.info(\"%s\", e.what());\n  }\n}\n"
  },
  {
    "path": "win/rfb_win32/CleanDesktop.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- CleanDesktop.h\n\n#ifndef __RFB_WIN32_CLEANDESKTOP_H__\n#define __RFB_WIN32_CLEANDESKTOP_H__\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class CleanDesktop {\n    public:\n      CleanDesktop();\n      ~CleanDesktop();\n\n      void disableWallpaper();\n      void enableWallpaper();\n\n      void disablePattern();\n      void enablePattern();\n\n      void disableEffects();\n      void enableEffects();\n\n    private:\n      bool restoreActiveDesktop;\n      bool restoreWallpaper;\n      bool restorePattern;\n      bool restoreEffects;\n      BOOL uiEffects;\n      BOOL comboBoxAnim, gradientCaptions, hotTracking, listBoxSmoothScroll, menuAnim;\n    };\n\n  }; // win32\n\n}; // rfb\n\n#endif // __RFB_WIN32_CLEANDESKTOP_H__\n"
  },
  {
    "path": "win/rfb_win32/Clipboard.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2012-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Clipboard.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <core/Exception.h>\n\n#include <rfb_win32/Clipboard.h>\n#include <rfb_win32/WMShatter.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"Clipboard\");\n\n//\n// -=- Clipboard object\n//\n\nClipboard::Clipboard()\n  : MsgWindow(\"Clipboard\"), notifier(nullptr), next_window(nullptr) {\n  next_window = SetClipboardViewer(getHandle());\n  vlog.debug(\"Registered clipboard handler\");\n}\n\nClipboard::~Clipboard() {\n  vlog.debug(\"Removing %p from chain (next is %p)\", getHandle(), next_window);\n  ChangeClipboardChain(getHandle(), next_window);\n}\n\nLRESULT\nClipboard::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {\n  switch (msg) {\n\n  case WM_CHANGECBCHAIN:\n    vlog.debug(\"Change clipboard chain (%I64x, %I64x)\",\n               (long long)wParam, (long long)lParam);\n    if ((HWND) wParam == next_window)\n      next_window = (HWND) lParam;\n    else if (next_window != nullptr)\n      SendMessage(next_window, msg, wParam, lParam);\n    else\n      vlog.error(\"Bad clipboard chain change!\");\n    break;\n\n  case WM_DRAWCLIPBOARD:\n    {\n      HWND owner = GetClipboardOwner();\n      if (owner == getHandle()) {\n        vlog.debug(\"Local clipboard changed by me\");\n      } else {\n        vlog.debug(\"Local clipboard changed by %p\", owner);\n\n        if (notifier == nullptr)\n          vlog.debug(\"No clipboard notifier registered\");\n        else\n          notifier->notifyClipboardChanged(IsClipboardFormatAvailable(CF_UNICODETEXT));\n\t\t\t}\n    }\n    if (next_window)\n\t\t  SendMessage(next_window, msg, wParam, lParam);\n    return 0;\n\n  };\n  return MsgWindow::processMessage(msg, wParam, lParam);\n};\n\nstd::string\nClipboard::getClipText() {\n  HGLOBAL cliphandle;\n  wchar_t* clipdata;\n  std::string utf8;\n\n  // Open the clipboard\n  if (!OpenClipboard(getHandle()))\n    return nullptr;\n\n  // Get the clipboard data\n  cliphandle = GetClipboardData(CF_UNICODETEXT);\n  if (!cliphandle) {\n    CloseClipboard();\n    return nullptr;\n  }\n\n  clipdata = (wchar_t*) GlobalLock(cliphandle);\n  if (!clipdata) {\n    CloseClipboard();\n    return nullptr;\n  }\n\n  // Convert it to UTF-8\n  utf8 = utf16ToUTF8(clipdata);\n\n  // Release the buffer and close the clipboard\n  GlobalUnlock(cliphandle);\n  CloseClipboard();\n\n  return convertLF(utf8.c_str());\n}\n\nvoid\nClipboard::setClipText(const char* text) {\n  HANDLE clip_handle = nullptr;\n\n  try {\n\n    // - Firstly, we must open the clipboard\n    if (!OpenClipboard(getHandle()))\n      throw core::win32_error(\"Unable to open Win32 clipboard\", GetLastError());\n\n    // - Convert the supplied clipboard text into UTF-16 format with CRLF\n    std::string filtered(convertCRLF(text));\n    std::wstring utf16(utf8ToUTF16(filtered.c_str()));\n\n    // - Allocate global memory for the data\n    clip_handle = ::GlobalAlloc(GMEM_MOVEABLE, (utf16.size() + 1) * 2);\n\n    wchar_t* data = (wchar_t*) GlobalLock(clip_handle);\n    wcscpy(data, utf16.c_str());\n    GlobalUnlock(clip_handle);\n\n    // - Next, we must clear out any existing data\n    if (!EmptyClipboard())\n      throw core::win32_error(\"Unable to empty Win32 clipboard\", GetLastError());\n\n    // - Set the new clipboard data\n    if (!SetClipboardData(CF_UNICODETEXT, clip_handle))\n      throw core::win32_error(\"Unable to set Win32 clipboard\", GetLastError());\n    clip_handle = nullptr;\n\n    vlog.debug(\"Set clipboard\");\n  } catch (std::exception& e) {\n    vlog.debug(\"%s\", e.what());\n  }\n\n  // - Close the clipboard\n  if (!CloseClipboard())\n    vlog.debug(\"Unable to close Win32 clipboard: %lu\", GetLastError());\n  else\n    vlog.debug(\"Closed clipboard\");\n  if (clip_handle) {\n    vlog.debug(\"Freeing clipboard handle\");\n    GlobalFree(clip_handle);\n  }\n}\n"
  },
  {
    "path": "win/rfb_win32/Clipboard.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2016-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Clipboard.h\n//\n// The Clipboard is used to set the system clipboard, and to get callbacks\n// when the system clipboard has changed.\n\n#ifndef __RFB_WIN32_CLIPBOARD_H__\n#define __RFB_WIN32_CLIPBOARD_H__\n\n#include <rfb/SDesktop.h>\n#include <rfb_win32/MsgWindow.h>\n#include <rfb_win32/DeviceFrameBuffer.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class Clipboard : MsgWindow {\n    public:\n\n      // -=- Abstract base class for callback recipients\n      class Notifier {\n      public:\n        virtual void notifyClipboardChanged(bool available) = 0;\n        virtual ~Notifier() {};\n      };\n\n      Clipboard();\n      ~Clipboard();\n\n      // - Set the notifier to use\n      void setNotifier(Notifier* cbn) {notifier = cbn;}\n\n      // - Get the clipboard contents\n      std::string getClipText();\n\n      // - Set the clipboard contents\n      void setClipText(const char* text);\n\n    protected:\n      // - Internal MsgWindow callback\n      LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) override;\n\n      Notifier* notifier;\n      HWND next_window;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_CLIPBOARD_H__\n"
  },
  {
    "path": "win/rfb_win32/CompatibleBitmap.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_WIN32_COMPAT_BITMAP_H__\n#define __RFB_WIN32_COMPAT_BITMAP_H__\n\n#include <windows.h>\n#include <core/Exception.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    class CompatibleBitmap {\n    public:\n      CompatibleBitmap(HDC hdc, int width, int height) {\n        hbmp = CreateCompatibleBitmap(hdc, width, height);\n        if (!hbmp)\n          throw core::win32_error(\"CreateCompatibleBitmap() failed\", GetLastError());\n      }\n      virtual ~CompatibleBitmap() {\n        if (hbmp) DeleteObject(hbmp);\n      }\n      operator HBITMAP() const {return hbmp;}\n    protected:\n      HBITMAP hbmp;\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/ComputerName.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_WIN32_COMPUTERNAME_H__\n#define __RFB_WIN32_COMPUTERNAME_H__\n\n#include <windows.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    // Get the computer name\n    struct ComputerName {\n      ComputerName() {\n        ULONG namelength = MAX_COMPUTERNAME_LENGTH+1;\n        if (!GetComputerName(buf, &namelength))\n          strcpy(buf, \"\");\n      }\n      char buf[MAX_COMPUTERNAME_LENGTH+1];\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/CurrentUser.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Currentuser.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <stdlib.h>\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/CurrentUser.h>\n#include <rfb_win32/Service.h>\n\n#include <lmcons.h>\n#include <wtsapi32.h>\n\nusing namespace rfb;\nusing namespace win32;\n\nstatic core::LogWriter vlog(\"CurrentUser\");\n\n\nconst char* shellIconClass = \"Shell_TrayWnd\";\n\nBOOL CALLBACK enumWindows(HWND hwnd, LPARAM lParam) {\n  char className[16];\n  if (GetClassName(hwnd, className, sizeof(className)) &&\n      (strcmp(className, shellIconClass) == 0)) {\n    vlog.debug(\"Located tray icon window (%s)\", className);\n    DWORD processId = 0;\n    GetWindowThreadProcessId(hwnd, &processId);\n    if (!processId)\n      return TRUE;\n    Handle process = OpenProcess(MAXIMUM_ALLOWED, FALSE, processId);\n    if (!process.h)\n      return TRUE;\n    if (!OpenProcessToken(process, MAXIMUM_ALLOWED, (HANDLE*)lParam))\n      return TRUE;\n    vlog.debug(\"Obtained user token\");\n    return FALSE;\n  }\n  return TRUE;\n}\n\nBOOL CALLBACK enumDesktops(LPTSTR lpszDesktop, LPARAM lParam) {\n  HDESK desktop = OpenDesktop(lpszDesktop, 0, FALSE, DESKTOP_ENUMERATE);\n  vlog.debug(\"Opening \\\"%s\\\"\", lpszDesktop);\n  if (!desktop) {\n    vlog.info(\"Desktop \\\"%s\\\" inaccessible\", lpszDesktop);\n    return TRUE;\n  }\n  BOOL result = EnumDesktopWindows(desktop, enumWindows, lParam);\n  if (!CloseDesktop(desktop))\n    vlog.info(\"Unable to close desktop: %ld\", GetLastError());\n  return result;\n}\n\n\nCurrentUserToken::CurrentUserToken() {\n  if (isServiceProcess()) {\n    // Try to get the user token using the Terminal Services APIs\n    WTSQueryUserToken(-1, &h);\n  } else {\n    // Try to open the security token for the User-Mode process\n    if (!OpenProcessToken(GetCurrentProcess(), GENERIC_ALL, &h)) {\n      DWORD err = GetLastError();\n      if (err != ERROR_CALL_NOT_IMPLEMENTED)\n        throw core::win32_error(\"OpenProcessToken failed\", err);\n      h = INVALID_HANDLE_VALUE;\n    }\n  }\n}\n\n\nImpersonateCurrentUser::ImpersonateCurrentUser() {\n  RegCloseKey(HKEY_CURRENT_USER);\n  if (!isServiceProcess())\n    return;\n  if (!token.canImpersonate())\n    throw std::runtime_error(\"Cannot impersonate unsafe or null token\");\n  if (!ImpersonateLoggedOnUser(token)) {\n    DWORD err = GetLastError();\n    if (err != ERROR_CALL_NOT_IMPLEMENTED)\n      throw core::win32_error(\"Failed to impersonate user\", GetLastError());\n  }\n}\n\nImpersonateCurrentUser::~ImpersonateCurrentUser() {\n  if (!RevertToSelf()) {\n    DWORD err = GetLastError();\n    if (err != ERROR_CALL_NOT_IMPLEMENTED)\n      exit(err);\n  }\n  RegCloseKey(HKEY_CURRENT_USER);\n}\n\n\nUserName::UserName() {\n  char buf[UNLEN+1];\n  DWORD len = UNLEN+1;\n  if (!GetUserName(buf, &len))\n    throw core::win32_error(\"GetUserName failed\", GetLastError());\n  assign(buf);\n}\n\n\nUserSID::UserSID() {\n  CurrentUserToken token;\n  if (!token.canImpersonate())\n    return;\n  setSID(Sid::FromToken(token.h));\n}\n"
  },
  {
    "path": "win/rfb_win32/CurrentUser.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// CurrentUser.h\n\n// Helper class providing the session's logged on username, if\n// a user is logged on.  Also allows processes running under\n// XP/2K3 etc to masquerade as the logged on user for security\n// purposes\n\n#ifndef __RFB_WIN32_CURRENT_USER_H__\n#define __RFB_WIN32_CURRENT_USER_H__\n\n#include <string>\n\n#include <rfb_win32/Handle.h>\n#include <rfb_win32/Security.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    // CurrentUserToken\n    //   CurrentUserToken is a Handle containing the security token\n    //   for the currently logged-on user, or null if no user is\n    //   logged on.\n    //\n    //   canImpersonate() tests whether there is a user token that is safe\n    //   to impersonate.\n    //\n    //   noUserLoggedOn() tests whether there is *definitely* no user logged on.\n\n    struct CurrentUserToken : public Handle {\n      CurrentUserToken();\n      bool canImpersonate() const { return h; }\n      bool noUserLoggedOn() const { return !h; }\n    };\n\n    // ImpersonateCurrentUser\n    //   Throws an exception on failure.\n    //   Succeeds (trivially) if process is not running as service.\n    //   Fails if CurrentUserToken is not valid.\n    //   Fails if cannot impersonate token.\n    //   Succeeds otherwise.\n\n    struct ImpersonateCurrentUser {\n      ImpersonateCurrentUser();\n      ~ImpersonateCurrentUser();\n      CurrentUserToken token;\n    };\n\n    // UserName\n    //   Returns the name of the user the thread is currently running as.\n    //   Raises a SystemException in case of error.\n\n    struct UserName : public std::string {\n      UserName();\n    };\n\n    // UserSID\n    //   Returns the SID of the currently logged-on user (i.e. the session user)\n\n    struct UserSID : public Sid {\n      UserSID();\n    };\n\n  }\n\n}\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/DIBSectionBuffer.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/DIBSectionBuffer.h>\n#include <rfb_win32/DeviceContext.h>\n#include <rfb_win32/BitmapInfo.h>\n\nusing namespace rfb;\nusing namespace win32;\n\nstatic core::LogWriter vlog(\"DIBSectionBuffer\");\n\n\nDIBSectionBuffer::DIBSectionBuffer(HWND window_)\n  : bitmap(nullptr), window(window_), device(nullptr) {\n}\n\nDIBSectionBuffer::DIBSectionBuffer(HDC device_)\n  : bitmap(nullptr), window(nullptr), device(device_) {\n}\n\nDIBSectionBuffer::~DIBSectionBuffer() {\n  if (bitmap)\n    DeleteObject(bitmap);\n}\n\n\ninline void initMaxAndShift(DWORD mask, int* max, int* shift) {\n  for ((*shift) = 0; (mask & 1) == 0; (*shift)++) mask >>= 1;\n  (*max) = (uint16_t)mask;\n}\n\nvoid DIBSectionBuffer::initBuffer(const PixelFormat& pf, int w, int h) {\n  HBITMAP new_bitmap = nullptr;\n  uint8_t* new_data = nullptr;\n\n  if (!pf.trueColour)\n    throw std::invalid_argument(\"Palette format not supported\");\n\n  format = pf;\n\n  if (w && h && (format.depth != 0)) {\n    BitmapInfo bi;\n    memset(&bi, 0, sizeof(bi));\n    UINT iUsage = DIB_RGB_COLORS;\n    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\n    bi.bmiHeader.biBitCount = format.bpp;\n    bi.bmiHeader.biSizeImage = (format.bpp / 8) * w * h;\n    bi.bmiHeader.biPlanes = 1;\n    bi.bmiHeader.biWidth = w;\n    bi.bmiHeader.biHeight = -h;\n    bi.bmiHeader.biCompression = (format.bpp > 8) ? BI_BITFIELDS : BI_RGB;\n    bi.mask.red = format.pixelFromRGB((uint16_t)~0, 0, 0);\n    bi.mask.green = format.pixelFromRGB(0, (uint16_t)~0, 0);\n    bi.mask.blue = format.pixelFromRGB(0, 0, (uint16_t)~0);\n\n    // Create a DIBSection to draw into\n    if (device)\n      new_bitmap = ::CreateDIBSection(device, (BITMAPINFO*)&bi.bmiHeader, iUsage,\n                                      (void**)&new_data, nullptr, 0);\n    else\n      new_bitmap = ::CreateDIBSection(WindowDC(window), (BITMAPINFO*)&bi.bmiHeader, iUsage,\n                                      (void**)&new_data, nullptr, 0);\n\n    if (!new_bitmap) {\n      int err = GetLastError();\n      throw core::win32_error(\"Unable to create DIB section\", err);\n    }\n\n    vlog.debug(\"recreateBuffer()\");\n  } else {\n    vlog.debug(\"One of area or format not set\");\n  }\n\n  if (new_bitmap && bitmap) {\n    vlog.debug(\"Preserving bitmap contents\");\n\n    // Copy the contents across\n    if (device) {\n      BitmapDC src_dev(device, bitmap);\n      BitmapDC dest_dev(device, new_bitmap);\n      BitBlt(dest_dev, 0, 0, w, h, src_dev, 0, 0, SRCCOPY);\n    } else {\n      WindowDC wndDC(window);\n      BitmapDC src_dev(wndDC, bitmap);\n      BitmapDC dest_dev(wndDC, new_bitmap);\n      BitBlt(dest_dev, 0, 0, w, h, src_dev, 0, 0, SRCCOPY);\n    }\n  }\n  \n  if (bitmap) {\n    // Delete the old bitmap\n    DeleteObject(bitmap);\n    bitmap = nullptr;\n    setBuffer(0, 0, nullptr, 0);\n  }\n\n  if (new_bitmap) {\n    int bpp, depth;\n    int redMax, greenMax, blueMax;\n    int redShift, greenShift, blueShift;\n    int new_stride;\n\n    // Set up the new bitmap\n    bitmap = new_bitmap;\n\n    // Determine the *actual* DIBSection format\n    DIBSECTION ds;\n    if (!GetObject(bitmap, sizeof(ds), &ds))\n      throw core::win32_error(\"GetObject\", GetLastError());\n\n    // Correct the \"stride\" of the DIB\n    // *** This code DWORD aligns each row - is that right???\n    new_stride = w;\n    int bytesPerRow = new_stride * format.bpp/8;\n    if (bytesPerRow % 4) {\n      bytesPerRow += 4 - (bytesPerRow % 4);\n      new_stride = (bytesPerRow * 8) / format.bpp;\n      vlog.info(\"Adjusting DIB stride: %d to %d\", w, new_stride);\n    }\n\n    setBuffer(w, h, new_data, new_stride);\n\n    // Calculate the PixelFormat for the DIB\n    bpp = depth = ds.dsBm.bmBitsPixel;\n\n    // Get the truecolour format used by the DIBSection\n    initMaxAndShift(ds.dsBitfields[0], &redMax, &redShift);\n    initMaxAndShift(ds.dsBitfields[1], &greenMax, &greenShift);\n    initMaxAndShift(ds.dsBitfields[2], &blueMax, &blueShift);\n\n    // Calculate the effective depth\n    depth = 0;\n    Pixel bits = ds.dsBitfields[0] | ds.dsBitfields[1] | ds.dsBitfields[2];\n    while (bits) {\n      depth++;\n      bits = bits >> 1;\n    }\n    if (depth > bpp)\n      throw std::runtime_error(\"Bad DIBSection format (depth exceeds bpp)\");\n\n    format = PixelFormat(bpp, depth, false, true,\n                         redMax, greenMax, blueMax,\n                         redShift, greenShift, blueShift);\n  }\n}\n"
  },
  {
    "path": "win/rfb_win32/DIBSectionBuffer.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- DIBSectionBuffer.h\n\n// A DIBSectionBuffer acts much like a standard PixelBuffer, but is associated\n// with a particular window on-screen and can be drawn into that window if\n// required, using the standard Win32 drawing operations.\n\n#ifndef __RFB_WIN32_DIB_SECTION_BUFFER_H__\n#define __RFB_WIN32_DIB_SECTION_BUFFER_H__\n\n#include <windows.h>\n\n#include <core/Region.h>\n\n#include <rfb/PixelBuffer.h>\n#include <rfb/Exception.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    //\n    // -=- DIBSectionBuffer\n    //\n\n    class DIBSectionBuffer : public FullFramePixelBuffer {\n    public:\n      DIBSectionBuffer(HWND window);\n      DIBSectionBuffer(HDC device);\n      virtual ~DIBSectionBuffer();\n\n    public:\n      HBITMAP bitmap;\n    protected:\n      void initBuffer(const PixelFormat& pf, int w, int h);\n      HWND window;\n      HDC device;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_DIB_SECTION_BUFFER_H__\n"
  },
  {
    "path": "win/rfb_win32/DeviceContext.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/DeviceContext.h>\n#include <rfb_win32/CompatibleBitmap.h>\n#include <rfb_win32/BitmapInfo.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\n\n\nstatic LogWriter vlog(\"DeviceContext\");\n\nPixelFormat DeviceContext::getPF() const {\n  return getPF(dc);\n}\n\nPixelFormat DeviceContext::getPF(HDC dc) {\n  bool trueColour, bigEndian;\n  int bpp, depth;\n  int redMax, greenMax, blueMax;\n  int redShift, greenShift, blueShift;\n\n  CompatibleBitmap bitmap(dc, 1, 1);\n\n  // -=- Get the bitmap format information\n  BitmapInfo bi;\n  memset(&bi, 0, sizeof(bi));\n  bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\n  bi.bmiHeader.biBitCount = 0;\n  if (!::GetDIBits(dc, bitmap, 0, 1, nullptr, (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {\n    throw core::win32_error(\"Unable to determine device pixel format\", GetLastError());\n  }\n  if (!::GetDIBits(dc, bitmap, 0, 1, nullptr, (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {\n    throw core::win32_error(\"Unable to determine pixel shifts/palette\", GetLastError());\n  }\n\n  // Set the initial format information\n  trueColour = bi.bmiHeader.biBitCount > 8;\n  bigEndian = 0;\n  bpp = bi.bmiHeader.biBitCount;\n\n  if (trueColour) {\n    DWORD rMask=0, gMask=0, bMask=0;\n\n    // Which true colour format is the DIB section using?\n    switch (bi.bmiHeader.biCompression) {\n    case BI_RGB:\n      // Default RGB layout\n      switch (bi.bmiHeader.biBitCount) {\n      case 16:\n        // RGB 555 - High Colour\n        vlog.info(\"16-bit High Colour\");\n        rMask = 0x7c00;\n        bMask = 0x001f;\n        gMask = 0x03e0;\n        break;\n      case 24:\n      case 32:\n        // RGB 888 - True Colour\n        vlog.info(\"24/32-bit High Colour\");\n        rMask = 0xff0000;\n        gMask = 0x00ff00;\n        bMask = 0x0000ff;\n        break;\n      default:\n        vlog.error(\"Bits per pixel %u not supported\", bi.bmiHeader.biBitCount);\n        throw std::invalid_argument(\"Unknown bits per pixel specified\");\n      };\n      break;\n    case BI_BITFIELDS:\n      // Custom RGB layout\n      rMask = bi.mask.red;\n      gMask = bi.mask.green;\n      bMask = bi.mask.blue;\n      vlog.info(\"%d-bit BitFields: (%lx, %lx, %lx)\",\n                 bi.bmiHeader.biBitCount, rMask, gMask, bMask);\n      break;\n    };\n\n    // Convert the data we just retrieved\n    initMaxAndShift(rMask, &redMax, &redShift);\n    initMaxAndShift(gMask, &greenMax, &greenShift);\n    initMaxAndShift(bMask, &blueMax, &blueShift);\n\n    // Calculate the depth from the colour shifts\n    depth = 0;\n    Pixel bits = rMask | gMask | bMask;\n    while (bits) {\n      depth++;\n      bits = bits >> 1;\n    }\n\n    // Check that the depth & bpp are valid\n    if (depth > bpp) {\n      vlog.error(\"Depth exceeds bits per pixel!\");\n      bpp = depth;\n    }\n\n    // Correct the bits-per-pixel to something we're happy with\n    if (bpp <= 16)\n      bpp = 16;\n    else if (bpp <= 32)\n      bpp = 32;\n  } else {\n    // Palettised format - depth reflects number of colours,\n    // but bits-per-pixel is ALWAYS 8\n    depth = bpp;\n    if (bpp < 8)\n      bpp = 8;\n    vlog.info(\"%d-colour palettised\", 1<<depth);\n    // Aren't really used, but set them to keep the compiler happy\n    redMax = redShift = 0;\n    greenMax = greenShift = 0;\n    blueMax = blueShift = 0;\n  }\n\n\n  return PixelFormat(bpp, depth, bigEndian, trueColour,\n\t\t                 redMax, greenMax, blueMax,\n\t\t                 redShift, greenShift, blueShift);\n}\n\nRect DeviceContext::getClipBox() const {\n  return getClipBox(dc);\n}\n\nRect DeviceContext::getClipBox(HDC dc) {\n  // Get the display dimensions\n  RECT cr;\n  if (!GetClipBox(dc, &cr))\n    throw core::win32_error(\"GetClipBox\", GetLastError());\n  return {cr.left, cr.top, cr.right, cr.bottom};\n}\n\n\nDeviceDC::DeviceDC(const char* deviceName) {\n  dc = ::CreateDC(\"DISPLAY\", deviceName, nullptr, nullptr);\n  if (!dc)\n    throw core::win32_error(\"Failed to create DeviceDC\", GetLastError());\n}\n\nDeviceDC::~DeviceDC() {\n  if (dc)\n    DeleteDC(dc);\n}\n\n\nWindowDC::WindowDC(HWND wnd) : hwnd(wnd) {\n  dc = GetDC(wnd);\n  if (!dc)\n    throw core::win32_error(\"GetDC failed\", GetLastError());\n}\n\nWindowDC::~WindowDC() {\n  if (dc)\n    ReleaseDC(hwnd, dc);\n}\n\n\nCompatibleDC::CompatibleDC(HDC existing) {\n  dc = CreateCompatibleDC(existing);\n  if (!dc)\n    throw core::win32_error(\"CreateCompatibleDC failed\", GetLastError());\n}\n\nCompatibleDC::~CompatibleDC() {\n  if (dc)\n    DeleteDC(dc);\n}\n\n\nBitmapDC::BitmapDC(HDC hdc, HBITMAP hbitmap) : CompatibleDC(hdc){\n  oldBitmap = (HBITMAP)SelectObject(dc, hbitmap);\n  if (!oldBitmap)\n    throw core::win32_error(\"SelectObject to CompatibleDC failed\",\n    GetLastError());\n}\n\nBitmapDC::~BitmapDC() {\n  SelectObject(dc, oldBitmap);\n}\n"
  },
  {
    "path": "win/rfb_win32/DeviceContext.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// DeviceContext base class, wrapping Windows HDC, plus some\n// helper classes tailored to particular types of DC, such as\n// window and device DCs.\n\n#ifndef __RFB_WIN32_DEVICECONTEXT_H__\n#define __RFB_WIN32_DEVICECONTEXT_H__\n\n#include <windows.h>\n\n#include <core/Rect.h>\n\n#include <rfb/PixelFormat.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    // Base class, providing methods to get the bounding (clip) box,\n    // and the pixel format, and access to the HDC itself.\n    class DeviceContext {\n    public:\n      DeviceContext() : dc(nullptr) {}\n      virtual ~DeviceContext() {}\n      operator HDC() const {return dc;}\n      PixelFormat getPF() const;\n      static PixelFormat getPF(HDC dc);\n      core::Rect getClipBox() const;\n      static core::Rect getClipBox(HDC dc);\n    protected:\n      HDC dc;\n    };\n\n    // -=- DeviceContext that opens a specific display device\n    class DeviceDC : public DeviceContext {\n    public:\n      DeviceDC(const char* deviceName);\n      ~DeviceDC();\n    };\n\n    // Get a DC for a particular window's client area.\n    class WindowDC : public DeviceContext {\n    public:\n      WindowDC(HWND wnd);\n      virtual ~WindowDC();\n    protected:\n      HWND hwnd;\n    };\n\n    // Create a new DC, compatible with an existing one.\n    class CompatibleDC : public DeviceContext {\n    public:\n      CompatibleDC(HDC existing);\n      virtual ~CompatibleDC();\n    };\n\n    // Create a new DC, compatible with an existing one, and\n    // select the specified bitmap into it.\n    class BitmapDC : public CompatibleDC {\n    public:\n      BitmapDC(HDC hdc, HBITMAP hbitmap);\n      ~BitmapDC();\n    protected:\n      HBITMAP oldBitmap;\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/DeviceFrameBuffer.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2014-2017 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- DeviceFrameBuffer.cxx\n//\n// The DeviceFrameBuffer class encapsulates the pixel data of the system\n// display.\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <vector>\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/DeviceFrameBuffer.h>\n#include <rfb_win32/DeviceContext.h>\n#include <rfb_win32/IconInfo.h>\n\n#include <rfb/VNCServer.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\n\nstatic LogWriter vlog(\"DeviceFrameBuffer\");\n\nBoolParameter DeviceFrameBuffer::useCaptureBlt(\"UseCaptureBlt\",\n  \"Use a slower capture method that ensures that alpha blended windows appear correctly\",\n  true);\n\n\n// -=- DeviceFrameBuffer class\n\nDeviceFrameBuffer::DeviceFrameBuffer(HDC deviceContext, const Rect& wRect)\n  : DIBSectionBuffer(deviceContext), device(deviceContext),\n    ignoreGrabErrors(false)\n{\n\n  // -=- Firstly, let's check that the device has suitable capabilities\n\n  int capabilities = GetDeviceCaps(device, RASTERCAPS);\n  if (!(capabilities & RC_BITBLT)) {\n    throw std::invalid_argument(\"Device does not support BitBlt\");\n  }\n  if (!(capabilities & RC_DI_BITMAP)) {\n    throw std::invalid_argument(\"Device does not support GetDIBits\");\n  }\n  /*\n  if (GetDeviceCaps(device, PLANES) != 1) {\n    throw std::invalid_argument(\"Device does not support planar displays\");\n  }\n  */\n\n  // -=- Get the display dimensions and pixel format\n\n  // Get the display dimensions\n  deviceCoords = DeviceContext::getClipBox(device);\n  if (!wRect.is_empty())\n    deviceCoords = wRect.translate(deviceCoords.tl);\n  int w = deviceCoords.width();\n  int h = deviceCoords.height();\n\n  // We can't handle uneven widths :(\n  if (w % 2) w--;\n\n  // Configure the underlying DIB to match the device\n  initBuffer(DeviceContext::getPF(device), w, h);\n}\n\nDeviceFrameBuffer::~DeviceFrameBuffer() {\n}\n\n\n#ifndef CAPTUREBLT\n#define CAPTUREBLT 0x40000000\n#endif\n\nvoid\nDeviceFrameBuffer::grabRect(const Rect &rect) {\n  BitmapDC tmpDC(device, bitmap);\n\n  // Map the rectangle coords from VNC Desktop-relative to device relative - usually (0,0)\n  Point src = desktopToDevice(rect.tl);\n\n  if (!::BitBlt(tmpDC, rect.tl.x, rect.tl.y,\n                rect.width(), rect.height(), device, src.x, src.y,\n                useCaptureBlt ? (CAPTUREBLT | SRCCOPY) : SRCCOPY)) {\n    if (ignoreGrabErrors)\n      vlog.error(\"BitBlt failed:%ld\", GetLastError());\n    else\n      throw core::win32_error(\"BitBlt failed\", GetLastError());\n  }\n}\n\nvoid\nDeviceFrameBuffer::grabRegion(const Region &rgn) {\n  std::vector<Rect> rects;\n  std::vector<Rect>::const_iterator i;\n  rgn.get_rects(&rects);\n  for(i=rects.begin(); i!=rects.end(); i++) {\n    grabRect(*i);\n  }\n  ::GdiFlush();\n}\n\n\nvoid DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server)\n{\n  // - If hCursor is null then there is no cursor - clear the old one\n\n  if (hCursor == nullptr) {\n    server->setCursor(0, 0, {}, nullptr);\n    return;\n  }\n\n  try {\n\n    int width, height;\n    std::vector<uint8_t> buffer;\n\n    // - Get the size and other details about the cursor.\n\n    IconInfo iconInfo((HICON)hCursor);\n\n    BITMAP maskInfo;\n    if (!GetObject(iconInfo.hbmMask, sizeof(BITMAP), &maskInfo))\n      throw core::win32_error(\"GetObject() failed\", GetLastError());\n    if (maskInfo.bmPlanes != 1)\n      throw std::invalid_argument(\"Unsupported multi-plane cursor\");\n    if (maskInfo.bmBitsPixel != 1)\n      throw std::invalid_argument(\"Unsupported cursor mask format\");\n\n    width = maskInfo.bmWidth;\n    height = maskInfo.bmHeight;\n    if (!iconInfo.hbmColor)\n      height /= 2;\n\n    buffer.resize(width * height * 4);\n\n    Point hotspot(iconInfo.xHotspot, iconInfo.yHotspot);\n\n    if (iconInfo.hbmColor) {\n      // Colour cursor\n\n      BITMAPV5HEADER bi;\n      BitmapDC dc(device, iconInfo.hbmColor);\n\n      memset(&bi, 0, sizeof(BITMAPV5HEADER));\n\n      bi.bV5Size        = sizeof(BITMAPV5HEADER);\n      bi.bV5Width       = width;\n      bi.bV5Height      = -height; // Negative for top-down\n      bi.bV5Planes      = 1;\n      bi.bV5BitCount    = 32;\n      bi.bV5Compression = BI_BITFIELDS;\n      bi.bV5RedMask     = 0x000000FF;\n      bi.bV5GreenMask   = 0x0000FF00;\n      bi.bV5BlueMask    = 0x00FF0000;\n      bi.bV5AlphaMask   = 0xFF000000;\n\n      if (!GetDIBits(dc, iconInfo.hbmColor, 0, height,\n                     buffer.data(), (LPBITMAPINFO)&bi, DIB_RGB_COLORS))\n        throw core::win32_error(\"GetDIBits\", GetLastError());\n\n      // We may not get the RGBA order we want, so shuffle things around\n      int ridx, gidx, bidx, aidx;\n\n      ridx = __builtin_ffs(bi.bV5RedMask) / 8;\n      gidx = __builtin_ffs(bi.bV5GreenMask) / 8;\n      bidx = __builtin_ffs(bi.bV5BlueMask) / 8;\n      // Usually not set properly\n      aidx = 6 - ridx - gidx - bidx;\n\n      if ((bi.bV5RedMask != ((unsigned)0xff << ridx*8)) ||\n          (bi.bV5GreenMask != ((unsigned)0xff << gidx*8)) ||\n          (bi.bV5BlueMask != ((unsigned)0xff << bidx*8)))\n        throw std::invalid_argument(\"Unsupported cursor colour format\");\n\n      uint8_t* rwbuffer = buffer.data();\n      for (int y = 0; y < height; y++) {\n        for (int x = 0; x < width; x++) {\n          uint8_t r, g, b, a;\n\n          r = rwbuffer[ridx];\n          g = rwbuffer[gidx];\n          b = rwbuffer[bidx];\n          a = rwbuffer[aidx];\n\n          rwbuffer[0] = r;\n          rwbuffer[1] = g;\n          rwbuffer[2] = b;\n          rwbuffer[3] = a;\n\n          rwbuffer += 4;\n        }\n      }\n    } else {\n      // B/W cursor\n\n      std::vector<uint8_t> mask(maskInfo.bmWidthBytes * maskInfo.bmHeight);\n      uint8_t* andMask = mask.data();\n      uint8_t* xorMask = mask.data() + height * maskInfo.bmWidthBytes;\n\n      if (!GetBitmapBits(iconInfo.hbmMask,\n                         maskInfo.bmWidthBytes * maskInfo.bmHeight, mask.data()))\n        throw core::win32_error(\"GetBitmapBits\", GetLastError());\n\n      bool doOutline = false;\n      uint8_t* rwbuffer = buffer.data();\n      for (int y = 0; y < height; y++) {\n        for (int x = 0; x < width; x++) {\n          int byte_ = y * maskInfo.bmWidthBytes + x / 8;\n          int bit = 7 - x % 8;\n\n          if (!(andMask[byte_] & (1 << bit))) {\n            // Valid pixel, so make it opaque\n            rwbuffer[3] = 0xff;\n\n            // Black or white?\n            if (xorMask[byte_] & (1 << bit))\n              rwbuffer[0] = rwbuffer[1] = rwbuffer[2] = 0xff;\n            else\n              rwbuffer[0] = rwbuffer[1] = rwbuffer[2] = 0;\n          } else if (xorMask[byte_] & (1 << bit)) {\n            // Replace any XORed pixels with black, because RFB doesn't support\n            // XORing of cursors.  XORing is used for the I-beam cursor, which is most\n            // often used over a white background, but also sometimes over a black\n            // background.  We set the XOR'd pixels to black, then draw a white outline\n            // around the whole cursor.\n\n            rwbuffer[0] = rwbuffer[1] = rwbuffer[2] = 0;\n            rwbuffer[3] = 0xff;\n\n            doOutline = true;\n          } else {\n            // Transparent pixel\n            rwbuffer[0] = rwbuffer[1] = rwbuffer[2] = rwbuffer[3] = 0;\n          }\n\n          rwbuffer += 4;\n        }\n      }\n\n      if (doOutline) {\n        vlog.debug(\"Drawing cursor outline!\");\n\n        // The buffer needs to be slightly larger to make sure there\n        // is room for the outline pixels\n        std::vector<uint8_t> outline((width + 2)*(height + 2)*4);\n        memset(outline.data(), 0, (width + 2)*(height + 2)*4);\n\n        // Pass 1, outline everything\n        uint8_t* in = buffer.data();\n        uint8_t* out = outline.data() + width*4 + 4;\n        for (int y = 0; y < height; y++) {\n          for (int x = 0; x < width; x++) {\n            // Visible pixel?\n            if (in[3] > 0) {\n              // Outline above...\n              memset(out - (width+2)*4 - 4, 0xff, 4 * 3);\n              // ...besides...\n              memset(out - 4, 0xff, 4 * 3);\n              // ...and above\n              memset(out + (width+2)*4 - 4, 0xff, 4 * 3);\n            }\n            in += 4;\n            out += 4;\n          }\n          // outline is slightly larger\n          out += 2*4;\n        }\n\n        // Pass 2, overwrite with actual cursor\n        in = buffer.data();\n        out = outline.data() + width*4 + 4;\n        for (int y = 0; y < height; y++) {\n          for (int x = 0; x < width; x++) {\n            if (in[3] > 0)\n              memcpy(out, in, 4);\n            in += 4;\n            out += 4;\n          }\n          out += 2*4;\n        }\n\n        width += 2;\n        height += 2;\n        hotspot.x += 1;\n        hotspot.y += 1;\n\n        buffer = outline;\n      }\n    }\n\n    server->setCursor(width, height, hotspot, buffer.data());\n\n  } catch (std::exception& e) {\n    vlog.error(\"%s\", e.what());\n  }\n}\n"
  },
  {
    "path": "win/rfb_win32/DeviceFrameBuffer.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- DeviceFrameBuffer.h\n//\n// The DeviceFrameBuffer class encapsulates the pixel data of a supplied\n// Device Context Handle (HDC)\n\n// *** THIS INTERFACE NEEDS TIDYING TO SEPARATE COORDINATE SYSTEMS BETTER ***\n\n#ifndef __RFB_WIN32_DEVICE_FRAME_BUFFER_H__\n#define __RFB_WIN32_DEVICE_FRAME_BUFFER_H__\n\n#include <windows.h>\n\n#include <core/Configuration.h>\n#include <core/Region.h>\n\n#include <rfb_win32/DIBSectionBuffer.h>\n\n#include <rfb/Cursor.h>\n#include <rfb/Exception.h>\n\nnamespace rfb {\n\n  class VNCServer;\n\n  namespace win32 {\n\n    // -=- DeviceFrameBuffer interface\n\n    // DeviceFrameBuffer is passed an HDC referring to a window or to\n    // the entire display.  It may also be passed a rectangle specifying\n    // the Device-relative coordinates of the actual rectangle to treat\n    // as the desktop.\n\n    // Coordinate systems start getting really annoying here.  There are\n    // three different \"origins\" to which coordinates might be relative:\n    //\n    // Desktop - VNC coordinates, top-left always (0,0)\n    // Device - DC coordinates.  Top-left *usually (0,0) but could be other.\n    // Window - coordinates relative to the specified sub-rectangle within\n    //          the supplied DC.\n    // Screen - Coordinates relative to the entire Windows virtual screen.\n    //          The virtual screen includes all monitors that are part of\n    //          the Windows desktop.\n\n    // The data member is made to point to an internal mirror of the\n    // current display data.  Individual rectangles or regions of the\n    // buffer can be brought up to date by calling the grab functions.\n\n    class DeviceFrameBuffer : public DIBSectionBuffer {\n    public:\n      DeviceFrameBuffer(HDC deviceContext, const core::Rect& area_={});\n      virtual ~DeviceFrameBuffer();\n\n      // - FrameBuffer overrides\n\n      virtual void grabRect(const core::Rect& rect);\n      void grabRegion(const core::Region& region) override;\n\n      // - DeviceFrameBuffer specific methods\n\n      void setCursor(HCURSOR c, VNCServer* server);\n\n      // Set whether grabRect should ignore errors or throw exceptions\n      // Only set this if you are sure you'll capture the errors some other way!\n      void setIgnoreGrabErrors(bool ie) {ignoreGrabErrors=ie;}\n      \n      static core::BoolParameter useCaptureBlt;\n\n    protected:\n      // Translate supplied Desktop coordinates into Device-relative coordinates\n      // This translation may have been affected at start-time by the supplied sub-rect.\n      core::Point desktopToDevice(const core::Point p) const {return p.translate(deviceCoords.tl);}\n\n      HDC device;\n      core::Rect deviceCoords;\n      bool ignoreGrabErrors;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_DEVICE_FRAME_BUFFER_H__\n"
  },
  {
    "path": "win/rfb_win32/Dialog.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2010 D. R. Commander.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Dialog.cxx\n\n// Base-class for any Dialog classes we might require\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/Dialog.h>\n#include <rfb_win32/Win32Util.h>\n\n#ifdef _DIALOG_CAPTURE\n#ifdef PropSheet_IndexToId\n#include <rfb_win32/DeviceFrameBuffer.h>\n#include <extra/LoadBMP.cxx>\n#else\n#undef _DIALOG_CAPTURE\n#pragma message(\"  NOTE: Not building Dialog Capture support.\")\n#endif\n#endif\n\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic core::LogWriter dlog(\"Dialog\");\nstatic core::LogWriter plog(\"PropSheet\");\n\n\nDialog::Dialog(HINSTANCE inst_)\n: inst(inst_), handle(nullptr), alreadyShowing(false)\n{\n}\n\nDialog::~Dialog()\n{\n}\n\n\nbool Dialog::showDialog(const char* resource, HWND owner)\n{\n  if (alreadyShowing) return false;\n  handle = nullptr;\n  alreadyShowing = true;\n  INT_PTR result = DialogBoxParam(inst, resource, owner,\n                                  staticDialogProc, (LPARAM)this);\n  if (result<0)\n    throw core::win32_error(\"DialogBoxParam failed\", GetLastError());\n  alreadyShowing = false;\n  return (result == 1);\n}\n\n\nbool Dialog::isItemChecked(int id) {\n  return SendMessage(GetDlgItem(handle, id), BM_GETCHECK, 0, 0) == BST_CHECKED;\n}\nint Dialog::getItemInt(int id) {\n  BOOL trans;\n  int result = GetDlgItemInt(handle, id, &trans, TRUE);\n  if (!trans)\n    throw std::runtime_error(\"Unable to read dialog Int\");\n  return result;\n}\nconst char* Dialog::getItemString(int id) {\n  static char tmp[256];\n  if (!GetDlgItemText(handle, id, tmp, 256))\n    return \"\";\n  return tmp;\n}\n\nvoid Dialog::setItemChecked(int id, bool state) {\n  SendMessage(GetDlgItem(handle, id), BM_SETCHECK, state ? BST_CHECKED : BST_UNCHECKED, 0);\n}\nvoid Dialog::setItemInt(int id, int value) {\n  SetDlgItemInt(handle, id, value, TRUE);\n}\nvoid Dialog::setItemString(int id, const char* s) {\n  SetDlgItemText(handle, id, s);\n}\n\n\nvoid Dialog::enableItem(int id, bool state) {\n  EnableWindow(GetDlgItem(handle, id), state);\n}\n\n\n\n\nINT_PTR CALLBACK Dialog::staticDialogProc(HWND hwnd, UINT msg,\n\t\t\t\t       WPARAM wParam, LPARAM lParam)\n{\n  if (msg == WM_INITDIALOG)\n    SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);\n\n  LONG_PTR self = GetWindowLongPtr(hwnd, GWLP_USERDATA);\n  if (!self) return FALSE;\n\n  return ((Dialog*)self)->dialogProc(hwnd, msg, wParam, lParam);\n}\n\nBOOL Dialog::dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\n{\n  switch (msg) {\n\n  case WM_INITDIALOG:\n    handle = hwnd;\n    initDialog();\n    return TRUE;\n\n  case WM_COMMAND:\n    switch (LOWORD(wParam)) {\n    case IDOK:\n      if (onOk()) {\n        EndDialog(hwnd, 1);\n        return TRUE;\n      }\n      return FALSE;\n    case IDCANCEL:\n      EndDialog(hwnd, 0);\n      return TRUE;\n    default:\n      return onCommand(LOWORD(wParam), HIWORD(wParam));\n    };\n\n  case WM_HELP:\n    return onHelp(((HELPINFO*)lParam)->iCtrlId);\n\n  }\n\n  return FALSE;\n}\n\n\nPropSheetPage::PropSheetPage(HINSTANCE inst_, const char* id) : Dialog(inst_), propSheet(nullptr) {\n  page.dwSize = sizeof(page);\n  page.dwFlags = 0; // PSP_USECALLBACK;\n  page.hInstance = inst;\n  page.pszTemplate = id;\n  page.pfnDlgProc = staticPageProc;\n  page.lParam = (LPARAM)this;\n  page.pfnCallback = nullptr; // staticPageProc;\n}\n\nPropSheetPage::~PropSheetPage() {\n}\n\n\nINT_PTR CALLBACK PropSheetPage::staticPageProc(HWND hwnd, UINT msg,\n\t\t\t\t       WPARAM wParam, LPARAM lParam)\n{\n  if (msg == WM_INITDIALOG)\n    SetWindowLongPtr(hwnd, GWLP_USERDATA, ((PROPSHEETPAGE*)lParam)->lParam);\n\n  LONG_PTR self = GetWindowLongPtr(hwnd, GWLP_USERDATA);\n  if (!self) return FALSE;\n\n  return ((PropSheetPage*)self)->dialogProc(hwnd, msg, wParam, lParam);\n}\n\nBOOL PropSheetPage::dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\n{\n  switch (msg) {\n\n  case WM_INITDIALOG:\n    handle = hwnd;\n    initDialog();\n    return TRUE;\n\n  case WM_NOTIFY:\n    switch (((NMHDR*)lParam)->code) {\n    case PSN_APPLY:\n      onOk();\n      return FALSE;\n    };\n    return FALSE;\n\n  case WM_COMMAND:\n    return onCommand(LOWORD(wParam), HIWORD(wParam));\n\n  case WM_HELP:\n    return onHelp(((HELPINFO*)lParam)->iCtrlId);\n\n  }\n\n  return FALSE;\n}\n\n\nPropSheet::PropSheet(HINSTANCE inst_, const char* title_, std::list<PropSheetPage*> pages_, HICON icon_)\n: icon(icon_), pages(pages_), inst(inst_), title(title_), handle(nullptr), alreadyShowing(0) {\n}\n\nPropSheet::~PropSheet() {\n}\n\n\n// For some reason, DLGTEMPLATEEX isn't defined in the Windows headers - go figure...\nstruct DLGTEMPLATEEX {\n  WORD dlgVer;\n  WORD signature;\n  DWORD helpID;\n  DWORD exStyle;\n  DWORD style;\n  WORD cDlgItems;\n  short x;\n  short y;\n  short cx;\n  short cy;\n};\n\nstatic int CALLBACK removeCtxtHelp(HWND /*hwnd*/, UINT message, LPARAM lParam) {\n  if (message == PSCB_PRECREATE) {\n    // Remove the context-help style, to remove the titlebar ? button\n    // *** Nasty hack to cope with new & old dialog template formats...\n    if (((DLGTEMPLATEEX*)lParam)->signature == 0xffff)\n      ((DLGTEMPLATEEX*)lParam)->style &= ~DS_CONTEXTHELP;\n    else\n      ((LPDLGTEMPLATE)lParam)->style &= ~DS_CONTEXTHELP;\n  }\n  return TRUE;\n}\n\n\nbool PropSheet::showPropSheet(HWND owner_, bool showApply, bool showCtxtHelp, bool capture) {\n  if (alreadyShowing) return false;\n  alreadyShowing = true;\n  int count = pages.size();\n\n  HPROPSHEETPAGE* hpages = new HPROPSHEETPAGE[count];\n  try {\n    // Create the PropertSheet page GDI objects.\n    std::list<PropSheetPage*>::iterator pspi;\n    int i = 0;\n    for (pspi=pages.begin(); pspi!=pages.end(); pspi++) {\n      hpages[i] = CreatePropertySheetPage(&((*pspi)->page));\n      (*pspi)->setPropSheet(this);\n      i++;\n    }\n \n    // Initialise and create the PropertySheet itself\n    PROPSHEETHEADER header;\n    header.dwSize = sizeof(PROPSHEETHEADER); // Requires comctl32.dll 4.71 or greater, ie IE 4 or later\n    header.dwFlags = PSH_MODELESS | (showApply ? 0 : PSH_NOAPPLYNOW) | (showCtxtHelp ? 0 : PSH_USECALLBACK);\n    header.pfnCallback = removeCtxtHelp;\n    header.hwndParent = owner_;\n    header.hInstance = inst;\n    header.pszCaption = title.c_str();\n    header.nPages = count;\n    header.nStartPage = 0;\n    header.phpage = hpages;\n    if (icon) {\n      header.hIcon = icon;\n      header.dwFlags |= PSH_USEHICON;\n    }\n\n    handle = (HWND)PropertySheet(&header);\n    if ((handle == nullptr) || (handle == (HWND)-1))\n      throw core::win32_error(\"PropertySheet failed\", GetLastError());\n    centerWindow(handle, owner_);\n    plog.info(\"Created %p\", handle);\n\n    (void)capture;\n#ifdef _DIALOG_CAPTURE\n    if (capture) {\n      plog.info(\"Capturing \\\"%s\\\"\", title.c_str());\n      char* tmpdir = getenv(\"TEMP\");\n      HDC dc = GetWindowDC(handle);\n      DeviceFrameBuffer fb(dc);\n      int i=0;\n      while (true) {\n        int id = PropSheet_IndexToId(handle, i);\n        if (!id) break;\n        PropSheet_SetCurSelByID(handle, id);\n        MSG msg;\n        while (PeekMessage(&msg, handle, 0, 0, PM_REMOVE)) {\n          if (!PropSheet_IsDialogMessage(handle, &msg))\n            DispatchMessage(&msg);\n        }\n        fb.grabRect(fb.getRect());\n        char title[128];\n        if (!GetWindowText(PropSheet_GetCurrentPageHwnd(handle), title, sizeof(title)))\n          sprintf(title, \"capture%d\", i);\n        for (int j=0; j<strlen(title); j++) {\n          if (title == '/' || title[j] == '\\\\' || title[j] == ':')\n            title[j] = '-';\n        }\n        char filename[256];\n        sprintf(filename, \"%s\\\\%s.bmp\", tmpdir, title);\n        vlog.debug(\"Writing to %s\", filename);\n        saveBMP(filename, &fb);\n        i++;\n      }\n      ReleaseDC(handle, dc);\n    } else {\n#endif\n      try {\n        if (owner_)\n          EnableWindow(owner_, FALSE);\n        // Run the PropertySheet\n        MSG msg;\n        while (GetMessage(&msg, nullptr, 0, 0)) {\n          if (!PropSheet_IsDialogMessage(handle, &msg))\n            DispatchMessage(&msg);\n          if (!PropSheet_GetCurrentPageHwnd(handle))\n            break;\n        }\n        if (owner_)\n          EnableWindow(owner_, TRUE);\n      } catch (...) {\n        if (owner_)\n          EnableWindow(owner_, TRUE);\n        throw;\n      }\n#ifdef _DIALOG_CAPTURE\n    }\n#endif\n\n    plog.info(\"Finished %p\", handle);\n\n    DestroyWindow(handle);\n    handle = nullptr;\n    alreadyShowing = false;\n\n    // Clear up the pages' GDI objects\n    for (pspi=pages.begin(); pspi!=pages.end(); pspi++)\n      (*pspi)->setPropSheet(nullptr);\n    delete [] hpages; hpages = nullptr;\n\n    return true;\n  } catch (std::exception&) {\n    alreadyShowing = false;\n\n    std::list<PropSheetPage*>::iterator pspi;\n    for (pspi=pages.begin(); pspi!=pages.end(); pspi++)\n      (*pspi)->setPropSheet(nullptr);\n    delete [] hpages; hpages = nullptr;\n\n    throw;\n  }\n}\n\nvoid PropSheet::reInitPages() {\n  std::list<PropSheetPage*>::iterator pspi;\n  for (pspi=pages.begin(); pspi!=pages.end(); pspi++) {\n    if ((*pspi)->handle)\n      (*pspi)->initDialog();\n  }\n}\n\nbool PropSheet::commitPages() {\n  bool result = true;\n  std::list<PropSheetPage*>::iterator pspi;\n  for (pspi=pages.begin(); pspi!=pages.end(); pspi++) {\n    if ((*pspi)->handle)\n      result = result && (*pspi)->onOk();\n  }\n  return result;\n}\n\n\nvoid PropSheetPage::setChanged(bool changed) {\n  if (propSheet) {\n    if (changed)\n      PropSheet_Changed(propSheet->handle, handle);\n    else\n      PropSheet_UnChanged(propSheet->handle, handle);\n  }\n}\n"
  },
  {
    "path": "win/rfb_win32/Dialog.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2010 D. R. Commander.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- RegConfig.h\n\n// Class which monitors the registry and reads in the registry settings\n// whenever they change, or are added or removed.\n\n#ifndef __RFB_WIN32_DIALOG_H__\n#define __RFB_WIN32_DIALOG_H__\n\n#include <string>\n\n#include <windows.h>\n#include <prsht.h>\n#include <list>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    // Dialog - A simple Win32 Dialog box.  A derived class of Dialog overrides the\n    // initDialog(), command() and ok() methods to take appropriate action.  A\n    // simple dialog box can be displayed by creating a Dialog object and calling\n    // show().\n\n    class Dialog {\n    public:\n\n      Dialog(HINSTANCE inst);\n      virtual ~Dialog();\n\n      // showDialog() displays the dialog box.  It returns when it has been dismissed,\n      // returning true if \"OK\" was pressed, false otherwise.  The resource\n      // argument identifies the dialog resource (often a MAKEINTRESOURCE macro\n      // expansion), and owner is an optional window handle - the corresponding\n      // window is disabled while the dialog box is displayed.\n\n      bool showDialog(const char* resource, HWND owner=nullptr);\n\n      // initDialog() is called upon receipt of the WM_INITDIALOG message.\n\n      virtual void initDialog() {}\n\n      // onCommand() is called upon receipt of a WM_COMMAND message item other than IDOK\n      // or IDCANCEL.  It should return true if the command has been handled.\n\n      virtual bool onCommand(int /*item*/, int /*cmd*/) { return false; }\n\n      // onHelp() is called upon receipt of a WM_MENU message.  This indicates that\n      // context-specific help should be displayed, for a dialog control, for example.\n      // It should return true if the command has been handled.\n\n      virtual bool onHelp(int /*item*/) { return false; }\n\n      // onOk() is called when the OK button is pressed.  The hwnd argument is the\n      // dialog box's window handle.\n\n      virtual bool onOk() { return true; }\n\n      // Read the states of items\n      bool isItemChecked(int id);\n      int getItemInt(int id);\n      const char *getItemString(int id);\n      \n      // Set the states of items\n      void setItemChecked(int id, bool state);\n      void setItemInt(int id, int value);\n      void setItemString(int id, const char* s);\n\n      // enableItem is used to grey out an item, making it inaccessible, or to\n      // re-enable it.\n      void enableItem(int id, bool state);\n\n    protected:\n      static INT_PTR CALLBACK staticDialogProc(HWND hwnd, UINT msg,\n\t\t\t      WPARAM wParam, LPARAM lParam);\n      virtual BOOL dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);\n      HINSTANCE inst;\n      HWND handle;\n      bool alreadyShowing;\n    };\n\n    // PropertySheetPage \n    // Class used to define property pages within a PropertySheet.\n    // Each page is associated with a particular dialog resource, indicated by\n    // the \"id\" parameter supplied to the constructor.\n\n    class PropSheetPage;\n\n    class PropSheet {\n    public:\n      PropSheet(HINSTANCE inst, const char* title, std::list<PropSheetPage*> pages, HICON icon=nullptr);\n      virtual ~PropSheet();\n\n      // Display the PropertySheet\n      bool showPropSheet(HWND owner, bool showApply = false, bool showCtxtHelp = false, bool capture=false);\n      \n      // Calls initDialog again for each page that has already had it called.\n      // Note: If a page hasn't been seen yet, it won't have been called.\n      // Note: This must only be called while the property sheet is visible.\n      void reInitPages();\n\n      // Calls onOk for each page that has had initDialog called, and returns\n      // false if any one of them returns false, or true otherwise.  ALL the\n      // onOk() methods will be called, even if one of them fails.\n      // Note: If a page hasn't been seen yet, it won't have been called.\n      // Note: This must only be called while the property sheet is visible.\n      bool commitPages();\n\n      friend class PropSheetPage;\n\n    protected:\n      HWND owner;\n      HICON icon;\n      std::list<PropSheetPage*> pages;\n      HINSTANCE inst;\n      std::string title;\n      HWND handle;\n      bool alreadyShowing;\n    };\n\n    class PropSheetPage : public Dialog {\n    public:\n      PropSheetPage(HINSTANCE inst, const char* id);\n      virtual ~PropSheetPage();\n\n      void setChanged(bool changed);\n\n      friend class PropSheet;\n\n    protected:\n      void setPropSheet(PropSheet* ps) {propSheet = ps;};\n      static INT_PTR CALLBACK staticPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);\n      BOOL dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) override;\n      PROPSHEETPAGE page;\n      PropSheet* propSheet;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_DIALOG_H__\n"
  },
  {
    "path": "win/rfb_win32/EventManager.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <windows.h>\n\n#include <stdexcept>\n\n#include <rfb_win32/EventManager.h>\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"EventManager\");\n\n\nEventManager::EventManager() : eventCount(0) {\n}\n\nEventManager::~EventManager() {\n}\n\n\nbool EventManager::addEvent(HANDLE event, EventHandler* ecb) {\n  if (eventCount >= MAXIMUM_WAIT_OBJECTS-1)\n    return false;\n  events[eventCount] = event;\n  handlers[eventCount] = ecb;\n  eventCount++;\n  return true;\n}\n\nvoid EventManager::removeEvent(HANDLE event) {\n  for (unsigned int i=0; i<eventCount; i++) {\n    if (events[i] == event) {\n      for (unsigned int j=i; j<eventCount-1; j++) {\n        events[j] = events[j+1];\n        handlers[j] = handlers[j+1];\n      }\n      eventCount--;\n      return;\n    }\n  }\n  throw std::runtime_error(\"Event not registered\");\n}\n\n\nint EventManager::checkTimeouts() {\n  return -1;\n}\n\nBOOL EventManager::getMessage(MSG* msg, HWND hwnd, UINT minMsg, UINT maxMsg) {\n  while (true) {\n    // - Process any pending timeouts\n    int timeout = checkTimeouts();\n    if (timeout < 0)\n      timeout = INFINITE;\n\n    // - Events take precedence over messages\n    DWORD result;\n    if (eventCount) {\n      // - Check whether any events are set\n      result = WaitForMultipleObjects(eventCount, events, FALSE, 0);\n      if (result == WAIT_TIMEOUT) {\n        // - No events are set, so check for messages\n        if (PeekMessage(msg, hwnd, minMsg, maxMsg, PM_REMOVE)) \n          return msg->message != WM_QUIT;\n\n        // - Block waiting for an event to be set, or a message\n        result = MsgWaitForMultipleObjects(eventCount, events, FALSE, timeout,\n                                           QS_ALLINPUT);\n        if (result == WAIT_OBJECT_0 + eventCount) {\n          // - Return the message, if any\n          if (PeekMessage(msg, hwnd, minMsg, maxMsg, PM_REMOVE)) \n            return msg->message != WM_QUIT;\n          continue;\n        }\n      }\n    } else\n      return GetMessage(msg, hwnd, minMsg, maxMsg);\n\n    if (result < (WAIT_OBJECT_0 + eventCount)) {\n      // - An event was set - call the handler\n      int index = result - WAIT_OBJECT_0;\n      handlers[index]->processEvent(events[index]);\n    } else if (result == WAIT_FAILED) {\n      // - An error has occurred, so return the error status code\n      return -1;\n    }\n  }\n}\n"
  },
  {
    "path": "win/rfb_win32/EventManager.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- EventManager.h\n\n// Win32 event manager.  Caller supplies event & handler pairs and\n// then uses getMessage() in place of ::GetMessage() in the main\n// loop.  EventManager calls the event handler whenever the event\n// is set.\n// Ownership of events remains with the caller.\n// It is the responsibility of handlers to reset events.\n\n#ifndef __RFB_WIN32_EVENT_MGR_H__\n#define __RFB_WIN32_EVENT_MGR_H__\n\n#include <rfb_win32/Win32Util.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    class EventHandler {\n    public:\n      virtual ~EventHandler() {}\n      virtual void processEvent(HANDLE event) = 0;\n    };\n\n    class EventManager {\n    public:\n      EventManager();\n      virtual ~EventManager();\n\n      // Add a Win32 event & handler for it\n      //   NB: The handler must call ResetEvent on the event.\n      //   NB: The caller retains ownership of the event.\n      virtual bool addEvent(HANDLE event, EventHandler* ecb);\n\n      // Remove a Win32 event\n      virtual void removeEvent(HANDLE event);\n\n      // getMessage\n      //   Waits for a message to become available on the thread's message queue,\n      //   and returns it.  If any registered events become set while waiting then\n      //   their handlers are called before returning.\n      //   Returns zero if the message is WM_QUIT, -1 in case of error, >0 otherwise.\n      virtual BOOL getMessage(MSG* msg, HWND hwnd, UINT minMsg, UINT maxMsg);\n\n    protected:\n      // checkTimeouts\n      //   Derived classes should override this to perform any extra processing,\n      //   returning the maximum number of milliseconds after which the callback\n      //   should be called again.\n      virtual int checkTimeouts();\n\n      HANDLE events[MAXIMUM_WAIT_OBJECTS];\n      EventHandler* handlers[MAXIMUM_WAIT_OBJECTS-1];\n      unsigned int eventCount;\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/Handle.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// Wrapper for Win32 HANDLEs that can/must be CloseHandle()d.\n\n#ifndef __RFB_WIN32_HANDLE_H__\n#define __RFB_WIN32_HANDLE_H__\n\n#include <windows.h>\n\nnamespace rfb {\n  namespace win32 {\n\n\n    class Handle {\n    public:\n      Handle(HANDLE h_=nullptr) : h(h_) {}\n      ~Handle() {\n        if (h) CloseHandle(h);\n      }\n      operator HANDLE() {return h;}\n      HANDLE h;\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/IconInfo.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_WIN32_ICONINFO_H__\n#define __RFB_WIN32_ICONINFO_H__\n\n#include <windows.h>\n#include <core/Exception.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    struct IconInfo : public ICONINFO {\n      IconInfo(HICON icon) {\n        if (!GetIconInfo(icon, this))\n          throw core::win32_error(\"GetIconInfo() failed\", GetLastError());\n      }\n      ~IconInfo() {\n        if (hbmColor)\n          DeleteObject(hbmColor);\n        if (hbmMask)\n          DeleteObject(hbmMask);\n      }\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/IntervalTimer.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- IntervalTimer.h\n//\n// Simple wrapper for standard Win32 timers\n\n#ifndef __RFB_WIN32_INTERVAL_TIMER_H__\n#define __RFB_WIN32_INTERVAL_TIMER_H__\n\n#include <core/Exception.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    struct IntervalTimer {\n      IntervalTimer(HWND hwnd_, int id_)\n        : hwnd(hwnd_), id(id_), active(false) {\n      }\n      IntervalTimer() : hwnd(nullptr), id(0), active(false) {\n      }\n      ~IntervalTimer() {\n        stop();\n      }\n\n      void start(int interval_) {\n        if (!active || interval_ != interval) {\n          interval = interval_;\n          if (!SetTimer(hwnd, id, interval, nullptr))\n            throw core::win32_error(\"SetTimer\", GetLastError());\n          active = true;\n        }\n      }\n      void stop() {\n        if (active)\n          KillTimer(hwnd, id);\n        active = false;\n      }\n\n      void setHWND(HWND hwnd_) {hwnd=hwnd_;}\n      void setId(int id_) {id = id_;}\n      int getId() const {return id;}\n      bool isActive() const {return active;}\n\n    private:\n      HWND hwnd;\n      int id;\n      bool active;\n      int interval;\n    };\n\n  }; // win32\n\n}; // rfb\n\n#endif // __RFB_WIN32_INTERVAL_TIMER_H__\n"
  },
  {
    "path": "win/rfb_win32/LaunchProcess.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- LaunchProcess.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n\n#include <rfb_win32/LaunchProcess.h>\n#include <rfb_win32/ModuleFileName.h>\n#include <rfb_win32/Win32Util.h>\n\n#include <stdio.h>\n\nusing namespace rfb;\nusing namespace win32;\n\n\nLaunchProcess::LaunchProcess(const char* exeName_, const char* params_)\n: exeName(exeName_), params(params_) {\n  memset(&procInfo, 0, sizeof(procInfo));\n}\n\nLaunchProcess::~LaunchProcess() {\n  await();\n}\n\n\nvoid LaunchProcess::start(HANDLE userToken, bool createConsole) {\n  if (procInfo.hProcess && (WaitForSingleObject(procInfo.hProcess, 0) != WAIT_OBJECT_0))\n    return;\n  await();\n  returnCode = STILL_ACTIVE;\n\n  DWORD size;\n  char desktopName[256];\n  char buf[256];\n  HDESK desktop = GetThreadDesktop(GetCurrentThreadId());\n  if (!GetUserObjectInformation(desktop, UOI_NAME, buf, 256, &size))\n    throw core::win32_error(\"Unable to launch process\", GetLastError());\n\n  snprintf(desktopName, 256, \"WinSta0\\\\%s\", buf);\n\n  // - Create storage for the process startup information\n  STARTUPINFO sinfo;\n  memset(&sinfo, 0, sizeof(sinfo));\n  sinfo.cb = sizeof(sinfo);\n  sinfo.lpDesktop = desktopName;\n\n  // - Concoct a suitable command-line\n  std::string exePath;\n  if (exeName.find('\\\\') == std::string::npos) {\n    ModuleFileName filename;\n    std::string path(filename.buf);\n    if (path.rfind('\\\\') != std::string::npos)\n      path.resize(path.rfind('\\\\'));\n    exePath = path + '\\\\' + exeName;\n  } else {\n    exePath = exeName;\n  }\n\n  // - Start the process\n  // Note: We specify the exe's precise path in the ApplicationName parameter,\n  //       AND include the name as the first part of the CommandLine parameter,\n  //       because CreateProcess doesn't make ApplicationName argv[0] in C programs.\n  std::string cmdLine;\n  cmdLine = (std::string)\"\\\"\" + exeName + \"\\\" \" + params;\n  DWORD flags = createConsole ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW;\n  BOOL success;\n  if (userToken != INVALID_HANDLE_VALUE)\n    success = CreateProcessAsUser(userToken, exePath.c_str(),\n                                  (char*)cmdLine.c_str(),\n                                  nullptr, nullptr, FALSE,\n                                  flags, nullptr, nullptr,\n                                  &sinfo, &procInfo);\n  else\n    success = CreateProcess(exePath.c_str(), (char*)cmdLine.c_str(),\n                            nullptr, nullptr, FALSE,\n                            flags, nullptr, nullptr,\n                            &sinfo, &procInfo);\n  if (!success)\n    throw core::win32_error(\"Unable to launch process\", GetLastError());\n\n  // Wait for it to finish initialising\n  WaitForInputIdle(procInfo.hProcess, 15000);\n}\n\nvoid LaunchProcess::detach()\n{\n  if (!procInfo.hProcess)\n    return;\n  CloseHandle(procInfo.hProcess);\n  CloseHandle(procInfo.hThread);\n  memset(&procInfo, 0, sizeof(procInfo));\n}\n\nbool LaunchProcess::await(DWORD timeoutMs) {\n  if (!procInfo.hProcess)\n    return true;\n  DWORD result = WaitForSingleObject(procInfo.hProcess, timeoutMs);\n  if (result == WAIT_OBJECT_0) {\n    GetExitCodeProcess(procInfo.hProcess, &returnCode);\n    detach();\n    return true;\n  } else if (result == WAIT_FAILED) {\n    throw core::win32_error(\"await() failed\", GetLastError());\n  }\n  return false;\n}\n"
  },
  {
    "path": "win/rfb_win32/LaunchProcess.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- LaunchProcess.h\n\n// Helper class to launch a names process from the same directory as\n// the current process executable resides in.\n\n#ifndef __RFB_WIN32_LAUNCHPROCESS_H__\n#define __RFB_WIN32_LAUNCHPROCESS_H__\n\n#include <string>\n\n#include <windows.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class LaunchProcess {\n    public:\n      LaunchProcess(const char* exeName_, const char* params);\n      ~LaunchProcess();\n\n      // start() starts the specified process with the supplied\n      //   command-line.\n      //   If userToken is INVALID_HANDLE_VALUE then starts the process\n      //   as the current user, otherwise as the specified user.\n      //   If createConsole is true then CREATE_CONSOLE_WINDOW is passed\n      //   as an extra flag to the process creation call.\n      void start(HANDLE userToken, bool createConsole=false);\n\n      // Detach from the child process. After detaching from a child\n      //   process, no other methods should be called on the object\n      //   that started it\n      void detach();\n\n      // Wait for the process to quit, up to the specified timeout, and\n      //   close the handles to it once it has quit.\n      //   If the process quits within the timeout then true is returned\n      //   and returnCode is set. If it has not quit then false is returned.\n      //   If an error occurs then an exception will be thrown.\n      bool await(DWORD timeoutMs=INFINITE);\n\n      PROCESS_INFORMATION procInfo;\n      DWORD returnCode;\n    protected:\n      std::string exeName;\n      std::string params;\n    };\n\n\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/ListViewControl.cxx",
    "content": "// ListViewControl.cxx: implementation of the ListViewControl class.\n//\n//////////////////////////////////////////////////////////////////////\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n#include \"ListViewControl.h\"\n#include \"commctrl.h\"\n//////////////////////////////////////////////////////////////////////\n// Construction/Destruction\n//////////////////////////////////////////////////////////////////////\nusing namespace rfb;\nusing namespace rfb::win32;\n\nListViewControl::ListViewControl()\n{\n}\n\nbool ListViewControl::IsSelectedLVItem(DWORD idListView,\n                                      HWND hDlg, int numberItem)\n{\t\n  return (ListView_GetItemState(GetDlgItem(hDlg, idListView),\n    numberItem, LVIS_SELECTED) == LVIS_SELECTED);\n}\n\nvoid ListViewControl::SelectLVItem(DWORD idListView, HWND hDlg, int numberItem)\n{\n  ListView_SetItemState(GetDlgItem(hDlg, idListView),\n    numberItem, LVIS_SELECTED, LVIS_SELECTED);\n}\n\nBOOL ListViewControl::InitLVColumns(DWORD idListView, HWND hDlg, int width, int columns,\n                                    char *title[], DWORD mask, DWORD LVStyle, DWORD format)\n{\n  (void)ListView_SetExtendedListViewStyle(GetDlgItem(hDlg, idListView), LVStyle);\n  char szText[256];      \n  LVCOLUMN lvc; \n  int iCol;\n  \n  lvc.mask = mask; \n  \n  for (iCol = 0; iCol < columns; iCol++) { \n    lvc.iSubItem = iCol;\n    lvc.pszText = szText;\t\n    lvc.cx = width;           \n    lvc.fmt = format;\n    \n    strcpy(szText, title[iCol]);\n    if (ListView_InsertColumn(GetDlgItem(hDlg, idListView), iCol, &lvc) == -1) \n      return FALSE; \n  } \n  return TRUE; \n}\n\nBOOL ListViewControl::InsertLVItem(DWORD idListView, HWND hDlg, int number,  char * texts[],\n                                   int columns)\n{\n  int i;\n  LVITEM lvI;\n  lvI.mask = LVIF_TEXT| LVIF_STATE; \n  lvI.state = 0; \n  lvI.stateMask = 0; \n  lvI.iItem = number; \n  lvI.iSubItem = 0; \n  lvI.pszText = texts[0]; \t\t\t\t\t\t\t\t\t  \n  \n  if(ListView_InsertItem(GetDlgItem(hDlg, idListView), &lvI) == -1)\n    return FALSE;\n  \n  for (i =1; i < columns; i++) {\t\n    SetLVItemText(\n      idListView, hDlg, \n      number, i, texts[i]);\n  }\n  return TRUE;\n}\n\nvoid ListViewControl::SetLVItemText(DWORD idListView, HWND hDlg, int numberItem,\n                                    int namberColumn, char * text)\n{\n  ListView_SetItemText(\n    GetDlgItem(hDlg, idListView), \n    numberItem, namberColumn, text);\n}\n\nvoid ListViewControl::GetLVItemText(DWORD idListView, HWND hDlg, int numberItem,\n                                    int namberColumn, char * text)\n{\n\t ListView_GetItemText(GetDlgItem(hDlg, idListView), numberItem,\n\t\t\t\t\t\t\tnamberColumn, text, 256);\n}\n\nvoid ListViewControl::DeleteLVItem(DWORD idListView, HWND hDlg, int number)\n{\n  (void)ListView_DeleteItem(GetDlgItem(hDlg, idListView), number);\n}\n\nvoid ListViewControl::DeleteAllLVItem(DWORD idListView, HWND hDlg)\n{\n  (void)ListView_DeleteAllItems(GetDlgItem(hDlg, idListView));\n}\n\nListViewControl::~ListViewControl()\n{\n}\n"
  },
  {
    "path": "win/rfb_win32/ListViewControl.h",
    "content": "// ListViewControl.h: interface for the ListViewControl class.\n//\n//////////////////////////////////////////////////////////////////////\n\n#ifndef AFX_LISTVIEWCONTROL_H__\n#define AFX_LISTVIEWCONTROL_H__\n\n#include <windows.h>\n#include \"commctrl.h\"\n\nnamespace rfb {\n  \n  namespace win32 {\n    class ListViewControl  \n    {\n    public:\n      ListViewControl();\n      bool IsSelectedLVItem(DWORD idListView, HWND hDlg, int numberItem);\n      void SelectLVItem(DWORD idListView, HWND hDlg, int numberItem);\n      BOOL InitLVColumns(DWORD idListView, HWND hDlg, int width, int columns,\n        char * title[], DWORD mask, DWORD style, DWORD format);\n      BOOL InsertLVItem(DWORD idListView, HWND hDlg, int number,  char * texts[],\n        int columns);\n      void SetLVItemText(DWORD idListView, HWND hDlg, int numberItem,\n        int namberColumn, char * text);\n      void GetLVItemText(DWORD idListView, HWND hDlg, int numberItem,\n        int namberColumn, char * text);\n      void DeleteLVItem(DWORD idListView, HWND hDlg, int number);\n      void DeleteAllLVItem(DWORD idListView, HWND hDlg);\n      virtual ~ListViewControl();\t\n    };\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/LocalMem.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_WIN32_LOCALMEM_H__\n#define __RFB_WIN32_LOCALMEM_H__\n\n#include <windows.h>\n#include <core/Exception.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    // Allocate and/or manage LocalAlloc memory.\n    struct LocalMem {\n      LocalMem(int size) : ptr(LocalAlloc(LMEM_FIXED, size)) {\n        if (!ptr) throw core::win32_error(\"LocalAlloc\", GetLastError());\n      }\n      LocalMem(void* p) : ptr(p) {}\n      ~LocalMem() {LocalFree(ptr);}\n      operator void*() {return ptr;}\n      void* takePtr() {\n        void* t = ptr; ptr = nullptr; return t;\n      }\n      void* ptr;\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/ModuleFileName.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_WIN32_MODULE_FILENAME_H__\n#define __RFB_WIN32_MODULE_FILENAME_H__\n\n#include <windows.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    struct ModuleFileName {\n      ModuleFileName(HMODULE module=nullptr) {\n        if (!module)\n          module = GetModuleHandle(nullptr);\n        if (!GetModuleFileName(module, buf, MAX_PATH))\n          buf[0] = 0;\n      }\n      char buf[MAX_PATH];\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/MonitorInfo.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/MonitorInfo.h>\n#include <rfb_win32/Win32Util.h>\n\n#ifndef min\n #define min(a,b) ((a)<(b)?(a):(b))\n#endif\n\n#ifndef max\n #define max(a,b) ((a)>(b)?(a):(b))\n#endif\n\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\n\nstatic LogWriter vlog(\"MonitorInfo\");\n\n\nstatic void fillMonitorInfo(HMONITOR monitor, MONITORINFOEXA* mi) {\n  vlog.debug(\"monitor=%p\", monitor);\n  memset(mi, 0, sizeof(MONITORINFOEXA));\n  mi->cbSize = sizeof(MONITORINFOEXA);\n  if (!GetMonitorInfo(monitor, mi))\n    throw core::win32_error(\"Failed to GetMonitorInfo\", GetLastError());\n  vlog.debug(\"Monitor is %ld,%ld-%ld,%ld\", mi->rcMonitor.left, mi->rcMonitor.top, mi->rcMonitor.right, mi->rcMonitor.bottom);\n  vlog.debug(\"Work area is %ld,%ld-%ld,%ld\", mi->rcWork.left, mi->rcWork.top, mi->rcWork.right, mi->rcWork.bottom);\n  vlog.debug(\"Device is \\\"%s\\\"\", mi->szDevice);\n}\n\n\nMonitorInfo::MonitorInfo(HWND window) {\n  cbSize = sizeof(MonitorInfo);\n  szDevice[0] = 0;\n\n  HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);\n  if (!monitor)\n    throw core::win32_error(\"Failed to get monitor\", GetLastError());\n  fillMonitorInfo(monitor, this);\n}\n\nMonitorInfo::MonitorInfo(const RECT& r) {\n  cbSize = sizeof(MonitorInfo);\n  szDevice[0] = 0;\n\n  HMONITOR monitor = MonitorFromRect(&r, MONITOR_DEFAULTTONEAREST);\n  if (!monitor)\n    throw core::win32_error(\"Failed to get monitor\", GetLastError());\n  fillMonitorInfo(monitor, this);\n}\n\n\nstruct monitorByNameData {\n  MONITORINFOEXA* info;\n  const char* monitorName;\n};\n\nstatic BOOL CALLBACK monitorByNameEnumProc(HMONITOR monitor,\n                                    HDC /*dc*/,\n                                    LPRECT /*pos*/,\n                                    LPARAM d) {\n  monitorByNameData* data = (monitorByNameData*)d;\n  memset(data->info, 0, sizeof(MONITORINFOEXA));\n  data->info->cbSize = sizeof(MONITORINFOEXA);\n  if (GetMonitorInfo(monitor, data->info)) {\n    if (stricmp(data->monitorName, data->info->szDevice) == 0)\n      return FALSE;\n  }\n\n  return TRUE;\n}\n\nMonitorInfo::MonitorInfo(const char* devName) {\n  monitorByNameData data;\n  data.info = this;\n  data.monitorName = devName;\n  EnumDisplayMonitors(nullptr, nullptr, &monitorByNameEnumProc, (LPARAM)&data);\n}\n\nvoid MonitorInfo::moveTo(HWND handle) {\n  vlog.debug(\"moveTo monitor=%s\", szDevice);\n\n  MonitorInfo mi(handle);\n  if (strcmp(szDevice, mi.szDevice) != 0) {\n    centerWindow(handle, rcWork);\n    clipTo(handle);\n  }\n}\n\nvoid MonitorInfo::clipTo(RECT* r) {\n  vlog.debug(\"clipTo monitor=%s\", szDevice);\n\n  if (r->top < rcWork.top) {\n    r->bottom += rcWork.top - r->top; r->top = rcWork.top;\n  }\n  if (r->left < rcWork.left) {\n    r->right += rcWork.left - r->left; r->left = rcWork.left;\n  }\n  if (r->bottom > rcWork.bottom) {\n    r->top += rcWork.bottom - r->bottom; r->bottom = rcWork.bottom;\n  }\n  if (r->right > rcWork.right) {\n    r->left += rcWork.right - r->right; r->right = rcWork.right;\n  }\n  r->left = max(r->left, rcWork.left);\n  r->right = min(r->right, rcWork.right);\n  r->top = max(r->top, rcWork.top);\n  r->bottom = min(r->bottom, rcWork.bottom);\n}\n\nvoid MonitorInfo::clipTo(HWND handle) {\n  RECT r;\n  GetWindowRect(handle, &r);\n  clipTo(&r);\n  SetWindowPos(handle, nullptr, r.left, r.top, r.right-r.left, r.bottom-r.top,\n               SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER);\n}\n\n\n"
  },
  {
    "path": "win/rfb_win32/MonitorInfo.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// Helper class used to obtain information about a particular monitor.\n\n\n#ifndef __RFB_WIN32_MONITORINFO_H__\n#define __RFB_WIN32_MONITORINFO_H__\n\n#include <windows.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    // Structure containing info on the monitor nearest the window.\n    struct MonitorInfo : MONITORINFOEXA {\n      // Constructor: Obtains monitor info for the monitor that has the\n      //   greatest overlap with the supplied window or rectangle.\n      MonitorInfo(HWND hwnd);\n      MonitorInfo(const RECT& r);\n\n      // Constructor: Obtains monitor info for the name monitor.  Monitor\n      //   names should be those obtained from the MonitorInfo\n      //   szDevice field, and usually look like \"\\\\.\\DISPLAY<n>\"\n      MonitorInfo(const char* devName);\n\n      // Move the specified window to reside on the monitor.\n      void moveTo(HWND handle);\n\n      // Clip the specified rectangle or window to the monitor's working area.\n      //   The rectangle/window is moved so that as much as possible resides\n      //   on the working area of the monitor, and is then intersected with it.\n      void clipTo(HWND handle);\n      void clipTo(RECT* r);\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/MsgBox.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_WIN32_MSGBOX_H__\n#define __RFB_WIN32_MSGBOX_H__\n\n#include <string>\n\n#include <windows.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    // Define rfb::win32::AppName somewhere in the application.\n    // The MsgBox function will use the specified application name\n    // as the prefix for the message box title.\n    // Message box titles are based on the (standard Win32) flags\n    // passed to the MsgBox helper function.\n\n    extern const char* AppName;\n\n    // Wrapper around Win32 MessageBox()\n    static int MsgBox(HWND parent, const char* msg, UINT flags) {\n      const char* msgType = nullptr;\n      UINT tflags = flags & 0x70;\n      if (tflags == MB_ICONHAND)\n        msgType = \"Error\";\n      else if (tflags == MB_ICONQUESTION)\n        msgType = \"Question\";\n      else if (tflags == MB_ICONEXCLAMATION)\n        msgType = \"Warning\";\n      else if (tflags == MB_ICONASTERISK)\n        msgType = \"Information\";\n      flags |= MB_TOPMOST | MB_SETFOREGROUND;\n      std::string title = AppName;\n      if (msgType) {\n        title += \" : \";\n        title += msgType;\n      }\n      return MessageBox(parent, msg, title.c_str(), flags);\n    }\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/MsgWindow.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2010 D. R. Commander.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- MsgWindow.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/MsgWindow.h>\n#include <rfb_win32/WMShatter.h>\n\n#include <malloc.h>\n\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic core::LogWriter vlog(\"MsgWindow\");\n\n//\n// -=- MsgWindowClass\n//\n\nclass MsgWindowClass {\npublic:\n  MsgWindowClass();\n  ~MsgWindowClass();\n  ATOM classAtom;\n  HINSTANCE instance;\n};\n\nLRESULT CALLBACK MsgWindowProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) {\n  LRESULT result = 0;\n\n  if (msg == WM_CREATE)\n    SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)((CREATESTRUCT*)lParam)->lpCreateParams);\n  else if (msg == WM_DESTROY)\n    SetWindowLongPtr(wnd, GWLP_USERDATA, 0);\n  MsgWindow* _this = (MsgWindow*) GetWindowLongPtr(wnd, GWLP_USERDATA);\n  if (!_this) {\n    vlog.info(\"Null _this in %p, message %x\", wnd, msg);\n    return SafeDefWindowProc(wnd, msg, wParam, lParam);\n  }\n\n  try {\n    result = _this->processMessage(msg, wParam, lParam);\n  } catch (std::exception& e) {\n    vlog.error(\"Untrapped: %s\", e.what());\n  }\n\n  return result;\n};\n\nMsgWindowClass::MsgWindowClass() : classAtom(0) {\n  WNDCLASS wndClass;\n  wndClass.style = 0;\n  wndClass.lpfnWndProc = MsgWindowProc;\n  wndClass.cbClsExtra = 0;\n  wndClass.cbWndExtra = 0;\n  wndClass.hInstance = instance = GetModuleHandle(nullptr);\n  wndClass.hIcon = nullptr;\n  wndClass.hCursor = nullptr;\n  wndClass.hbrBackground = nullptr;\n  wndClass.lpszMenuName = nullptr;\n  wndClass.lpszClassName = \"rfb::win32::MsgWindowClass\";\n  classAtom = RegisterClass(&wndClass);\n  if (!classAtom) {\n    throw core::win32_error(\"Unable to register MsgWindow window class\", GetLastError());\n  }\n}\n\nMsgWindowClass::~MsgWindowClass() {\n  if (classAtom) {\n    UnregisterClass((const char*)(intptr_t)classAtom, instance);\n  }\n}\n\nstatic MsgWindowClass baseClass;\n\n//\n// -=- MsgWindow\n//\n\nMsgWindow::MsgWindow(const char* name_) : name(name_), handle(nullptr) {\n  vlog.debug(\"Creating window \\\"%s\\\"\", name.c_str());\n  handle = CreateWindow((const char*)(intptr_t)baseClass.classAtom,\n                        name.c_str(), WS_OVERLAPPED, 0, 0, 10, 10,\n                        nullptr, nullptr, baseClass.instance, this);\n  if (!handle) {\n    throw core::win32_error(\"Unable to create WMNotifier window instance\", GetLastError());\n  }\n  vlog.debug(\"Created window \\\"%s\\\" (%p)\", name.c_str(), handle);\n}\n\nMsgWindow::~MsgWindow() {\n  if (handle)\n    DestroyWindow(handle);\n  vlog.debug(\"Destroyed window \\\"%s\\\" (%p)\", name.c_str(), handle);\n}\n\nLRESULT\nMsgWindow::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {\n  return SafeDefWindowProc(getHandle(), msg, wParam, lParam);\n}\n"
  },
  {
    "path": "win/rfb_win32/MsgWindow.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- MsgWindow.h\n\n// Base-class for any hidden message-handling windows used in the rfb::win32\n// implementation.\n\n#ifndef __RFB_WIN32_MSG_WINDOW_H__\n#define __RFB_WIN32_MSG_WINDOW_H__\n\n#include <string>\n\n#include <windows.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class MsgWindow {\n    public:\n      MsgWindow(const char* _name);\n      virtual ~MsgWindow();\n\n      const char* getName() {return name.c_str();}\n      HWND getHandle() const {return handle;}\n\n      virtual LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam);\n\n    protected:\n      std::string name;\n      HWND handle;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_MSG_WINDOW_H__\n"
  },
  {
    "path": "win/rfb_win32/RegConfig.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- RegConfig.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <malloc.h>\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/RegConfig.h>\n\n//#include <rdr/HexOutStream.h>\n\nusing namespace rfb;\nusing namespace rfb::win32;\n\n\nstatic core::LogWriter vlog(\"RegConfig\");\n\n\nRegConfig::RegConfig(EventManager* em)\n  : eventMgr(em), event(CreateEvent(nullptr, TRUE, FALSE, nullptr)),\n    callback(nullptr)\n{\n  if (em->addEvent(event, this))\n    eventMgr = em;\n}\n\nRegConfig::~RegConfig() {\n  if (eventMgr)\n    eventMgr->removeEvent(event);\n}\n\nbool RegConfig::setKey(const HKEY rootkey, const char* keyname) {\n  try {\n    key.createKey(rootkey, keyname);\n    processEvent(event);\n    return true;\n  } catch (std::exception& e) {\n    vlog.debug(\"%s\", e.what());\n    return false;\n  }\n}\n\nvoid RegConfig::loadRegistryConfig(RegKey& key) {\n  DWORD i = 0;\n  try {\n    while (1) {\n      const char *name = key.getValueName(i++);\n      if (!name) break;\n      std::string value = key.getRepresentation(name);\n      if (!core::Configuration::setParam(name, value.c_str()))\n        vlog.info(\"Unable to process %s\", name);\n    }\n  } catch (core::win32_error& e) {\n    if (e.err != ERROR_INVALID_HANDLE)\n      vlog.error(\"%s\", e.what());\n  }\n}\n\nvoid RegConfig::processEvent(HANDLE /*event*/) {\n  vlog.info(\"Registry changed\");\n\n  // Reinstate the registry change notifications\n  ResetEvent(event);\n  key.awaitChange(true, REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET, event);\n\n  // Load settings\n  loadRegistryConfig(key);\n\n  // Notify the callback, if supplied\n  if (callback)\n    callback->regConfigChanged();\n}\n\n\nRegConfigThread::RegConfigThread() : config(&eventMgr), thread(nullptr),\n                                     thread_id(-1) {\n}\n\nRegConfigThread::~RegConfigThread() {\n  PostThreadMessage(thread_id, WM_QUIT, 0, 0);\n  if (thread != nullptr) {\n    thread->join();\n    delete thread;\n  }\n}\n\nbool RegConfigThread::start(const HKEY rootKey, const char* keyname) {\n  if (config.setKey(rootKey, keyname)) {\n    thread = new std::thread(&RegConfigThread::worker, this);\n    while (thread_id == (DWORD)-1)\n      Sleep(0);\n    return true;\n  }\n  return false;\n}\n\nvoid RegConfigThread::worker() {\n  BOOL result = 0;\n  MSG msg;\n  thread_id = GetCurrentThreadId();\n  while ((result = eventMgr.getMessage(&msg, nullptr, 0, 0)) > 0) {}\n  if (result < 0)\n    throw core::win32_error(\"RegConfigThread failed\", GetLastError());\n}\n"
  },
  {
    "path": "win/rfb_win32/RegConfig.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- RegConfig.h\n\n// Class which monitors the registry and reads in the registry settings\n// whenever they change, or are added or removed.\n\n#ifndef __RFB_WIN32_REG_CONFIG_H__\n#define __RFB_WIN32_REG_CONFIG_H__\n\n#include <thread>\n\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/EventManager.h>\n#include <rfb_win32/Handle.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class RegConfig : EventHandler {\n    public:\n      RegConfig(EventManager* em);\n      ~RegConfig();\n\n      // Specify the registry key to read Configuration items from\n      bool setKey(const HKEY rootkey, const char* keyname);\n\n      // Support for a callback, run in the RegConfig host thread whenever\n      // the registry configuration changes\n      class Callback {\n      public:\n        virtual ~Callback() {}\n        virtual void regConfigChanged() = 0;\n      };\n      void setCallback(Callback* cb) { callback = cb; }\n\n      // Read entries from the specified key into the Configuration\n      static void loadRegistryConfig(RegKey& key);\n    protected:\n      // EventHandler interface and trigger event\n      void processEvent(HANDLE event) override;\n\n      EventManager* eventMgr;\n      Handle event;\n      Callback* callback;\n      RegKey key;\n    };\n\n    class RegConfigThread {\n    public:\n      RegConfigThread();\n      ~RegConfigThread();\n\n      // Start the thread, reading from the specified key\n      bool start(const HKEY rootkey, const char* keyname);\n    protected:\n      void worker();\n      EventManager eventMgr;\n      RegConfig config;\n      std::thread* thread;\n      DWORD thread_id;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_REG_CONFIG_H__\n"
  },
  {
    "path": "win/rfb_win32/Registry.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Registry.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/Security.h>\n\n#include <rdr/MemOutStream.h>\n#include <rdr/HexOutStream.h>\n#include <rdr/HexInStream.h>\n\n#include <stdlib.h>\n\n// These flags are required to control access control inheritance,\n// but are not defined by VC6's headers.  These definitions comes\n// from the Microsoft Platform SDK.\n#ifndef PROTECTED_DACL_SECURITY_INFORMATION\n#define PROTECTED_DACL_SECURITY_INFORMATION     (0x80000000L)\n#endif\n#ifndef UNPROTECTED_DACL_SECURITY_INFORMATION\n#define UNPROTECTED_DACL_SECURITY_INFORMATION     (0x20000000L)\n#endif\n\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\n\nstatic LogWriter vlog(\"Registry\");\n\n\nRegKey::RegKey() : key(nullptr), freeKey(false), valueName(nullptr), valueNameBufLen(0) {}\n\nRegKey::RegKey(const HKEY k) : key(nullptr), freeKey(false), valueName(nullptr), valueNameBufLen(0) {\n  LONG result = RegOpenKeyEx(k, nullptr, 0, KEY_ALL_ACCESS, &key);\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"RegOpenKeyEx(HKEY)\", result);\n  vlog.debug(\"Duplicated %p to %p\", k, key);\n  freeKey = true;\n}\n\nRegKey::RegKey(const RegKey& k) : key(nullptr), freeKey(false), valueName(nullptr), valueNameBufLen(0) {\n  LONG result = RegOpenKeyEx(k.key, nullptr, 0, KEY_ALL_ACCESS, &key);\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"RegOpenKeyEx(RegKey&)\", result);\n  vlog.debug(\"Duplicated %p to %p\", k.key, key);\n  freeKey = true;\n}\n\nRegKey::~RegKey() {\n  close();\n  delete [] valueName;\n}\n\n\nvoid RegKey::setHKEY(HKEY k, bool fK) {\n  vlog.debug(\"setHKEY(%p,%d)\", k, (int)fK);\n  close();\n  freeKey = fK;\n  key = k;\n}\n\n\nbool RegKey::createKey(const RegKey& root, const char* name) {\n  close();\n  LONG result = RegCreateKey(root.key, name, &key);\n  if (result != ERROR_SUCCESS) {\n    vlog.error(\"RegCreateKey(%p, %s): %lx\", root.key, name, result);\n    throw core::win32_error(\"RegCreateKeyEx\", result);\n  }\n  vlog.debug(\"createKey(%p,%s) = %p\", root.key, name, key);\n  freeKey = true;\n  return true;\n}\n\nvoid RegKey::openKey(const RegKey& root, const char* name, bool readOnly) {\n  close();\n  LONG result = RegOpenKeyEx(root.key, name, 0, readOnly ? KEY_READ : KEY_ALL_ACCESS, &key);\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"RegOpenKeyEx (open)\", result);\n  vlog.debug(\"openKey(%p,%s,%s) = %p\", root.key, name,\n\t         readOnly ? \"ro\" : \"rw\", key);\n  freeKey = true;\n}\n\nvoid RegKey::setDACL(const PACL acl, bool inherit) {\n  DWORD result;\n  if ((result = SetSecurityInfo(key, SE_REGISTRY_KEY,\n    DACL_SECURITY_INFORMATION |\n    (inherit ? UNPROTECTED_DACL_SECURITY_INFORMATION : PROTECTED_DACL_SECURITY_INFORMATION),\n    nullptr, nullptr, acl, nullptr)) != ERROR_SUCCESS)\n    throw core::win32_error(\"RegKey::setDACL failed\", result);\n}\n\nvoid RegKey::close() {\n  if (freeKey) {\n    vlog.debug(\"RegCloseKey(%p)\", key);\n    RegCloseKey(key);\n    key = nullptr;\n  }\n}\n\nvoid RegKey::deleteKey(const char* name) const {\n  LONG result = RegDeleteKey(key, name);\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"RegDeleteKey\", result);\n}\n\nvoid RegKey::deleteValue(const char* name) const {\n  LONG result = RegDeleteValue(key, name);\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"RegDeleteValue\", result);\n}\n\nvoid RegKey::awaitChange(bool watchSubTree, DWORD filter, HANDLE event) const {\n  LONG result = RegNotifyChangeKeyValue(key, watchSubTree, filter, event, event != nullptr);\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"RegNotifyChangeKeyValue\", result);\n}\n\n\nRegKey::operator HKEY() const {return key;}\n\n\nvoid RegKey::setExpandString(const char* valname, const char* value) const {\n  LONG result = RegSetValueEx(key, valname, 0, REG_EXPAND_SZ, (const BYTE*)value, (strlen(value)+1)*sizeof(char));\n  if (result != ERROR_SUCCESS) throw core::win32_error(\"setExpandString\", result);\n}\n\nvoid RegKey::setString(const char* valname, const char* value) const {\n  LONG result = RegSetValueEx(key, valname, 0, REG_SZ, (const BYTE*)value, (strlen(value)+1)*sizeof(char));\n  if (result != ERROR_SUCCESS) throw core::win32_error(\"setString\", result);\n}\n\nvoid RegKey::setBinary(const char* valname, const void* value, size_t length) const {\n  LONG result = RegSetValueEx(key, valname, 0, REG_BINARY, (const BYTE*)value, length);\n  if (result != ERROR_SUCCESS) throw core::win32_error(\"setBinary\", result);\n}\n\nvoid RegKey::setInt(const char* valname, int value) const {\n  LONG result = RegSetValueEx(key, valname, 0, REG_DWORD, (const BYTE*)&value, sizeof(value));\n  if (result != ERROR_SUCCESS) throw core::win32_error(\"setInt\", result);\n}\n\nvoid RegKey::setBool(const char* valname, bool value) const {\n  setInt(valname, value ? 1 : 0);\n}\n\nstd::string RegKey::getString(const char* valname) const {\n  return getRepresentation(valname);\n}\n\nstd::string RegKey::getString(const char* valname, const char* def) const {\n  try {\n    return getString(valname);\n  } catch(std::exception&) {\n    return def;\n  }\n}\n\nstd::vector<uint8_t> RegKey::getBinary(const char* valname) const {\n  std::string hex = getRepresentation(valname);\n  return hexToBin(hex.data(), hex.size());\n}\nstd::vector<uint8_t> RegKey::getBinary(const char* valname, const uint8_t* def, size_t deflen) const {\n  try {\n    return getBinary(valname);\n  } catch(std::exception&) {\n    std::vector<uint8_t> out(deflen);\n    memcpy(out.data(), def, deflen);\n    return out;\n  }\n}\n\nint RegKey::getInt(const char* valname) const {\n  return atoi(getRepresentation(valname).c_str());\n}\nint RegKey::getInt(const char* valname, int def) const {\n  try {\n    return getInt(valname);\n  } catch(std::exception&) {\n    return def;\n  }\n}\n\nbool RegKey::getBool(const char* valname) const {\n  return getInt(valname) > 0;\n}\nbool RegKey::getBool(const char* valname, bool def) const {\n  return getInt(valname, def ? 1 : 0) > 0;\n}\n\nstd::string RegKey::getRepresentation(const char* valname) const {\n  DWORD type, length;\n  LONG result = RegQueryValueEx(key, valname, nullptr, &type, nullptr, &length);\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"Get registry value length\", result);\n  std::vector<uint8_t> data(length);\n  result = RegQueryValueEx(key, valname, nullptr, &type, (BYTE*)data.data(), &length);\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"Get registry value\", result);\n\n  switch (type) {\n  case REG_BINARY:\n    {\n      return binToHex(data.data(), length);\n    }\n  case REG_SZ:\n    if (length) {\n      return std::string((char*)data.data(), length);\n    } else {\n      return \"\";\n    }\n  case REG_DWORD:\n    {\n      char tmp[16];\n      sprintf(tmp, \"%lu\", *((DWORD*)data.data()));\n      return tmp;\n    }\n  case REG_EXPAND_SZ:\n    {\n    if (length) {\n      std::string str((char*)data.data(), length);\n      DWORD required = ExpandEnvironmentStrings(str.c_str(), nullptr, 0);\n      if (required==0)\n        throw core::win32_error(\"ExpandEnvironmentStrings\", GetLastError());\n      std::vector<char> expanded(required);\n      length = ExpandEnvironmentStrings(str.c_str(), expanded.data(), required);\n      if (required<length)\n        throw std::runtime_error(\"Unable to expand environment strings\");\n      return expanded.data();\n    } else {\n      return \"\";\n    }\n    }\n  default:\n    throw std::logic_error(\"Unsupported registry type\");\n  }\n}\n\nbool RegKey::isValue(const char* valname) const {\n  try {\n    getRepresentation(valname);\n    return true;\n  } catch(std::exception&) {\n    return false;\n  }\n}\n\nconst char* RegKey::getValueName(int i) {\n  DWORD maxValueNameLen;\n  LONG result = RegQueryInfoKey(key, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &maxValueNameLen, nullptr, nullptr, nullptr);\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"RegQueryInfoKey\", result);\n  if (valueNameBufLen < maxValueNameLen + 1) {\n    valueNameBufLen = maxValueNameLen + 1;\n    delete [] valueName;\n    valueName = new char[valueNameBufLen];\n  }\n  DWORD length = valueNameBufLen;\n  result = RegEnumValue(key, i, valueName, &length, nullptr, nullptr, nullptr, nullptr);\n  if (result == ERROR_NO_MORE_ITEMS) return nullptr;\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"RegEnumValue\", result);\n  return valueName;\n}\n\nconst char* RegKey::getKeyName(int i) {\n  DWORD maxValueNameLen;\n  LONG result = RegQueryInfoKey(key, nullptr, nullptr, nullptr, nullptr, &maxValueNameLen, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"RegQueryInfoKey\", result);\n  if (valueNameBufLen < maxValueNameLen + 1) {\n    valueNameBufLen = maxValueNameLen + 1;\n    delete [] valueName;\n    valueName = new char[valueNameBufLen];\n  }\n  DWORD length = valueNameBufLen;\n  result = RegEnumKeyEx(key, i, valueName, &length, nullptr, nullptr, nullptr, nullptr);\n  if (result == ERROR_NO_MORE_ITEMS) return nullptr;\n  if (result != ERROR_SUCCESS)\n    throw core::win32_error(\"RegEnumKey\", result);\n  return valueName;\n}\n"
  },
  {
    "path": "win/rfb_win32/Registry.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n// -=- Registry.h\n\n// C++ wrappers around the Win32 Registry APIs\n\n#ifndef __RFB_WIN32_REGISTRY_H__\n#define __RFB_WIN32_REGISTRY_H__\n\n#include <string>\n\n#include <windows.h>\n#include <rfb_win32/Security.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class RegKey {\n    public:\n      // No key open\n      RegKey();\n\n      // Duplicate the specified existing key\n      RegKey(const HKEY k);\n      RegKey(const RegKey& k);\n\n      // Calls close() internally\n      ~RegKey();\n\n      void setHKEY(HKEY key, bool freeKey);\n    private:\n      RegKey& operator=(const RegKey& k);\n      HKEY& operator=(const HKEY& k);\n    public:\n\n      // Returns true if key was created, false if already existed\n      bool createKey(const RegKey& root, const char* name);\n\n      // Opens key if it exists, or raises an exception if not\n      void openKey(const RegKey& root, const char* name, bool readOnly=false);\n\n      // Set the (discretionary) access control list for the key\n      void setDACL(const PACL acl, bool inheritFromParent=true);\n\n      // Closes current key, if required\n      void close();\n\n      // Delete a subkey/value\n      void deleteKey(const char* name) const;\n      void deleteValue(const char* name) const;\n\n\n      // Block waiting for a registry change, OR return immediately and notify the\n      // event when there is a change, if specified\n      void awaitChange(bool watchSubTree, DWORD filter, HANDLE event=nullptr) const;\n\n      void setExpandString(const char* valname, const char* s) const;\n      void setString(const char* valname, const char* s) const;\n      void setBinary(const char* valname, const void* data, size_t length) const;\n      void setInt(const char* valname, int i) const;\n      void setBool(const char* valname, bool b) const;\n\n      std::string getString(const char* valname) const;\n      std::string getString(const char* valname, const char* def) const;\n\n      std::vector<uint8_t> getBinary(const char* valname) const;\n      std::vector<uint8_t> getBinary(const char* valname, const uint8_t* def, size_t deflength) const;\n\n      int getInt(const char* valname) const;\n      int getInt(const char* valname, int def) const;\n\n      bool getBool(const char* valname) const;\n      bool getBool(const char* valname, bool def) const;\n\n      std::string getRepresentation(const char* valname) const;\n\n      bool isValue(const char* valname) const;\n\n      // Get the name of value/key number \"i\"\n      // If there are fewer than \"i\" values then return 0\n      // NAME IS OWNED BY RegKey OBJECT!\n      const char* getValueName(int i);\n      const char* getKeyName(int i);\n\n      operator HKEY() const;\n    protected:\n      HKEY key;\n      bool freeKey;\n      char* valueName;\n      DWORD valueNameBufLen;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_REG_CONFIG_H__\n"
  },
  {
    "path": "win/rfb_win32/SDisplay.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- SDisplay.cxx\n//\n// The SDisplay class encapsulates a particular system display.\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <assert.h>\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/SDisplay.h>\n#include <rfb_win32/Service.h>\n#include <rfb_win32/TsSessions.h>\n#include <rfb_win32/CleanDesktop.h>\n#include <rfb_win32/CurrentUser.h>\n#include <rfb_win32/MonitorInfo.h>\n#include <rfb_win32/SDisplayCorePolling.h>\n#include <rfb_win32/SDisplayCoreWMHooks.h>\n#include <rfb/VNCServer.h>\n#include <rfb/ledStates.h>\n\n\nusing namespace core;\nusing namespace rdr;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"SDisplay\");\n\n// - SDisplay-specific configuration options\n\nIntParameter rfb::win32::SDisplay::updateMethod(\"UpdateMethod\",\n  \"How to discover desktop updates; 0 - Polling, 1 - Application hooking, 2 - Driver hooking.\",\n  0, 0, 2);\nBoolParameter rfb::win32::SDisplay::disableLocalInputs(\"DisableLocalInputs\",\n  \"Disable local keyboard and pointer input while the server is in use\", false);\nEnumParameter rfb::win32::SDisplay::disconnectAction(\"DisconnectAction\",\n  \"Action to perform when all clients have disconnected.  (None, Lock, Logoff)\",\n  {\"None\", \"Lock\", \"Logoff\"}, \"None\");\nStringParameter displayDevice(\"DisplayDevice\",\n  \"Display device name of the monitor to be remoted, or empty to export the whole desktop.\", \"\");\nBoolParameter rfb::win32::SDisplay::removeWallpaper(\"RemoveWallpaper\",\n  \"Remove the desktop wallpaper when the server is in use.\", false);\nBoolParameter rfb::win32::SDisplay::disableEffects(\"DisableEffects\",\n  \"Disable desktop user interface effects when the server is in use.\", false);\n\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// SDisplay\n//\n\n// -=- Constructor/Destructor\n\nSDisplay::SDisplay()\n  : server(nullptr), pb(nullptr), device(nullptr),\n    core(nullptr), ptr(nullptr), kbd(nullptr), clipboard(nullptr),\n    inputs(nullptr), monitor(nullptr), cleanDesktop(nullptr), cursor(nullptr),\n    statusLocation(nullptr), queryConnectionHandler(nullptr), ledState(0)\n{\n  updateEvent.h = CreateEvent(nullptr, TRUE, FALSE, nullptr);\n  terminateEvent.h = CreateEvent(nullptr, TRUE, FALSE, nullptr);\n}\n\nSDisplay::~SDisplay()\n{\n  // XXX when the VNCServer has been deleted with clients active, stop()\n  // doesn't get called - this ought to be fixed in VNCServerST.  In any event,\n  // we should never call any methods on VNCServer once we're being deleted.\n  // This is because it is supposed to be guaranteed that the SDesktop exists\n  // throughout the lifetime of the VNCServer.  So if we're being deleted, then\n  // the VNCServer ought not to exist and therefore we shouldn't invoke any\n  // methods on it.  Setting server to zero here ensures that stop() doesn't\n  // call setPixelBuffer(0) on the server.\n  server = nullptr;\n  if (core) stop();\n}\n\n\n// -=- SDesktop interface\n\nvoid SDisplay::init(VNCServer* vs)\n{\n  server = vs;\n}\n\nvoid SDisplay::start()\n{\n  vlog.debug(\"Starting\");\n\n  // Try to make session zero the console session\n  if (!inConsoleSession())\n    setConsoleSession();\n\n  // Start the SDisplay core\n  startCore();\n\n  vlog.debug(\"Started\");\n\n  if (statusLocation) *statusLocation = true;\n}\n\nvoid SDisplay::stop()\n{\n  vlog.debug(\"Stopping\");\n\n  // If we successfully start()ed then perform the DisconnectAction\n  if (core) {\n    CurrentUserToken cut;\n    if (disconnectAction == \"Logoff\") {\n      if (!cut.h)\n        vlog.info(\"Ignoring DisconnectAction=Logoff - no current user\");\n      else\n        ExitWindowsEx(EWX_LOGOFF, 0);\n    } else if (disconnectAction == \"Lock\") {\n      if (!cut.h) {\n        vlog.info(\"Ignoring DisconnectAction=Lock - no current user\");\n      } else {\n        LockWorkStation();\n      }\n    }\n  }\n\n  // Stop the SDisplayCore\n  server->setPixelBuffer(nullptr);\n  stopCore();\n\n  vlog.debug(\"Stopped\");\n\n  if (statusLocation) *statusLocation = false;\n}\n\nvoid SDisplay::terminate()\n{\n  SetEvent(terminateEvent);\n}\n\n\nvoid SDisplay::queryConnection(network::Socket* sock,\n                               const char* userName)\n{\n  assert(server != nullptr);\n\n  if (queryConnectionHandler) {\n    queryConnectionHandler->queryConnection(sock, userName);\n    return;\n  }\n\n  server->approveConnection(sock, true);\n}\n\n\nvoid SDisplay::startCore() {\n\n  // Currently, we just check whether we're in the console session, and\n  //   fail if not\n  if (!inConsoleSession())\n    throw std::runtime_error(\"Console is not session zero - oreconnect to restore Console sessin\");\n  \n  // Switch to the current input desktop\n  if (rfb::win32::desktopChangeRequired()) {\n    if (!rfb::win32::changeDesktop())\n      throw std::runtime_error(\"Unable to switch into input desktop\");\n  }\n\n  // Initialise the change tracker and clipper\n  updates.clear();\n  clipper.setUpdateTracker(server);\n\n  // Create the framebuffer object\n  recreatePixelBuffer(true);\n\n  // Create the SDisplayCore\n  updateMethod_ = updateMethod;\n  int tryMethod = updateMethod_;\n  while (!core) {\n    try {\n      if (tryMethod == 1)\n        core = new SDisplayCoreWMHooks(this, &updates);\n      else\n        core = new SDisplayCorePolling(this, &updates);\n      core->setScreenRect(screenRect);\n    } catch (std::exception& e) {\n      delete core; core = nullptr;\n      if (tryMethod == 0)\n        throw std::runtime_error(\"Unable to access desktop\");\n      tryMethod--;\n      vlog.error(\"%s\", e.what());\n    }\n  }\n  vlog.info(\"Started %s\", core->methodName());\n\n  // Start display monitor, clipboard handler and input handlers\n  monitor = new WMMonitor;\n  monitor->setNotifier(this);\n  clipboard = new Clipboard;\n  clipboard->setNotifier(this);\n  ptr = new SPointer;\n  kbd = new SKeyboard;\n  inputs = new WMBlockInput;\n  cursor = new WMCursor;\n\n  // Apply desktop optimisations\n  cleanDesktop = new CleanDesktop;\n  if (removeWallpaper)\n    cleanDesktop->disableWallpaper();\n  if (disableEffects)\n    cleanDesktop->disableEffects();\n  isWallpaperRemoved = removeWallpaper;\n  areEffectsDisabled = disableEffects;\n\n  checkLedState();\n  if (server)\n    server->setLEDState(ledState);\n}\n\nvoid SDisplay::stopCore() {\n  if (core)\n    vlog.info(\"Stopping %s\", core->methodName());\n  delete core; core = nullptr;\n  delete pb; pb = nullptr;\n  delete device; device = nullptr;\n  delete monitor; monitor = nullptr;\n  delete clipboard; clipboard = nullptr;\n  delete inputs; inputs = nullptr;\n  delete ptr; ptr = nullptr;\n  delete kbd; kbd = nullptr;\n  delete cleanDesktop; cleanDesktop = nullptr;\n  delete cursor; cursor = nullptr;\n  ResetEvent(updateEvent);\n}\n\n\nbool SDisplay::isRestartRequired() {\n  // - We must restart the SDesktop if:\n  // 1. We are no longer in the input desktop.\n  // 2. The any setting has changed.\n\n  // - Check that our session is the Console\n  if (!inConsoleSession())\n    return true;\n\n  // - Check that we are in the input desktop\n  if (rfb::win32::desktopChangeRequired())\n    return true;\n\n  // - Check that the update method setting hasn't changed\n  //   NB: updateMethod reflects the *selected* update method, not\n  //   necessarily the one in use, since we fall back to simpler\n  //   methods if more advanced ones fail!\n  if (updateMethod_ != updateMethod)\n    return true;\n\n  // - Check that the desktop optimisation settings haven't changed\n  //   This isn't very efficient, but it shouldn't change very often!\n  if ((isWallpaperRemoved != removeWallpaper) ||\n      (areEffectsDisabled != disableEffects))\n    return true;\n\n  return false;\n}\n\n\nvoid SDisplay::restartCore() {\n  vlog.info(\"Restarting\");\n\n  // Stop the existing Core  related resources\n  stopCore();\n  try {\n    // Start a new Core if possible\n    startCore();\n    vlog.info(\"Restarted\");\n  } catch (std::exception& e) {\n    // If startCore() fails then we MUST disconnect all clients,\n    // to cause the server to stop() the desktop.\n    // Otherwise, the SDesktop is in an inconsistent state\n    // and the server will crash.\n    server->closeClients(e.what());\n  }\n}\n\n\nvoid SDisplay::handleClipboardRequest() {\n  server->sendClipboardData(clipboard->getClipText().c_str());\n}\n\nvoid SDisplay::handleClipboardAnnounce(bool available) {\n  // FIXME: Wait for an application to actually request it\n  if (available)\n    server->requestClipboard();\n}\n\nvoid SDisplay::handleClipboardData(const char* data) {\n  clipboard->setClipText(data);\n}\n\n\nvoid SDisplay::pointerEvent(const Point& pos, uint16_t buttonmask) {\n  if (pb->getRect().contains(pos)) {\n    Point screenPos = pos.translate(screenRect.tl);\n    // - Check that the SDesktop doesn't need restarting\n    if (isRestartRequired())\n      restartCore();\n    if (ptr)\n      ptr->pointerEvent(screenPos, buttonmask);\n  }\n}\n\nvoid SDisplay::keyEvent(uint32_t keysym, uint32_t keycode, bool down) {\n  // - Check that the SDesktop doesn't need restarting\n  if (isRestartRequired())\n    restartCore();\n  if (kbd)\n    kbd->keyEvent(keysym, keycode, down);\n}\n\nbool SDisplay::checkLedState() {\n  unsigned state = 0;\n\n  if (GetKeyState(VK_SCROLL) & 0x0001)\n    state |= ledScrollLock;\n  if (GetKeyState(VK_NUMLOCK) & 0x0001)\n    state |= ledNumLock;\n  if (GetKeyState(VK_CAPITAL) & 0x0001)\n    state |= ledCapsLock;\n\n  if (ledState != state) {\n    ledState = state;\n    return true;\n  }\n\n  return false;\n}\n\n\nvoid\nSDisplay::notifyClipboardChanged(bool available) {\n  vlog.debug(\"Clipboard text changed\");\n  if (server)\n    server->announceClipboard(available);\n}\n\n\nvoid\nSDisplay::notifyDisplayEvent(WMMonitor::Notifier::DisplayEventType evt) {\n  switch (evt) {\n  case WMMonitor::Notifier::DisplaySizeChanged:\n    vlog.debug(\"Desktop size changed\");\n    recreatePixelBuffer();\n    break;\n  case WMMonitor::Notifier::DisplayPixelFormatChanged:\n    vlog.debug(\"Desktop format changed\");\n    recreatePixelBuffer();\n    break;\n  default:\n    vlog.error(\"Unknown display event received\");\n  }\n}\n\nvoid\nSDisplay::processEvent(HANDLE event) {\n  if (event == updateEvent) {\n    vlog.write(120, \"processEvent\");\n    ResetEvent(updateEvent);\n\n    // - If the SDisplay isn't even started then quit now\n    if (!core) {\n      vlog.error(\"Not start()ed\");\n      return;\n    }\n\n    // - Ensure that the disableLocalInputs flag is respected\n    inputs->blockInputs(disableLocalInputs);\n\n    // - Only process updates if the server is ready\n    if (server) {\n      // - Check that the SDesktop doesn't need restarting\n      if (isRestartRequired()) {\n        restartCore();\n        return;\n      }\n\n      // - Flush any updates from the core\n      try {\n        core->flushUpdates();\n      } catch (std::exception& e) {\n        vlog.error(\"%s\", e.what());\n        restartCore();\n        return;\n      }\n\n      // Ensure the cursor is up to date\n      WMCursor::Info info = cursor->getCursorInfo();\n      if (old_cursor != info) {\n        // Update the cursor shape if the visibility has changed\n        bool set_cursor = info.visible != old_cursor.visible;\n        // OR if the cursor is visible and the shape has changed.\n        set_cursor |= info.visible && (old_cursor.cursor != info.cursor);\n\n        // Update the cursor shape\n        if (set_cursor)\n          pb->setCursor(info.visible ? info.cursor : nullptr, server);\n\n        // Update the cursor position\n        // NB: First translate from Screen coordinates to Desktop\n        Point desktopPos = info.position.translate(screenRect.tl.negate());\n        server->setCursorPos(desktopPos, false);\n\n        old_cursor = info;\n      }\n\n      // Flush any changes to the server\n      flushChangeTracker();\n\n      // Forward current LED state to the server\n      if (checkLedState())\n        server->setLEDState(ledState);\n    }\n    return;\n  }\n  throw std::runtime_error(\"No such event\");\n}\n\n\n// -=- Protected methods\n\nvoid\nSDisplay::recreatePixelBuffer(bool force) {\n  // Open the specified display device\n  //   If no device is specified, open entire screen using GetDC().\n  //   Opening the whole display with CreateDC doesn't work on multi-monitor\n  //   systems for some reason.\n  DeviceContext* new_device = nullptr;\n  if (strlen(displayDevice) > 0) {\n    vlog.info(\"Attaching to device %s\", (const char*)displayDevice);\n    new_device = new DeviceDC(displayDevice);\n  }\n  if (!new_device) {\n    vlog.info(\"Attaching to virtual desktop\");\n    new_device = new WindowDC(nullptr);\n  }\n\n  // Get the coordinates of the specified dispay device\n  Rect newScreenRect;\n  if (strlen(displayDevice) > 0) {\n    MonitorInfo info(displayDevice);\n    newScreenRect = {info.rcMonitor.left, info.rcMonitor.top,\n                     info.rcMonitor.right, info.rcMonitor.bottom};\n  } else {\n    newScreenRect = new_device->getClipBox();\n  }\n\n  // If nothing has changed & a recreate has not been forced, delete\n  // the new device context and return\n  if (pb && !force &&\n    newScreenRect == screenRect &&\n    new_device->getPF() == pb->getPF()) {\n    delete new_device;\n    return;\n  }\n\n  // Flush any existing changes to the server\n  flushChangeTracker();\n\n  // Delete the old pixelbuffer and device context\n  vlog.debug(\"Deleting old pixel buffer & device\");\n  if (pb)\n    delete pb;\n  if (device)\n    delete device;\n\n  // Create a DeviceFrameBuffer attached to the new device\n  vlog.debug(\"Creating pixel buffer\");\n  DeviceFrameBuffer* new_buffer = new DeviceFrameBuffer(*new_device);\n\n  // Replace the old PixelBuffer\n  screenRect = newScreenRect;\n  pb = new_buffer;\n  device = new_device;\n\n  // Initialise the pixels\n  pb->grabRegion(pb->getRect());\n\n  // Prevent future grabRect operations from throwing exceptions\n  pb->setIgnoreGrabErrors(true);\n\n  // Update the clipping update tracker\n  clipper.setClipRect(pb->getRect());\n\n  // Inform the core of the changes\n  if (core)\n    core->setScreenRect(screenRect);\n\n  // Inform the server of the changes\n  if (server)\n    server->setPixelBuffer(pb);\n}\n\nbool SDisplay::flushChangeTracker() {\n  if (updates.is_empty())\n    return false;\n\n  vlog.write(120, \"flushChangeTracker\");\n\n  // Translate the update coordinates from Screen coords to Desktop\n  updates.translate(screenRect.tl.negate());\n\n  // Clip the updates & flush them to the server\n  updates.copyTo(&clipper);\n  updates.clear();\n  return true;\n}\n"
  },
  {
    "path": "win/rfb_win32/SDisplay.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright 2011-2019 Pierre Ossman for Cendio AB\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- SDisplay.h\n//\n// The SDisplay class encapsulates a system display.\n\n#ifndef __RFB_SDISPLAY_H__\n#define __RFB_SDISPLAY_H__\n\n#include <core/Configuration.h>\n\n#include <rfb/SDesktop.h>\n#include <rfb/UpdateTracker.h>\n\n#include <rfb_win32/Handle.h>\n#include <rfb_win32/EventManager.h>\n#include <rfb_win32/SInput.h>\n#include <rfb_win32/Clipboard.h>\n#include <rfb_win32/CleanDesktop.h>\n#include <rfb_win32/WMCursor.h>\n#include <rfb_win32/WMNotifier.h>\n#include <rfb_win32/DeviceFrameBuffer.h>\n#include <rfb_win32/DeviceContext.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    //\n    // -=- SDisplay\n    //\n\n    class SDisplayCore {\n    public:\n      virtual ~SDisplayCore() {};\n      virtual void setScreenRect(const core::Rect& screenRect_) = 0;\n      virtual void flushUpdates() = 0;\n      virtual const char* methodName() const = 0;\n    };\n\n    class QueryConnectionHandler {\n    public:\n      virtual ~QueryConnectionHandler() {}\n      virtual void queryConnection(network::Socket* sock,\n                                   const char* userName) = 0;\n    };\n\n    class SDisplay : public SDesktop,\n      WMMonitor::Notifier,\n      Clipboard::Notifier,\n      public EventHandler\n    {\n    public:\n      SDisplay();\n      virtual ~SDisplay();\n\n      // -=- SDesktop interface\n\n      void init(VNCServer* vs) override;\n      void start() override;\n      void stop() override;\n      void terminate() override;\n      void queryConnection(network::Socket* sock,\n                           const char* userName) override;\n      void handleClipboardRequest() override;\n      void handleClipboardAnnounce(bool available) override;\n      void handleClipboardData(const char* data) override;\n      void pointerEvent(const core::Point& pos,\n                        uint16_t buttonmask) override;\n      void keyEvent(uint32_t keysym, uint32_t keycode, bool down) override;\n\n      // -=- Clipboard events\n      \n      void notifyClipboardChanged(bool available) override;\n\n      // -=- Display events\n      \n      void notifyDisplayEvent(WMMonitor::Notifier::DisplayEventType evt) override;\n\n      // -=- EventHandler interface\n\n      HANDLE getUpdateEvent() {return updateEvent;}\n      HANDLE getTerminateEvent() {return terminateEvent;}\n      void processEvent(HANDLE event) override;\n\n      // -=- Notification of whether or not SDisplay is started\n\n      void setStatusLocation(bool* status) {statusLocation = status;}\n\n      // -=- Set handler for incoming connections\n\n      void setQueryConnectionHandler(QueryConnectionHandler* qch) {\n        queryConnectionHandler = qch;\n      }\n\n      static core::IntParameter updateMethod;\n      static core::BoolParameter disableLocalInputs;\n      static core::EnumParameter disconnectAction;\n      static core::BoolParameter removeWallpaper;\n      static core::BoolParameter disableEffects;\n\n      // -=- Use by VNC Config to determine whether hooks are available\n      static bool areHooksAvailable();\n\n\n    protected:\n      bool isRestartRequired();\n      void startCore();\n      void stopCore();\n      void restartCore();\n      void recreatePixelBuffer(bool force=false);\n      bool flushChangeTracker();  // true if flushed, false if empty\n      bool checkLedState();\n\n      VNCServer* server;\n\n      // -=- Display pixel buffer\n      DeviceFrameBuffer* pb;\n      DeviceContext* device;\n\n      // -=- The coordinates of Window's entire virtual Screen\n      core::Rect screenRect;\n\n      // -=- All changes are collected in UN-CLIPPED Display coords and merged\n      //     When they are to be flushed to the VNCServer, they are changed\n      //     to server coords and clipped appropriately.\n      SimpleUpdateTracker updates;\n      ClippingUpdateTracker clipper;\n\n      // -=- Internal SDisplay implementation\n      SDisplayCore* core;\n      int updateMethod_;\n\n      // Inputs\n      SPointer* ptr;\n      SKeyboard* kbd;\n      Clipboard* clipboard;\n      WMBlockInput* inputs;\n\n      // Desktop state\n      WMMonitor* monitor;\n\n      // Desktop optimisation\n      CleanDesktop* cleanDesktop;\n      bool isWallpaperRemoved;\n      bool areEffectsDisabled;\n\n      // Cursor\n      WMCursor* cursor;\n      WMCursor::Info old_cursor;\n      core::Region old_cursor_region;\n      core::Point cursor_renderpos;\n\n      // -=- Event signalled to trigger an update to be flushed\n      Handle updateEvent;\n      // -=- Event signalled to terminate the server\n      Handle terminateEvent;\n\n      // -=- Where to write the active/inactive indicator to\n      bool* statusLocation;\n\n      // -=- Whom to query incoming connections\n      QueryConnectionHandler* queryConnectionHandler;\n\n      unsigned ledState;\n    };\n\n  }\n}\n\n#endif // __RFB_SDISPLAY_H__\n"
  },
  {
    "path": "win/rfb_win32/SDisplayCorePolling.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- SDisplayCorePolling.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/SDisplayCorePolling.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"SDisplayCorePolling\");\n\nconst int POLLING_SEGMENTS = 16;\n\nconst unsigned int SDisplayCorePolling::pollTimerId = 1;\n\nSDisplayCorePolling::SDisplayCorePolling(SDisplay* d, UpdateTracker* ut, int pollInterval_)\n  : MsgWindow(\"rfb::win32::SDisplayCorePolling\"),\n  pollTimer(getHandle(), pollTimerId), pollNextStrip(false), display(d), updateTracker(ut) {\n  pollInterval = pollInterval_ / POLLING_SEGMENTS;\n  if (pollInterval < 10)\n    pollInterval = 10;\n  copyrect.setUpdateTracker(ut);\n}\n\nSDisplayCorePolling::~SDisplayCorePolling() {\n}\n\nLRESULT SDisplayCorePolling::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {\n  if (msg == WM_TIMER && wParam == pollTimerId) {\n    pollNextStrip = true;\n    SetEvent(display->getUpdateEvent());\n    return 0;\n  }\n  return MsgWindow::processMessage(msg, wParam, lParam);\n}\n\nvoid SDisplayCorePolling::setScreenRect(const Rect& screenRect_) {\n  vlog.info(\"setScreenRect\");\n  screenRect = screenRect_;\n  pollIncrementY = (screenRect.height()+POLLING_SEGMENTS-1)/POLLING_SEGMENTS;\n  pollNextY = screenRect.tl.y;\n  pollTimer.start(pollInterval);\n}\n\nvoid SDisplayCorePolling::flushUpdates() {\n  vlog.write(120, \"flushUpdates\");\n\n  // Check for window movement\n  while (copyrect.processEvent()) {}\n\n  if (pollNextStrip) {\n    // Poll the next strip of the screen (in Screen coordinates)\n    pollNextStrip = false;\n    Rect pollrect = screenRect;\n    if (pollNextY >= pollrect.br.y) {\n      // Yes.  Reset the counter and return\n      pollNextY = pollrect.tl.y;\n    } else {\n      // No.  Poll the next section\n      pollrect.tl.y = pollNextY;\n      pollNextY += pollIncrementY;\n      if (pollrect.br.y > pollNextY)\n        pollrect.br.y = pollNextY;\n      updateTracker->add_changed(pollrect);\n    }\n  }\n}\n"
  },
  {
    "path": "win/rfb_win32/SDisplayCorePolling.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- SDisplayCorePolling.h\n//\n// SDisplayCore implementation that simply polls the screen, in sections,\n// in order to detect changes.  This Core will signal the SDisplay's\n// updateEvent regularly, causing it to call the Core back to propagate\n// changes to the VNC Server.\n\n\n#ifndef __RFB_SDISPLAY_CORE_POLLING_H__\n#define __RFB_SDISPLAY_CORE_POLLING_H__\n\n#include <rfb_win32/SDisplay.h>\n#include <rfb_win32/IntervalTimer.h>\n#include <rfb_win32/WMWindowCopyRect.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    class SDisplayCorePolling : public SDisplayCore, protected MsgWindow {\n    public:\n      SDisplayCorePolling(SDisplay* display, UpdateTracker* ut, int pollIntervalMs=50);\n      ~SDisplayCorePolling();\n\n      // - Called by SDisplay to inform Core of the screen size\n      void setScreenRect(const core::Rect& screenRect_) override;\n\n      // - Called by SDisplay to flush updates to the specified tracker\n      void flushUpdates() override;\n\n      const char* methodName() const override { return \"Polling\"; }\n\n    protected:\n      // - MsgWindow overrides\n      //   processMessage is used to service the cursor & polling timers\n      LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) override;\n\n      // - Hooking subcomponents used to track the desktop state\n      WMCopyRect copyrect;\n\n      // - Background full screen polling fields\n      IntervalTimer pollTimer;\n      static const unsigned int pollTimerId;\n      core::Rect screenRect;\n      int pollInterval;\n      int pollNextY;\n      int pollIncrementY;\n      bool pollNextStrip;\n\n      // - Handle back to the owning SDisplay, and to the UpdateTracker to flush to\n      SDisplay* display;\n      UpdateTracker* updateTracker;\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/SDisplayCoreWMHooks.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- SDisplayCoreWMHooks.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/SDisplayCoreWMHooks.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"SDisplayCoreWMHooks\");\n\nconst unsigned int SDisplayCoreWMHooks::cursorTimerId = 2;\nconst unsigned int SDisplayCoreWMHooks::consolePollTimerId = 3;\n\n\nSDisplayCoreWMHooks::SDisplayCoreWMHooks(SDisplay* d, UpdateTracker* ut)\n  : SDisplayCorePolling(d, ut, 5000),\n  cursorTimer(getHandle(), cursorTimerId),\n  consolePollTimer(getHandle(), consolePollTimerId),\n  pollConsoles(false) {\n  if (!hooks.setEvent(display->getUpdateEvent()))\n    throw std::runtime_error(\"Hook subsystem failed to initialise\");\n  poller.setUpdateTracker(updateTracker);\n  cursorTimer.start(20);\n  consolePollTimer.start(200);\n}\n\nSDisplayCoreWMHooks::~SDisplayCoreWMHooks() {\n}\n\nLRESULT SDisplayCoreWMHooks::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {\n  if (msg == WM_TIMER) {\n    if (wParam == cursorTimerId) {\n      SetEvent(display->getUpdateEvent());\n      return 0;\n    } else if (wParam == consolePollTimerId) {\n      pollConsoles = true;\n      SetEvent(display->getUpdateEvent());\n      return 0;\n    }\n  }\n  return SDisplayCorePolling::processMessage(msg, wParam, lParam);\n}\n\nvoid SDisplayCoreWMHooks::flushUpdates() {\n  // Poll any visible console windows\n  if (pollConsoles) {\n    pollConsoles = false;\n    poller.processEvent();\n  }\n\n  // Check for updates from the hooks\n  hooks.getUpdates(updateTracker);\n\n  // Check for updates from the polling Core\n  SDisplayCorePolling::flushUpdates();\n}\n"
  },
  {
    "path": "win/rfb_win32/SDisplayCoreWMHooks.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- SDisplayCoreWMHooks.h\n//\n// SDisplayCore implementation that uses WMHooks to capture changes to\n// the display.\n// Whenever changes are detected, the SDisplay's updateEvent is signalled,\n// so that it can perform housekeeping tasks (like ensuring the currently\n// active desktop is the correct one), before flushing changes from the\n// Core to the VNC Server.  The SDisplay will clip the changes before they\n// reach the VNC Server.\n\n\n#ifndef __RFB_SDISPLAY_CORE_WMHOOKS_H__\n#define __RFB_SDISPLAY_CORE_WMHOOKS_H__\n\n#include <rfb_win32/SDisplayCorePolling.h>\n#include <rfb_win32/WMHooks.h>\n#include <rfb_win32/WMPoller.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    class SDisplayCoreWMHooks : public SDisplayCorePolling {\n    public:\n      SDisplayCoreWMHooks(SDisplay* display, UpdateTracker* ut);\n      ~SDisplayCoreWMHooks();\n\n      // - Called by SDisplay to flush updates to the specified tracker\n      void flushUpdates() override;\n\n      const char* methodName() const override { return \"VNC Hooks\"; }\n\n    protected:\n      // - MsgWindow overrides\n      //   processMessage is used to service the cursor & polling timers\n      LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) override;\n\n      // - Hooking subcomponents used to track the desktop state\n      WMHooks hooks;\n      WMPoller poller;\n      IntervalTimer cursorTimer;\n      IntervalTimer consolePollTimer;\n      bool pollConsoles;\n      static const unsigned int consolePollTimerId;\n      static const unsigned int cursorTimerId;\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/SInput.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- SInput.cxx\n//\n// A number of routines that accept VNC input event data and perform\n// the appropriate actions under Win32\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#define XK_MISCELLANY\n#define XK_LATIN1\n#define XK_CURRENCY\n#include <rfb/keysymdef.h>\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/SInput.h>\n#include <rfb_win32/MonitorInfo.h>\n#include <rfb_win32/Service.h>\n#include <rfb_win32/keymap.h>\n\nusing namespace core;\nusing namespace rfb;\n\nstatic LogWriter vlog(\"SInput\");\n\n//\n// -=- Pointer implementation for Win32\n//\n\nstatic DWORD buttonDownMapping[8] = {\n  MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN,\n  MOUSEEVENTF_WHEEL, MOUSEEVENTF_WHEEL, 0, 0, 0\n};\n\nstatic DWORD buttonUpMapping[8] = {\n  MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP,\n  MOUSEEVENTF_WHEEL, MOUSEEVENTF_WHEEL, 0, 0, 0\n};\n\nstatic DWORD buttonDataMapping[8] = {\n  0, 0, 0, 120, (DWORD)-120, 0, 0, 0\n};\n\nwin32::SPointer::SPointer()\n  : last_buttonmask(0)\n{\n}\n\nvoid\nwin32::SPointer::pointerEvent(const Point& pos, uint16_t buttonmask)\n{\n  // - We are specifying absolute coordinates\n  DWORD flags = MOUSEEVENTF_ABSOLUTE;\n\n  // - Has the pointer moved since the last event?\n  if (last_position != pos)\n    flags |= MOUSEEVENTF_MOVE;\n\n  // - If the system swaps left and right mouse buttons then we must\n  //   swap them here to negate the effect, so that we do the actual\n  //   action we mean to do\n  if (::GetSystemMetrics(SM_SWAPBUTTON)) {\n    bool leftDown = buttonmask & 1;\n    bool rightDown = buttonmask & 4;\n    buttonmask = (buttonmask & ~(1 | 4));\n    if (leftDown) buttonmask |= 4;\n    if (rightDown) buttonmask |= 1;\n  }\n\n  DWORD data = 0;\n  for (int i = 0; i < 8; i++) {\n    if ((buttonmask & (1<<i)) != (last_buttonmask & (1<<i))) {\n      if (buttonmask & (1<<i)) {\n        flags |= buttonDownMapping[i];\n        if (buttonDataMapping[i]) {\n          if (data) vlog.info(\"Warning: Two buttons set mouse_event data field\");\n          data = buttonDataMapping[i];\n        }\n      } else {\n        flags |= buttonUpMapping[i];\n      }\n    }\n  }\n\n  last_position = pos;\n  last_buttonmask = buttonmask;\n\n  Rect primaryDisplay(0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));\n  if (primaryDisplay.contains(pos)) {\n    // mouse_event wants coordinates specified as a proportion of the\n    // primary display's size, scaled to the range 0 to 65535\n    Point scaled;\n    scaled.x = (pos.x * 65535) / (primaryDisplay.width()-1);\n    scaled.y = (pos.y * 65535) / (primaryDisplay.height()-1);\n    ::mouse_event(flags, scaled.x, scaled.y, data, 0);\n  } else {\n    // The event lies outside the primary monitor.  Under Win2K, we can just use\n    // SendInput, which allows us to provide coordinates scaled to the virtual desktop.\n    // SendInput is available on all multi-monitor-aware platforms.\n    INPUT evt;\n    evt.type = INPUT_MOUSE;\n    Point vPos(pos.x-GetSystemMetrics(SM_XVIRTUALSCREEN),\n               pos.y-GetSystemMetrics(SM_YVIRTUALSCREEN));\n    evt.mi.dx = (vPos.x * 65535) / (GetSystemMetrics(SM_CXVIRTUALSCREEN)-1);\n    evt.mi.dy = (vPos.y * 65535) / (GetSystemMetrics(SM_CYVIRTUALSCREEN)-1);\n    evt.mi.dwFlags = flags | MOUSEEVENTF_VIRTUALDESK;\n    evt.mi.dwExtraInfo = 0;\n    evt.mi.mouseData = data;\n    evt.mi.time = 0;\n    if (SendInput(1, &evt, sizeof(evt)) != 1)\n      throw core::win32_error(\"SendInput\", GetLastError());\n  }\n}\n\n//\n// -=- Keyboard implementation\n//\n\nBoolParameter rfb::win32::SKeyboard::deadKeyAware(\"DeadKeyAware\",\n  \"Whether to assume the viewer has already interpreted dead key sequences \"\n  \"into latin-1 characters\", true);\nBoolParameter rfb::win32::SKeyboard::rawKeyboard(\"RawKeyboard\",\n  \"Send keyboard events straight through and avoid mapping them to the \"\n  \"current keyboard layout\", false);\n\n// The keysymToAscii table transforms a couple of awkward keysyms into their\n// ASCII equivalents.\nstruct  keysymToAscii_t {\n  uint32_t keysym;\n  uint8_t ascii;\n};\n\nkeysymToAscii_t keysymToAscii[] = {\n  { XK_KP_Space, ' ' },\n  { XK_KP_Equal, '=' },\n};\n\nuint8_t latin1DeadChars[] = {\n  XK_grave, XK_acute, XK_asciicircum, XK_diaeresis, XK_degree, XK_cedilla,\n  XK_asciitilde\n};\n\nstruct latin1ToDeadChars_t {\n  uint8_t latin1Char;\n  uint8_t deadChar;\n  uint8_t baseChar;\n};\n\nlatin1ToDeadChars_t latin1ToDeadChars[] = {\n\n  { XK_Agrave, XK_grave, XK_A },\n  { XK_Egrave, XK_grave, XK_E },\n  { XK_Igrave, XK_grave, XK_I },\n  { XK_Ograve, XK_grave, XK_O },\n  { XK_Ugrave, XK_grave, XK_U },\n  { XK_agrave, XK_grave, XK_a },\n  { XK_egrave, XK_grave, XK_e },\n  { XK_igrave, XK_grave, XK_i },\n  { XK_ograve, XK_grave, XK_o},\n  { XK_ugrave, XK_grave, XK_u },\n\n  { XK_Aacute, XK_acute, XK_A },\n  { XK_Eacute, XK_acute, XK_E },\n  { XK_Iacute, XK_acute, XK_I },\n  { XK_Oacute, XK_acute, XK_O },\n  { XK_Uacute, XK_acute, XK_U },\n  { XK_Yacute, XK_acute, XK_Y },\n  { XK_aacute, XK_acute, XK_a },\n  { XK_eacute, XK_acute, XK_e },\n  { XK_iacute, XK_acute, XK_i },\n  { XK_oacute, XK_acute, XK_o},\n  { XK_uacute, XK_acute, XK_u },\n  { XK_yacute, XK_acute, XK_y },\n\n  { XK_Acircumflex, XK_asciicircum, XK_A },\n  { XK_Ecircumflex, XK_asciicircum, XK_E },\n  { XK_Icircumflex, XK_asciicircum, XK_I },\n  { XK_Ocircumflex, XK_asciicircum, XK_O },\n  { XK_Ucircumflex, XK_asciicircum, XK_U },\n  { XK_acircumflex, XK_asciicircum, XK_a },\n  { XK_ecircumflex, XK_asciicircum, XK_e },\n  { XK_icircumflex, XK_asciicircum, XK_i },\n  { XK_ocircumflex, XK_asciicircum, XK_o},\n  { XK_ucircumflex, XK_asciicircum, XK_u },\n\n  { XK_Adiaeresis, XK_diaeresis, XK_A },\n  { XK_Ediaeresis, XK_diaeresis, XK_E },\n  { XK_Idiaeresis, XK_diaeresis, XK_I },\n  { XK_Odiaeresis, XK_diaeresis, XK_O },\n  { XK_Udiaeresis, XK_diaeresis, XK_U },\n  { XK_adiaeresis, XK_diaeresis, XK_a },\n  { XK_ediaeresis, XK_diaeresis, XK_e },\n  { XK_idiaeresis, XK_diaeresis, XK_i },\n  { XK_odiaeresis, XK_diaeresis, XK_o},\n  { XK_udiaeresis, XK_diaeresis, XK_u },\n  { XK_ydiaeresis, XK_diaeresis, XK_y },\n\n  { XK_Aring, XK_degree, XK_A },\n  { XK_aring, XK_degree, XK_a },\n\n  { XK_Ccedilla, XK_cedilla, XK_C },\n  { XK_ccedilla, XK_cedilla, XK_c },\n\n  { XK_Atilde, XK_asciitilde, XK_A },\n  { XK_Ntilde, XK_asciitilde, XK_N },\n  { XK_Otilde, XK_asciitilde, XK_O },\n  { XK_atilde, XK_asciitilde, XK_a },\n  { XK_ntilde, XK_asciitilde, XK_n },\n  { XK_otilde, XK_asciitilde, XK_o },\n};\n\n// doKeyboardEvent wraps the system keybd_event function and attempts to find\n// the appropriate scancode corresponding to the supplied virtual keycode.\n\ninline void doKeyboardEvent(BYTE vkCode, DWORD flags) {\n  vlog.debug(\"vkCode 0x%x flags 0x%lx\", vkCode, flags);\n  keybd_event(vkCode, MapVirtualKey(vkCode, 0), flags, 0);\n}\n\ninline void doScanCodeEvent(BYTE scancode, bool down) {\n  INPUT evt;\n\n  evt.type = INPUT_KEYBOARD;\n  evt.ki.wVk = 0;\n  evt.ki.dwFlags = KEYEVENTF_SCANCODE;\n\n  if (!down)\n    evt.ki.dwFlags |= KEYEVENTF_KEYUP;\n\n  if (scancode & 0x80) {\n    evt.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;\n    scancode &= ~0x80;\n  }\n\n  evt.ki.wScan = scancode;\n  evt.ki.dwExtraInfo = 0;\n  evt.ki.time = 0;\n  vlog.debug(\"SendInput ScanCode: 0x%x Flags: 0x%lx %s\", scancode,\n             evt.ki.dwFlags, down ? \"Down\" : \"Up\");\n\n  // Windows has some bug where it doesn't look up scan code 0x45\n  // properly, so we need to help it out\n  if (evt.ki.wScan == 0x45) {\n    evt.ki.dwFlags &= ~KEYEVENTF_SCANCODE;\n    if (evt.ki.dwFlags & KEYEVENTF_EXTENDEDKEY)\n      evt.ki.wVk = VK_NUMLOCK;\n    else\n      evt.ki.wVk = VK_PAUSE;\n  }\n\n  if (SendInput(1, &evt, sizeof(evt)) != 1)\n    vlog.error(\"SendInput %lu\", GetLastError());\n}\n\n// KeyStateModifier is a class which helps simplify generating a \"fake\" press\n// or release of shift, ctrl, alt, etc.  An instance of the class is created\n// for every key which may need to be pressed or released.  Then either press()\n// or release() may be called to make sure that the corresponding key is in the\n// right state.  The destructor of the class automatically reverts to the\n// previous state.\n\nclass KeyStateModifier {\npublic:\n  KeyStateModifier(int vkCode_, int flags_=0)\n    : vkCode(vkCode_), flags(flags_), pressed(false), released(false)\n  {}\n  void press() {\n    if (!(GetAsyncKeyState(vkCode) & 0x8000)) {\n      doKeyboardEvent(vkCode, flags);\n      pressed = true;\n    }\n  }\n  void release() {\n    if (GetAsyncKeyState(vkCode) & 0x8000) {\n      doKeyboardEvent(vkCode, flags | KEYEVENTF_KEYUP);\n      released = true;\n    }\n  }\n  ~KeyStateModifier() {\n    if (pressed) {\n      doKeyboardEvent(vkCode, flags | KEYEVENTF_KEYUP);\n    } else if (released) {\n      doKeyboardEvent(vkCode, flags);\n    }\n  }\n  int vkCode;\n  int flags;\n  bool pressed;\n  bool released;\n};\n\n\n// doKeyEventWithModifiers() generates a key event having first \"pressed\" or\n// \"released\" the shift, ctrl or alt modifiers if necessary.\n\nvoid doKeyEventWithModifiers(BYTE vkCode, BYTE modifierState, bool down)\n{\n  KeyStateModifier ctrl(VK_CONTROL);\n  KeyStateModifier alt(VK_MENU);\n  KeyStateModifier shift(VK_SHIFT);\n\n  if (down) {\n    if (modifierState & 2) ctrl.press();\n    if (modifierState & 4) alt.press();\n    if (modifierState & 1) {\n      shift.press(); \n    } else {\n      shift.release();\n    }\n  }\n  doKeyboardEvent(vkCode, down ? 0 : KEYEVENTF_KEYUP);\n}\n\n\nwin32::SKeyboard::SKeyboard()\n{\n  for (unsigned int i = 0; i < sizeof(keymap) / sizeof(keymap_t); i++) {\n    vkMap[keymap[i].keysym] = keymap[i].vk;\n    extendedMap[keymap[i].keysym] = keymap[i].extended;\n  }\n\n  // Find dead characters for the current keyboard layout\n  // XXX how could we handle the keyboard layout changing?\n  BYTE keystate[256];\n  memset(keystate, 0, 256);\n  for (unsigned int j = 0; j < sizeof(latin1DeadChars); j++) {\n    SHORT s = VkKeyScan(latin1DeadChars[j]);\n    if (s != -1) {\n      BYTE vkCode = LOBYTE(s);\n      BYTE modifierState = HIBYTE(s);\n      keystate[VK_SHIFT] = (modifierState & 1) ? 0x80 : 0;\n      keystate[VK_CONTROL] = (modifierState & 2) ? 0x80 : 0;\n      keystate[VK_MENU] = (modifierState & 4) ? 0x80 : 0;\n      uint8_t chars[2];\n      int nchars = ToAscii(vkCode, 0, keystate, (WORD*)&chars, 0);\n      if (nchars < 0) {\n        vlog.debug(\"Found dead key 0x%x '%c'\",\n                   latin1DeadChars[j], latin1DeadChars[j]);\n        deadChars.push_back(latin1DeadChars[j]);\n        ToAscii(vkCode, 0, keystate, (WORD*)&chars, 0);\n      }\n    }\n  }\n}\n\n\nvoid win32::SKeyboard::keyEvent(uint32_t keysym, uint32_t keycode, bool down)\n{\n  // If scan code is available use that directly as windows uses\n  // compatible scancodes\n  if (keycode && rawKeyboard) {\n    // However NumLock incorrectly has the extended bit set\n    if (keycode == 0x45)\n      keycode = 0xc5;\n\n    // And Pause uses NumLock's proper code, except when Control is\n    // also pressed (i.e. when it is generating Break)\n    if ((keycode == 0xc6) && !(GetAsyncKeyState(VK_CONTROL) & 0x8000))\n      keycode = 0x45;\n\n    // And PrintScreen uses a different code than Alt+PrintScreen (SysRq)\n    if ((keycode == 0x54) && !(GetAsyncKeyState(VK_MENU) & 0x8000))\n      keycode = 0xb7;\n\n    if (down && (keycode == 0xd3) &&\n        ((GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0) &&\n        ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0))\n    {\n      rfb::win32::emulateCtrlAltDel();\n      return;\n    }\n\n    doScanCodeEvent(keycode, down);\n    return;\n  }\n\n  for (unsigned int i = 0; i < sizeof(keysymToAscii) / sizeof(keysymToAscii_t); i++) {\n    if (keysymToAscii[i].keysym == keysym) {\n      keysym = keysymToAscii[i].ascii;\n      break;\n    }\n  }\n\n  if ((keysym >= 32 && keysym <= 126) ||\n      (keysym >= 160 && keysym <= 255))\n  {\n    // ordinary Latin-1 character\n\n    if (deadKeyAware) {\n      // Detect dead chars and generate the dead char followed by space so\n      // that we'll end up with the original char.\n      for (unsigned int i = 0; i < deadChars.size(); i++) {\n        if (keysym == deadChars[i]) {\n          SHORT dc = VkKeyScan(keysym);\n          if (dc != -1) {\n            if (down) {\n              vlog.info(\"Latin-1 dead key: 0x%x vkCode 0x%x mod 0x%x \"\n                        \"followed by space\", keysym, LOBYTE(dc), HIBYTE(dc));\n              doKeyEventWithModifiers(LOBYTE(dc), HIBYTE(dc), true);\n              doKeyEventWithModifiers(LOBYTE(dc), HIBYTE(dc), false);\n              doKeyEventWithModifiers(VK_SPACE, 0, true);\n              doKeyEventWithModifiers(VK_SPACE, 0, false);\n            }\n            return;\n          }\n        }\n      }\n    }\n\n    SHORT s = VkKeyScan(keysym);\n    if (s == -1) {\n      if (down) {\n        // not a single keypress - try synthesizing dead chars.\n        for (unsigned int j = 0;\n             j < sizeof(latin1ToDeadChars) / sizeof(latin1ToDeadChars_t);\n             j++) {\n          if (keysym == latin1ToDeadChars[j].latin1Char) {\n            for (unsigned int i = 0; i < deadChars.size(); i++) {\n              if (deadChars[i] == latin1ToDeadChars[j].deadChar) {\n                SHORT dc = VkKeyScan(latin1ToDeadChars[j].deadChar);\n                SHORT bc = VkKeyScan(latin1ToDeadChars[j].baseChar);\n                if (dc != -1 && bc != -1) {\n                  vlog.info(\"Latin-1 key: 0x%x dead key vkCode 0x%x mod 0x%x \"\n                            \"followed by vkCode 0x%x mod 0x%x\",\n                            keysym, LOBYTE(dc), HIBYTE(dc),\n                            LOBYTE(bc), HIBYTE(bc));\n                  doKeyEventWithModifiers(LOBYTE(dc), HIBYTE(dc), true);\n                  doKeyEventWithModifiers(LOBYTE(dc), HIBYTE(dc), false);\n                  doKeyEventWithModifiers(LOBYTE(bc), HIBYTE(bc), true);\n                  doKeyEventWithModifiers(LOBYTE(bc), HIBYTE(bc), false);\n                  return;\n                }\n                break;\n              }\n            }\n            break;\n          }\n        }\n        vlog.info(\"Ignoring unrecognised Latin-1 keysym 0x%x\",keysym);\n      }\n      return;\n    }\n\n    BYTE vkCode = LOBYTE(s);\n    BYTE modifierState = HIBYTE(s);\n    vlog.debug(\"Latin-1 key: 0x%x vkCode 0x%x mod 0x%x down %d\",\n               keysym, vkCode, modifierState, down);\n    doKeyEventWithModifiers(vkCode, modifierState, down);\n\n  } else {\n\n    // see if it's a recognised keyboard key, otherwise ignore it\n\n    if (vkMap.find(keysym) == vkMap.end()) {\n      vlog.info(\"Ignoring unknown keysym 0x%x\",keysym);\n      return;\n    }\n    BYTE vkCode = vkMap[keysym];\n    DWORD flags = 0;\n    if (extendedMap[keysym]) flags |= KEYEVENTF_EXTENDEDKEY;\n    if (!down) flags |= KEYEVENTF_KEYUP;\n\n    vlog.debug(\"Keyboard key: keysym 0x%x vkCode 0x%x ext %d down %d\",\n               keysym, vkCode, extendedMap[keysym], down);\n    if (down && (vkCode == VK_DELETE) &&\n        ((GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0) &&\n        ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0))\n    {\n      rfb::win32::emulateCtrlAltDel();\n      return;\n    }\n\n    doKeyboardEvent(vkCode, flags);\n  }\n}\n"
  },
  {
    "path": "win/rfb_win32/SInput.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Input.h\n//\n// A number of routines that accept VNC-style input event data and perform\n// the appropriate actions under Win32\n\n#ifndef __RFB_WIN32_INPUT_H__\n#define __RFB_WIN32_INPUT_H__\n\n#include <core/Configuration.h>\n#include <core/Rect.h>\n\n#include <map>\n#include <vector>\n\n#include <stdint.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    // -=- Pointer event handling\n\n    class SPointer {\n    public:\n      SPointer();\n      // - Create a pointer event at a the given coordinates, with the\n      //   specified button state.  The event must be specified using\n      //   Screen coordinates.\n      void pointerEvent(const core::Point& pos, uint16_t buttonmask);\n    protected:\n      core::Point last_position;\n      uint16_t last_buttonmask;\n    };\n\n    // -=- Keyboard event handling\n\n    class SKeyboard {\n    public:\n      SKeyboard();\n      void keyEvent(uint32_t keysym, uint32_t keycode, bool down);\n      static core::BoolParameter deadKeyAware;\n      static core::BoolParameter rawKeyboard;\n    private:\n      std::map<uint32_t,uint8_t> vkMap;\n      std::map<uint32_t,bool> extendedMap;\n      std::vector<uint8_t> deadChars;\n    };\n\n  }; // win32\n\n}; // rfb\n\n#endif // __RFB_WIN32_INPUT_H__\n"
  },
  {
    "path": "win/rfb_win32/Security.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Security.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/Security.h>\n\n#include <lmcons.h>\n#include <accctrl.h>\n#include <list>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"SecurityWin32\");\n\n\nTrustee::Trustee(const char* name,\n                 TRUSTEE_FORM form,\n                 TRUSTEE_TYPE type) {\n  pMultipleTrustee = nullptr;\n  MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;\n  TrusteeForm = form;\n  TrusteeType = type;\n  ptstrName = (char*)name;\n}\n\n\nExplicitAccess::ExplicitAccess(const char* name,\n                               TRUSTEE_FORM type,\n                               DWORD perms,\n                               ACCESS_MODE mode,\n                               DWORD inherit) {\n  Trustee = rfb::win32::Trustee(name, type);\n  grfAccessPermissions = perms;\n  grfAccessMode = mode;\n  grfInheritance = inherit;\n}\n\n\nAccessEntries::AccessEntries() : entries(nullptr), entry_count(0) {}\n\nAccessEntries::~AccessEntries() {\n  delete [] entries;\n}\n\nvoid AccessEntries::allocMinEntries(int count) {\n  if (count > entry_count) {\n    EXPLICIT_ACCESS* new_entries = new EXPLICIT_ACCESS[entry_count+1];\n    if (entries) {\n      memcpy(new_entries, entries, sizeof(EXPLICIT_ACCESS) * entry_count);\n      delete entries;\n    }\n    entries = new_entries;\n  }\n}\n\nvoid AccessEntries::addEntry(const char* trusteeName,\n                             DWORD permissions,\n                             ACCESS_MODE mode) {\n  allocMinEntries(entry_count+1);\n  ZeroMemory(&entries[entry_count], sizeof(EXPLICIT_ACCESS));\n  entries[entry_count] = ExplicitAccess(trusteeName, TRUSTEE_IS_NAME, permissions, mode);\n  entry_count++;\n}\n\nvoid AccessEntries::addEntry(const PSID sid,\n                             DWORD permissions,\n                             ACCESS_MODE mode) {\n  allocMinEntries(entry_count+1);\n  ZeroMemory(&entries[entry_count], sizeof(EXPLICIT_ACCESS));\n  entries[entry_count] = ExplicitAccess((char*)sid, TRUSTEE_IS_SID, permissions, mode);\n  entry_count++;\n}\n\n\nPSID Sid::copySID(const PSID sid) {\n  if (!IsValidSid(sid))\n    throw std::invalid_argument(\"Invalid SID in copyPSID\");\n  PSID buf = (PSID)new uint8_t[GetLengthSid(sid)];\n  if (!CopySid(GetLengthSid(sid), buf, sid))\n    throw core::win32_error(\"CopySid failed\", GetLastError());\n  return buf;\n}\n\nvoid Sid::setSID(const PSID sid) {\n  if (!IsValidSid(sid))\n    throw std::invalid_argument(\"Invalid SID in copyPSID\");\n  resize(GetLengthSid(sid));\n  if (!CopySid(GetLengthSid(sid), data(), sid))\n    throw core::win32_error(\"CopySid failed\", GetLastError());\n}\n\nvoid Sid::getUserNameAndDomain(char** name, char** domain) {\n  DWORD nameLen = 0;\n  DWORD domainLen = 0;\n  SID_NAME_USE use;\n  LookupAccountSid(nullptr, (PSID)*this, nullptr, &nameLen, nullptr, &domainLen, &use);\n  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)\n    throw core::win32_error(\"Unable to determine SID name lengths\", GetLastError());\n  vlog.info(\"nameLen=%lu, domainLen=%lu, use=%d\", nameLen, domainLen, use);\n  *name = new char[nameLen];\n  *domain = new char[domainLen];\n  if (!LookupAccountSid(nullptr, (PSID)*this, *name, &nameLen, *domain, &domainLen, &use))\n    throw core::win32_error(\"Unable to lookup account SID\", GetLastError());\n}\n\n\nSid::Administrators::Administrators() {\n  PSID sid = nullptr;\n  SID_IDENTIFIER_AUTHORITY ntAuth = { SECURITY_NT_AUTHORITY };\n  if (!AllocateAndInitializeSid(&ntAuth, 2,\n                                SECURITY_BUILTIN_DOMAIN_RID,\n                                DOMAIN_ALIAS_RID_ADMINS,\n                                0, 0, 0, 0, 0, 0, &sid)) \n    throw core::win32_error(\"Sid::Administrators\", GetLastError());\n  setSID(sid);\n  FreeSid(sid);\n}\n\nSid::SYSTEM::SYSTEM() {\n  PSID sid = nullptr;\n  SID_IDENTIFIER_AUTHORITY ntAuth = { SECURITY_NT_AUTHORITY };\n  if (!AllocateAndInitializeSid(&ntAuth, 1,\n                                SECURITY_LOCAL_SYSTEM_RID,\n                                0, 0, 0, 0, 0, 0, 0, &sid))\n          throw core::win32_error(\"Sid::SYSTEM\", GetLastError());\n  setSID(sid);\n  FreeSid(sid);\n}\n\nSid::FromToken::FromToken(HANDLE h) {\n  DWORD required = 0;\n  GetTokenInformation(h, TokenUser, nullptr, 0, &required);\n  std::vector<uint8_t> tmp(required);\n  if (!GetTokenInformation(h, TokenUser, tmp.data(), tmp.size(), &required))\n    throw core::win32_error(\"GetTokenInformation\", GetLastError());\n  TOKEN_USER* tokenUser = (TOKEN_USER*)tmp.data();\n  setSID(tokenUser->User.Sid);\n}\n\n\nPACL rfb::win32::CreateACL(const AccessEntries& ae, PACL existing_acl) {\n  PACL new_dacl;\n  DWORD result;\n  if ((result = SetEntriesInAcl(ae.entry_count, ae.entries, existing_acl, &new_dacl)) != ERROR_SUCCESS)\n    throw core::win32_error(\"SetEntriesInAcl\", result);\n  return new_dacl;\n}\n\n\nPSECURITY_DESCRIPTOR rfb::win32::CreateSdWithDacl(const PACL dacl) {\n  SECURITY_DESCRIPTOR absSD;\n  if (!InitializeSecurityDescriptor(&absSD, SECURITY_DESCRIPTOR_REVISION))\n    throw core::win32_error(\"InitializeSecurityDescriptor\", GetLastError());\n  Sid::SYSTEM owner;\n  if (!SetSecurityDescriptorOwner(&absSD, owner, FALSE))\n    throw core::win32_error(\"SetSecurityDescriptorOwner\", GetLastError());\n  Sid::Administrators group;\n  if (!SetSecurityDescriptorGroup(&absSD, group, FALSE))\n    throw core::win32_error(\"SetSecurityDescriptorGroupp\", GetLastError());\n  if (!SetSecurityDescriptorDacl(&absSD, TRUE, dacl, FALSE))\n    throw core::win32_error(\"SetSecurityDescriptorDacl\", GetLastError());\n  DWORD sdSize = GetSecurityDescriptorLength(&absSD);\n  SecurityDescriptorPtr sd(sdSize);\n  if (!MakeSelfRelativeSD(&absSD, (PSECURITY_DESCRIPTOR)sd.ptr, &sdSize))\n    throw core::win32_error(\"MakeSelfRelativeSD\", GetLastError());\n  return sd.takeSD();\n}\n"
  },
  {
    "path": "win/rfb_win32/Security.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// Security.h\n\n// Wrapper classes for a few Windows NT security structures/functions\n// that are used by VNC\n\n#ifndef __RFB_WIN32_SECURITY_H__\n#define __RFB_WIN32_SECURITY_H__\n\n#include <stdint.h>\n#include <vector>\n#include <rfb_win32/LocalMem.h>\n#include <aclapi.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    struct Trustee : public TRUSTEE {\n      Trustee(const char* name,\n              TRUSTEE_FORM form=TRUSTEE_IS_NAME,\n              TRUSTEE_TYPE type=TRUSTEE_IS_UNKNOWN);\n    };\n\n    struct ExplicitAccess : public EXPLICIT_ACCESS {\n      ExplicitAccess(const char* name,\n                     TRUSTEE_FORM type,\n                     DWORD perms,\n                     ACCESS_MODE mode,\n                     DWORD inherit=0);\n    };\n\n    // Helper class for building access control lists\n    struct AccessEntries {\n      AccessEntries();\n      ~AccessEntries();\n      void allocMinEntries(int count);\n      void addEntry(const char* trusteeName,\n                    DWORD permissions,\n                    ACCESS_MODE mode);\n      void addEntry(const PSID sid,\n                    DWORD permissions,\n                    ACCESS_MODE mode);\n\n      EXPLICIT_ACCESS* entries;\n      int entry_count;\n    };\n\n    // Helper class for handling SIDs\n    struct Sid : std::vector<uint8_t> {\n      Sid() {}\n      operator PSID() const {return (PSID)data();}\n\n      static PSID copySID(const PSID sid);\n\n      void setSID(const PSID sid);\n\n      void getUserNameAndDomain(char** name, char** domain);\n\n      struct Administrators;\n      struct SYSTEM;\n      struct FromToken;\n\n    private:\n      Sid(const Sid&);\n      Sid& operator=(const Sid&);\n    };\n      \n    struct Sid::Administrators : public Sid {\n      Administrators();\n    };\n    struct Sid::SYSTEM : public Sid {\n      SYSTEM();\n    };\n    struct Sid::FromToken : public Sid {\n      FromToken(HANDLE h);\n    };\n\n    // Helper class for handling & freeing ACLs\n    struct AccessControlList : public LocalMem {\n      AccessControlList(int size) : LocalMem(size) {}\n      AccessControlList(PACL acl_=nullptr) : LocalMem(acl_) {}\n      operator PACL() {return (PACL)ptr;}\n    };\n\n    // Create a new ACL based on supplied entries and, if supplied, existing ACL \n    PACL CreateACL(const AccessEntries& ae, PACL existing_acl=nullptr);\n\n    // Helper class for memory-management of self-relative SecurityDescriptors\n    struct SecurityDescriptorPtr : LocalMem {\n      SecurityDescriptorPtr(int size) : LocalMem(size) {}\n      SecurityDescriptorPtr(PSECURITY_DESCRIPTOR sd_=nullptr) : LocalMem(sd_) {}\n      PSECURITY_DESCRIPTOR takeSD() {return (PSECURITY_DESCRIPTOR)takePtr();}\n    };\n\n    // Create a new self-relative Security Descriptor, owned by SYSTEM/Administrators,\n    //   with the supplied DACL and no SACL.  The returned value can be assigned\n    //   to a SecurityDescriptorPtr to be managed.\n    PSECURITY_DESCRIPTOR CreateSdWithDacl(const PACL dacl);\n\n  }\n\n}\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/SecurityPage.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <rfb/Security.h>\n\n#include <rfb_win32/resource.h>\n#include <rfb_win32/SecurityPage.h>\n\n#include <list>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\nusing namespace std;\n\nstatic LogWriter vlog(\"AuthDialog\");\n\n/* XXX: This class contains bunch of similar code to unix/vncviewer/CConn.cxx */\nSecurityPage::SecurityPage(Security *security_)\n  : PropSheetPage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDD_SECURITY)),\n    security(security_) {\n}\n\nvoid\nSecurityPage::initDialog()\n{\n  list<uint8_t> secTypes;\n\n  if (isItemChecked(IDC_ENC_X509))\n    enableX509Dialogs();\n  else\n    disableX509Dialogs();\n\n  secTypes = security->GetEnabledSecTypes();\n\n  /* Process non-VeNCrypt sectypes */\n  for (uint8_t type : secTypes) {\n    switch (type) {\n    case secTypeNone:\n      enableAuthMethod(IDC_ENC_NONE, IDC_AUTH_NONE);\n      break;\n    case secTypeVncAuth:\n      enableAuthMethod(IDC_ENC_NONE, IDC_AUTH_VNC);\n      break;\n    }\n  }\n\n  list<uint32_t> secTypesExt;\n\n  secTypesExt = security->GetEnabledExtSecTypes();\n\n  /* Process VeNCrypt subtypes */\n  for (uint32_t type : secTypesExt) {\n    switch (type) {\n    case secTypePlain:\n      enableAuthMethod(IDC_ENC_NONE, IDC_AUTH_PLAIN);\n      break;\n    case secTypeTLSNone:\n      enableAuthMethod(IDC_ENC_TLS, IDC_AUTH_NONE);\n      break;\n    case secTypeTLSVnc:\n      enableAuthMethod(IDC_ENC_TLS, IDC_AUTH_VNC);\n      break;\n    case secTypeTLSPlain:\n      enableAuthMethod(IDC_ENC_TLS, IDC_AUTH_PLAIN);\n      break;\n    case secTypeX509None:\n      enableAuthMethod(IDC_ENC_X509, IDC_AUTH_NONE);\n      enableX509Dialogs();\n      break;\n    case secTypeX509Vnc:\n      enableAuthMethod(IDC_ENC_X509, IDC_AUTH_VNC);\n      enableX509Dialogs();\n      break;\n    case secTypeX509Plain:\n      enableAuthMethod(IDC_ENC_X509, IDC_AUTH_PLAIN);\n      enableX509Dialogs();\n      break;\n    }\n  }\n}\n\nbool\nSecurityPage::onCommand(int id, int /*cmd*/)\n{\n  if (id == IDC_ENC_X509) {\n    if (isItemChecked(IDC_ENC_X509))\n      enableX509Dialogs();\n    else\n      disableX509Dialogs();\n  }\n\n  return true;\n}\n\nbool\nSecurityPage::onOk() {\n#ifdef HAVE_GNUTLS\n  bool x509_loaded = false;\n#endif\n  bool vnc_loaded = false;\n  list<uint32_t> secTypes;\n\n#ifdef HAVE_GNUTLS\n  /* X509Plain */\n  if (authMethodEnabled(IDC_ENC_X509, IDC_AUTH_PLAIN)) {\n    loadX509Certs(x509_loaded);\n    secTypes.push_back(secTypeX509Plain);\n  }\n\n  /* TLSPlain */\n  if (authMethodEnabled(IDC_ENC_TLS, IDC_AUTH_PLAIN))\n    secTypes.push_back(secTypeTLSPlain);\n\n  /* X509Vnc */\n  if (authMethodEnabled(IDC_ENC_X509, IDC_AUTH_VNC)) {\n    loadX509Certs(x509_loaded);\n    loadVncPasswd(vnc_loaded);\n    secTypes.push_back(secTypeX509Vnc);\n  }\n\n  /* TLSVnc */\n  if (authMethodEnabled(IDC_ENC_TLS, IDC_AUTH_VNC)) {\n    loadVncPasswd(vnc_loaded);\n    secTypes.push_back(secTypeTLSVnc);\n  }\n\n  /* X509None */\n  if (authMethodEnabled(IDC_ENC_X509, IDC_AUTH_NONE)) {\n    loadX509Certs(x509_loaded);\n    secTypes.push_back(secTypeX509None);\n  }\n\n  /* TLSNone */\n  if (authMethodEnabled(IDC_ENC_TLS, IDC_AUTH_NONE))\n    secTypes.push_back(secTypeTLSNone);\n#endif\n\n  /* VncAuth */\n  if (authMethodEnabled(IDC_ENC_NONE, IDC_AUTH_VNC)) {\n    loadVncPasswd(vnc_loaded);\n    secTypes.push_back(secTypeVncAuth);\n  }\n\n  /* None */\n  if (authMethodEnabled(IDC_ENC_NONE, IDC_AUTH_NONE))\n    secTypes.push_back(secTypeNone);\n\n  security->SetSecTypes(secTypes);\n\n  return true;\n}\n\ninline void\nSecurityPage::disableFeature(int id)\n{\n  enableItem(id, false);\n  setItemChecked(id, false);\n}\n\ninline void\nSecurityPage::enableAuthMethod(int encid, int authid)\n{\n  setItemChecked(encid, true);\n  setItemChecked(authid, true);\n}\n\ninline bool\nSecurityPage::authMethodEnabled(int encid, int authid)\n{\n  return isItemChecked(encid) && isItemChecked(authid);\n}\n\ninline void\nSecurityPage::loadX509Certs(bool &loaded)\n{\n  if (!loaded)\n    loadX509Certs();\n  loaded = true;\n}\n\ninline void\nSecurityPage::loadVncPasswd(bool &loaded)\n{\n  if (!loaded)\n    loadVncPasswd();\n  loaded = true;\n}\n\n"
  },
  {
    "path": "win/rfb_win32/SecurityPage.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * Copyright (C) 2011 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __RFB_WIN32_SECURITYPAGE_H__\n#define __RFB_WIN32_SECURITYPAGE_H__\n\n\n#include <rfb/Security.h>\n#include <rfb_win32/Dialog.h>\n\n#include <list>\n\nnamespace rfb {\nnamespace win32 {\n\nclass SecurityPage: public PropSheetPage\n{\npublic:\n  SecurityPage(Security *security_);\n\n  virtual void loadX509Certs(void) = 0;\n  virtual void enableX509Dialogs(void) = 0;\n  virtual void disableX509Dialogs(void) = 0;\n  virtual void loadVncPasswd(void) = 0;\n\n  void initDialog() override;\n  bool onCommand(int id, int cmd) override;\n  bool onOk() override;\n\nprotected:\n  Security *security;\n\nprivate:\n  inline void enableVeNCryptFeatures(bool enable);\n  inline void disableFeature(int id);\n  inline void enableAuthMethod(int encid, int authid);\n  inline bool authMethodEnabled(int encid, int authid);\n  inline void loadX509Certs(bool &loaded);\n  inline void loadVncPasswd(bool &loaded);\n};\n    \n};\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/Service.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Service.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb_win32/Service.h>\n#include <rfb_win32/MsgWindow.h>\n#include <rfb_win32/ModuleFileName.h>\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/Handle.h>\n\n#include <logmessages/messages.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\n\nstatic LogWriter vlog(\"Service\");\n\n\n// - Internal service implementation functions\n\nService* service = nullptr;\nbool runAsService = false;\n\nVOID WINAPI serviceHandler(DWORD control) {\n  switch (control) {\n  case SERVICE_CONTROL_INTERROGATE:\n    vlog.info(\"CMD: Report status\");\n    service->setStatus();\n    return;\n  case SERVICE_CONTROL_PARAMCHANGE:\n    vlog.info(\"CMD: Param change\");\n    service->readParams();\n    return;\n  case SERVICE_CONTROL_SHUTDOWN:\n    vlog.info(\"CMD: OS shutdown\");\n    service->osShuttingDown();\n    return;\n  case SERVICE_CONTROL_STOP:\n    vlog.info(\"CMD: Stop\");\n    service->setStatus(SERVICE_STOP_PENDING);\n    service->stop();\n    return;\n  };\n  vlog.debug(\"CMD: Unknown %lu\", control);\n}\n\n\n// -=- Service main procedure\n\nVOID WINAPI serviceProc(DWORD dwArgc, LPTSTR* lpszArgv) {\n  vlog.debug(\"Entering %s serviceProc\", service->getName());\n  vlog.info(\"Registering handler...\");\n  service->status_handle = RegisterServiceCtrlHandler(service->getName(), serviceHandler);\n  if (!service->status_handle) {\n    DWORD err = GetLastError();\n    vlog.error(\"Failed to register handler: %lu\", err);\n    ExitProcess(err);\n  }\n  vlog.debug(\"Registered handler (%p)\", service->status_handle);\n  service->setStatus(SERVICE_START_PENDING);\n  vlog.debug(\"Entering %s serviceMain\", service->getName());\n  service->status.dwWin32ExitCode = service->serviceMain(dwArgc, lpszArgv);\n  vlog.debug(\"Leaving %s serviceMain\", service->getName());\n  service->setStatus(SERVICE_STOPPED);\n}\n\n\n// -=- Service\n\nService::Service(const char* name_) : name(name_) {\n  vlog.debug(\"Service\");\n  status_handle = nullptr;\n  status.dwControlsAccepted = SERVICE_CONTROL_INTERROGATE | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;\n  status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;\n  status.dwWin32ExitCode = NO_ERROR;\n  status.dwServiceSpecificExitCode = 0;\n  status.dwCheckPoint = 0;\n  status.dwWaitHint = 30000;\n  status.dwCurrentState = SERVICE_STOPPED;\n}\n\nvoid\nService::start() {\n  SERVICE_TABLE_ENTRY entry[2];\n  entry[0].lpServiceName = (char*)name;\n  entry[0].lpServiceProc = serviceProc;\n  entry[1].lpServiceName = nullptr;\n  entry[1].lpServiceProc = nullptr;\n  vlog.debug(\"Entering dispatcher\");\n  if (!SetProcessShutdownParameters(0x100, 0))\n    vlog.error(\"Unable to set shutdown parameters: %lu\", GetLastError());\n  service = this;\n  if (!StartServiceCtrlDispatcher(entry))\n    throw win32_error(\"Unable to start service\", GetLastError());\n}\n\nvoid\nService::setStatus() {\n  setStatus(status.dwCurrentState);\n}\n\nvoid\nService::setStatus(DWORD state) {\n  if (status_handle == nullptr) {\n    vlog.debug(\"Warning: Cannot setStatus\");\n    return;\n  }\n  status.dwCurrentState = state;\n  status.dwCheckPoint++;\n  if (!SetServiceStatus(status_handle, &status)) {\n    status.dwCurrentState = SERVICE_STOPPED;\n    status.dwWin32ExitCode = GetLastError();\n    vlog.error(\"Unable to set service status:%lu\", status.dwWin32ExitCode);\n  }\n  vlog.debug(\"Set status to %lu(%lu)\", state, status.dwCheckPoint);\n}\n\nService::~Service() {\n  vlog.debug(\"~Service\");\n  service = nullptr;\n}\n\n\n// Find out whether this process is running as the WinVNC service\nbool thisIsService() {\n  return service && (service->status.dwCurrentState != SERVICE_STOPPED);\n}\n\n\n// -=- Desktop handling code\n\n// Switch the current thread to the specified desktop\nstatic bool\nswitchToDesktop(HDESK desktop) {\n  HDESK old_desktop = GetThreadDesktop(GetCurrentThreadId());\n  if (!SetThreadDesktop(desktop)) {\n    vlog.debug(\"switchToDesktop failed:%lu\", GetLastError());\n    return false;\n  }\n  if (!CloseDesktop(old_desktop))\n    vlog.debug(\"Unable to close old desktop:%lu\", GetLastError());\n  return true;\n}\n\n// Determine whether the thread's current desktop is the input one\nstatic bool\ninputDesktopSelected() {\n  HDESK current = GetThreadDesktop(GetCurrentThreadId());\n\tHDESK input = OpenInputDesktop(0, FALSE,\n  \tDESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |\n\t\tDESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |\n\t\tDESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |\n\t\tDESKTOP_SWITCHDESKTOP | GENERIC_WRITE);\n  if (!input) {\n    vlog.debug(\"Unable to OpenInputDesktop(1):%lu\", GetLastError());\n    return false;\n  }\n\n  DWORD size;\n  char currentname[256];\n  char inputname[256];\n\n  if (!GetUserObjectInformation(current, UOI_NAME, currentname, 256, &size)) {\n    vlog.debug(\"Unable to GetUserObjectInformation(1):%lu\", GetLastError());\n    CloseDesktop(input);\n    return false;\n  }\n  if (!GetUserObjectInformation(input, UOI_NAME, inputname, 256, &size)) {\n    vlog.debug(\"Unable to GetUserObjectInformation(2):%lu\", GetLastError());\n    CloseDesktop(input);\n    return false;\n  }\n  if (!CloseDesktop(input))\n    vlog.debug(\"Unable to close input desktop:%lu\", GetLastError());\n\n  // *** vlog.debug(\"current=%s, input=%s\", currentname, inputname);\n  bool result = strcmp(currentname, inputname) == 0;\n  return result;\n}\n\n// Switch the current thread into the input desktop\nstatic bool\nselectInputDesktop() {\n  // - Open the input desktop\n  HDESK desktop = OpenInputDesktop(0, FALSE,\n\t\tDESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |\n\t\tDESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |\n\t\tDESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |\n\t\tDESKTOP_SWITCHDESKTOP | GENERIC_WRITE);\n  if (!desktop) {\n    vlog.debug(\"Unable to OpenInputDesktop(2):%lu\", GetLastError());\n    return false;\n  }\n\n  // - Switch into it\n  if (!switchToDesktop(desktop)) {\n    CloseDesktop(desktop);\n    return false;\n  }\n\n  // ***\n  DWORD size = 256;\n  char currentname[256];\n  if (GetUserObjectInformation(desktop, UOI_NAME, currentname, 256, &size)) {\n    vlog.debug(\"Switched to %s\", currentname);\n  }\n  // ***\n\n  vlog.debug(\"Switched to input desktop\");\n\n  return true;\n}\n\n\n// -=- Access points to desktop-switching routines\n\nbool\nrfb::win32::desktopChangeRequired() {\n  return !inputDesktopSelected();\n}\n\nbool\nrfb::win32::changeDesktop() {\n  return selectInputDesktop();\n}\n\n\n// -=- Ctrl-Alt-Del emulation\n\nbool\nrfb::win32::emulateCtrlAltDel() {\n  rfb::win32::Handle sessionEventCad = \n    CreateEvent(nullptr, FALSE, FALSE, \"Global\\\\SessionEventTigerVNCCad\");\n  SetEvent(sessionEventCad);\n  return true;\n}\n\n\n// -=- Application Event Log target Logger class\n\nclass Logger_EventLog : public Logger {\npublic:\n  Logger_EventLog(const char* srcname) : Logger(\"EventLog\") {\n    eventlog = RegisterEventSource(nullptr, srcname);\n    if (!eventlog)\n      printf(\"Unable to open event log:%ld\\n\", GetLastError());\n  }\n  ~Logger_EventLog() {\n    if (eventlog)\n      DeregisterEventSource(eventlog);\n  }\n\n  void write(int level, const char *logname, const char *message) override {\n    if (!eventlog) return;\n    const char* strings[] = {logname, message};\n    WORD type = EVENTLOG_INFORMATION_TYPE;\n    if (level == 0) type = EVENTLOG_ERROR_TYPE;\n    if (!ReportEvent(eventlog, type, 0, VNC4LogMessage, nullptr, 2, 0, strings, nullptr)) {\n      // *** It's not at all clear what is the correct behaviour if this fails...\n      printf(\"ReportEvent failed:%ld\\n\", GetLastError());\n    }\n  }\n\nprotected:\n  HANDLE eventlog;\n};\n\nstatic Logger_EventLog* logger = nullptr;\n\nbool rfb::win32::initEventLogLogger(const char* srcname) {\n  if (logger)\n    return false;\n  logger = new Logger_EventLog(srcname);\n  logger->registerLogger();\n  return true;\n}\n\n\n// -=- Registering and unregistering the service\n\nbool rfb::win32::registerService(const char* name,\n                                 const char* display,\n                                 const char* desc,\n                                 int argc, char** argv) {\n  int i;\n\n  // - Initialise the default service parameters\n  const char* defaultcmdline;\n  defaultcmdline = \"-service\";\n\n  // - Get the full pathname of our executable\n  ModuleFileName buffer;\n\n  // - Add the supplied extra parameters to the command line\n  std::string cmdline;\n  cmdline = format(\"\\\"%s\\\" %s\", buffer.buf, defaultcmdline);\n  for (i=0; i<argc; i++) {\n    cmdline += \" \\\"\";\n    cmdline += argv[i];\n    cmdline += \"\\\"\";\n  }\n    \n  // - Register the service\n\n  // - Open the SCM\n  ServiceHandle scm = OpenSCManager(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE);\n  if (!scm)\n    throw core::win32_error(\"Unable to open Service Control Manager\", GetLastError());\n\n  // - Add the service\n  ServiceHandle handle = CreateService(scm,\n    name, display, SC_MANAGER_ALL_ACCESS,\n    SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,\n    SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,\n    cmdline.c_str(), nullptr, nullptr, nullptr, nullptr, nullptr);\n  if (!handle)\n    throw core::win32_error(\"Unable to create service\", GetLastError());\n\n  // - Set a description\n  SERVICE_DESCRIPTION sdesc = {(LPTSTR)desc};\n  ChangeServiceConfig2(handle, SERVICE_CONFIG_DESCRIPTION, &sdesc);\n\n  // - Register the event log source\n  RegKey hk, hk2;\n\n  hk2.createKey(HKEY_LOCAL_MACHINE, \"SYSTEM\\\\CurrentControlSet\\\\Services\\\\EventLog\\\\Application\");\n  hk.createKey(hk2, name);\n\n  for (i=strlen(buffer.buf); i>0; i--) {\n    if (buffer.buf[i] == '\\\\') {\n      buffer.buf[i+1] = 0;\n      break;\n    }\n  }\n\n  const char* dllFilename = \"logmessages.dll\";\n  std::string dllPath;\n  dllPath = buffer.buf;\n  dllPath += dllFilename;\n\n  hk.setExpandString(\"EventMessageFile\", dllPath.c_str());\n  hk.setInt(\"TypesSupported\", EVENTLOG_ERROR_TYPE | EVENTLOG_INFORMATION_TYPE);\n\n  Sleep(500);\n\n  return true;\n}\n\nbool rfb::win32::unregisterService(const char* name) {\n  // - Open the SCM\n  ServiceHandle scm = OpenSCManager(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE);\n  if (!scm)\n    throw core::win32_error(\"Unable to open Service Control Manager\", GetLastError());\n\n  // - Create the service\n  ServiceHandle handle = OpenService(scm, name, SC_MANAGER_ALL_ACCESS);\n  if (!handle)\n    throw core::win32_error(\"Unable to locate the service\", GetLastError());\n  if (!DeleteService(handle))\n    throw core::win32_error(\"Unable to remove the service\", GetLastError());\n\n  // - Register the event log source\n  RegKey hk;\n  hk.openKey(HKEY_LOCAL_MACHINE, \"SYSTEM\\\\CurrentControlSet\\\\Services\\\\EventLog\\\\Application\");\n  hk.deleteKey(name);\n\n  Sleep(500);\n\n  return true;\n}\n\n\n// -=- Starting and stopping the service\n\nbool rfb::win32::startService(const char* name) {\n\n  // - Open the SCM\n  ServiceHandle scm = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT);\n  if (!scm)\n    throw core::win32_error(\"Unable to open Service Control Manager\", GetLastError());\n\n  // - Locate the service\n  ServiceHandle handle = OpenService(scm, name, SERVICE_START);\n  if (!handle)\n    throw core::win32_error(\"Unable to open the service\", GetLastError());\n\n  // - Start the service\n  if (!StartService(handle, 0, nullptr))\n    throw core::win32_error(\"Unable to start the service\", GetLastError());\n\n  Sleep(500);\n\n  return true;\n}\n\nbool rfb::win32::stopService(const char* name) {\n  // - Open the SCM\n  ServiceHandle scm = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT);\n  if (!scm)\n    throw core::win32_error(\"Unable to open Service Control Manager\", GetLastError());\n\n  // - Locate the service\n  ServiceHandle handle = OpenService(scm, name, SERVICE_STOP);\n  if (!handle)\n    throw core::win32_error(\"Unable to open the service\", GetLastError());\n\n  // - Start the service\n  SERVICE_STATUS status;\n  if (!ControlService(handle, SERVICE_CONTROL_STOP, &status))\n    throw core::win32_error(\"Unable to stop the service\", GetLastError());\n\n  Sleep(500);\n\n  return true;\n}\n\nDWORD rfb::win32::getServiceState(const char* name) {\n  // - Open the SCM\n  ServiceHandle scm = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT);\n  if (!scm)\n    throw core::win32_error(\"Unable to open Service Control Manager\", GetLastError());\n\n  // - Locate the service\n  ServiceHandle handle = OpenService(scm, name, SERVICE_INTERROGATE);\n  if (!handle)\n    throw core::win32_error(\"Unable to open the service\", GetLastError());\n\n  // - Get the service status\n  SERVICE_STATUS status;\n  if (!ControlService(handle, SERVICE_CONTROL_INTERROGATE, (SERVICE_STATUS*)&status))\n    throw core::win32_error(\"Unable to query the service\", GetLastError());\n\n  return status.dwCurrentState;\n}\n\nconst char* rfb::win32::serviceStateName(DWORD state) {\n  switch (state) {\n  case SERVICE_RUNNING: return \"Running\";\n  case SERVICE_STOPPED: return \"Stopped\";\n  case SERVICE_STOP_PENDING: return \"Stopping\";\n  };\n  static char tmp[32];\n  sprintf(tmp, \"Unknown (%lu)\", state);\n  return tmp;\n}\n\n\nbool rfb::win32::isServiceProcess() {\n  return runAsService;\n}\n"
  },
  {
    "path": "win/rfb_win32/Service.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Service.h\n//\n// Win32 service-mode code.\n// Derive your service from this code and let it handle the annoying Win32\n// service API.\n\n#ifndef __RFB_WIN32_SERVICE_H__\n#define __RFB_WIN32_SERVICE_H__\n\n#include <windows.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    //\n    // -=- Service\n    //\n\n    // Application base-class for services.\n\n    class Service {\n    public:\n\n      Service(const char* name_);\n      virtual ~Service();\n\n      const char* getName() {return name;}\n      SERVICE_STATUS& getStatus() {return status;}\n\n      void setStatus(DWORD status);\n      void setStatus();\n\n      // - Start the service, having initialised it\n      void start();\n\n      // - Service main procedure - override to implement a service\n      virtual DWORD serviceMain(int argc, char* argv[]) = 0;\n\n      // - Service control notifications\n\n      // To get notified when the OS is shutting down\n      virtual void osShuttingDown() {};\n\n      // To get notified when the service parameters change\n      virtual void readParams() {};\n\n      // To cause the serviceMain() routine to return\n      virtual void stop() {};\n\n    public:\n      SERVICE_STATUS_HANDLE status_handle;\n      SERVICE_STATUS status;\n    protected:\n      const char* name;\n    };\n\n    class ServiceHandle {\n    public:\n      ServiceHandle(SC_HANDLE h) : handle(h) {}\n      ~ServiceHandle() {CloseServiceHandle(handle);}\n      operator SC_HANDLE() const {return handle;}\n    protected:\n      SC_HANDLE handle;\n    };\n\n    // -=- Routines used by desktop back-end code to manage desktops/window stations\n\n    bool desktopChangeRequired();\n\n    bool changeDesktop();\n\n    // -=- Routines used by the SInput Keyboard class to emulate Ctrl-Alt-Del\n    bool emulateCtrlAltDel();\n\n    // -=- Routines to initialise the Event Log target Logger\n    bool initEventLogLogger(const char* srcname);\n\n    // -=- Routines to register/unregister the service\n    //     These routines also take care of registering the required\n    //     event source information, etc.\n    // *** should really accept char argv\n\n    bool registerService(const char* name, const char* display,\n                         const char* desc, int argc, char** argv);\n    bool unregisterService(const char* name);\n\n    bool startService(const char* name);\n    bool stopService(const char* name);\n\n    // -=- Get the state of the named service (one of the NT service state values)\n    DWORD getServiceState(const char* name);\n\n    // -=- Convert a supplied service state value to a printable string e.g. Running, Stopped...\n    const char* serviceStateName(DWORD state);\n\n    // -=- Routine to determine whether the host process is running a service\n    bool isServiceProcess();\n\n  };\n\n};\n\n#endif // __RFB_WIN32_SERVICE_NT_H__\n"
  },
  {
    "path": "win/rfb_win32/SocketManager.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- SocketManager.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <winsock2.h>\n#include <list>\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n#include <core/Timer.h>\n#include <core/time.h>\n\n#include <rdr/FdOutStream.h>\n\n#include <network/Socket.h>\n\n#include <rfb/VNCServer.h>\n#include <rfb_win32/SocketManager.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"SocketManager\");\n\n\n// -=- SocketManager\n\nSocketManager::SocketManager() {\n}\n\nSocketManager::~SocketManager() {\n}\n\n\nstatic void requestAddressChangeEvents(network::SocketListener* sock_) {\n  DWORD dummy = 0;\n  if (WSAIoctl(sock_->getFd(), SIO_ADDRESS_LIST_CHANGE, nullptr, 0, nullptr, 0, &dummy, nullptr, nullptr) == SOCKET_ERROR) {\n    DWORD err = WSAGetLastError();\n    if (err != WSAEWOULDBLOCK)\n      vlog.error(\"Unable to track address changes: 0x%08x\", (unsigned)err);\n  }\n}\n\n\nvoid SocketManager::addListener(network::SocketListener* sock_,\n                                VNCServer* srvr,\n                                AddressChangeNotifier* acn) {\n  WSAEVENT event = WSACreateEvent();\n  long flags = FD_ACCEPT | FD_CLOSE;\n  if (acn)\n    flags |= FD_ADDRESS_LIST_CHANGE;\n  try {\n    if (event && (WSAEventSelect(sock_->getFd(), event, flags) == SOCKET_ERROR))\n      throw core::socket_error(\"Unable to select on listener\", WSAGetLastError());\n\n    // requestAddressChangeEvents MUST happen after WSAEventSelect, so that the socket is non-blocking\n    if (acn)\n      requestAddressChangeEvents(sock_);\n\n    // addEvent is the last thing we do, so that the event is NOT registered if previous steps fail\n    if (!event || !addEvent(event, this))\n      throw std::runtime_error(\"Unable to add listener\");\n  } catch (std::exception& e) {\n    if (event)\n      WSACloseEvent(event);\n    delete sock_;\n    vlog.error(\"%s\", e.what());\n    throw;\n  }\n\n  ListenInfo li;\n  li.sock = sock_;\n  li.server = srvr;\n  li.notifier = acn;\n  li.disable = false;\n  listeners[event] = li;\n}\n\nvoid SocketManager::remListener(network::SocketListener* sock) {\n  std::map<HANDLE,ListenInfo>::iterator i;\n  for (i=listeners.begin(); i!=listeners.end(); i++) {\n    if (i->second.sock == sock) {\n      removeEvent(i->first);\n      WSACloseEvent(i->first);\n      delete sock;\n      listeners.erase(i);\n      return;\n    }\n  }\n  throw std::runtime_error(\"Listener not registered\");\n}\n\n\nvoid SocketManager::addSocket(network::Socket* sock_, VNCServer* srvr, bool outgoing) {\n  WSAEVENT event = WSACreateEvent();\n  if (!event || !addEvent(event, this) ||\n      (WSAEventSelect(sock_->getFd(), event, FD_READ | FD_CLOSE) == SOCKET_ERROR)) {\n    if (event)\n      WSACloseEvent(event);\n    delete sock_;\n    vlog.error(\"Unable to add connection\");\n    return;\n  }\n  if (!srvr->addSocket(sock_, outgoing)) {\n    removeEvent(event);\n    WSACloseEvent(event);\n    delete sock_;\n    return;\n  }\n  ConnInfo ci;\n  ci.sock = sock_;\n  ci.server = srvr;\n  connections[event] = ci;\n}\n\nvoid SocketManager::remSocket(network::Socket* sock_) {\n  std::map<HANDLE,ConnInfo>::iterator i;\n  for (i=connections.begin(); i!=connections.end(); i++) {\n    if (i->second.sock == sock_) {\n      i->second.server->removeSocket(sock_);\n      removeEvent(i->first);\n      WSACloseEvent(i->first);\n      delete sock_;\n      connections.erase(i);\n      return;\n    }\n  }\n  throw std::runtime_error(\"Socket not registered\");\n}\n\nbool SocketManager::getDisable(VNCServer* srvr)\n{\n  std::map<HANDLE,ListenInfo>::iterator i;\n  for (i=listeners.begin(); i!=listeners.end(); i++) {\n    if (i->second.server == srvr) {\n      return i->second.disable;\n    }\n  }\n  throw std::runtime_error(\"Listener not registered\");\n}\n\nvoid SocketManager::setDisable(VNCServer* srvr, bool disable)\n{\n  bool found = false;\n  std::map<HANDLE,ListenInfo>::iterator i;\n  for (i=listeners.begin(); i!=listeners.end(); i++) {\n    if (i->second.server == srvr) {\n      i->second.disable = disable;\n      // There might be multiple sockets for the same server, so\n      // continue iterating\n      found = true;\n    }\n  }\n  if (!found)\n    throw std::runtime_error(\"Listener not registered\");\n}\n\nint SocketManager::checkTimeouts() {\n  int timeout = EventManager::checkTimeouts();\n\n  int nextTimeout = Timer::checkTimeouts();\n  if (nextTimeout >= 0 && nextTimeout < timeout)\n    timeout = nextTimeout;\n\n  std::list<network::Socket*> shutdownSocks;\n  std::map<HANDLE,ConnInfo>::iterator j, j_next;\n  for (j=connections.begin(); j!=connections.end(); j=j_next) {\n    j_next = j; j_next++;\n    if (j->second.sock->isShutdownRead())\n      shutdownSocks.push_back(j->second.sock);\n    else {\n      long eventMask = FD_READ | FD_CLOSE;\n      if (j->second.sock->outStream().hasBufferedData())\n        eventMask |= FD_WRITE;\n      if (WSAEventSelect(j->second.sock->getFd(), j->first, eventMask) == SOCKET_ERROR)\n        throw core::socket_error(\"unable to adjust WSAEventSelect:%u\", WSAGetLastError());\n    }\n  }\n\n  std::list<network::Socket*>::iterator k;\n  for (k=shutdownSocks.begin(); k!=shutdownSocks.end(); k++)\n    remSocket(*k);\n\n  return timeout;\n}\n\n\nvoid SocketManager::processEvent(HANDLE event) {\n  if (listeners.count(event)) {\n    ListenInfo li = listeners[event];\n\n    // Accept an incoming connection\n    vlog.debug(\"Accepting incoming connection\");\n\n    // What kind of event is this?\n    WSANETWORKEVENTS network_events;\n    WSAEnumNetworkEvents(li.sock->getFd(), event, &network_events);\n    if (network_events.lNetworkEvents & FD_ACCEPT) {\n      network::Socket* new_sock = li.sock->accept();\n      if (new_sock && li.disable) {\n        delete new_sock;\n        new_sock = nullptr;\n      }\n      if (new_sock)\n        addSocket(new_sock, li.server, false);\n    } else if (network_events.lNetworkEvents & FD_CLOSE) {\n      vlog.info(\"Deleting listening socket\");\n      remListener(li.sock);\n    } else if (network_events.lNetworkEvents & FD_ADDRESS_LIST_CHANGE) {\n      li.notifier->processAddressChange();\n      requestAddressChangeEvents(li.sock);\n    } else {\n      vlog.error(\"Unknown listener event: %lx\", network_events.lNetworkEvents);\n    }\n  } else if (connections.count(event)) {\n    ConnInfo ci = connections[event];\n\n    try {\n      // Process data from an active connection\n\n      WSANETWORKEVENTS network_events;\n      long eventMask;\n\n      // Fetch why this event notification triggered\n      if (WSAEnumNetworkEvents(ci.sock->getFd(), event, &network_events) == SOCKET_ERROR)\n        throw core::socket_error(\"Unable to get WSAEnumNetworkEvents:%u\", WSAGetLastError());\n\n      // Cancel event notification for this socket\n      if (WSAEventSelect(ci.sock->getFd(), event, 0) == SOCKET_ERROR)\n        throw core::socket_error(\"unable to disable WSAEventSelect:%u\", WSAGetLastError());\n\n      // Reset the event object\n      WSAResetEvent(event);\n\n\n      // Call the socket server to process the event\n      if (network_events.lNetworkEvents & FD_WRITE) {\n        ci.server->processSocketWriteEvent(ci.sock);\n      }\n      if (network_events.lNetworkEvents & (FD_READ | FD_CLOSE)) {\n        ci.server->processSocketReadEvent(ci.sock);\n      }\n\n      // Re-instate the required socket event\n      // If the read event is still valid, the event object gets set here\n      eventMask = FD_READ | FD_CLOSE;\n      if (ci.sock->outStream().hasBufferedData())\n        eventMask |= FD_WRITE;\n      if (WSAEventSelect(ci.sock->getFd(), event, eventMask) == SOCKET_ERROR)\n        throw core::socket_error(\"unable to re-enable WSAEventSelect:%u\", WSAGetLastError());\n    } catch (std::exception& e) {\n      vlog.error(\"%s\", e.what());\n      remSocket(ci.sock);\n    }\n  }\n}\n"
  },
  {
    "path": "win/rfb_win32/SocketManager.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- SocketManager.h\n\n// Socket manager class for Win32.\n// Passed a network::SocketListener and a rfb::VNCServer when\n// constructed.  Uses WSAAsyncSelect to get notifications of network \n// connection attempts.  When an incoming connection is received,\n// the manager will call rfb::VNCServer::addClient().  If\n// addClient returns true then the manager registers interest in\n// network events on that socket, and calls\n// rfb::VNCServer::processSocketEvent().\n\n#ifndef __RFB_WIN32_SOCKET_MGR_H__\n#define __RFB_WIN32_SOCKET_MGR_H__\n\n#include <map>\n#include <rfb_win32/EventManager.h>\n\nnamespace network {\n  class SocketListener;\n  class Socket;\n}\n\nnamespace rfb {\n  class VNCServer;\n\n  namespace win32 {\n\n    class SocketManager : public EventManager, EventHandler {\n    public:\n      SocketManager();\n      virtual ~SocketManager();\n\n      // AddressChangeNotifier callback interface\n      // If an object implementing this is passed to addListener then it will be\n      // called whenever the SocketListener's address list changes\n      class AddressChangeNotifier {\n      public:\n        virtual ~AddressChangeNotifier() {}\n        virtual void processAddressChange() = 0;\n      };\n\n      // Add a listening socket.  Incoming connections will be added to the supplied\n      // VNCServer.\n      void addListener(network::SocketListener* sock_,\n                       VNCServer* srvr,\n                       AddressChangeNotifier* acn = nullptr);\n\n      // Remove and delete a listening socket.\n      void remListener(network::SocketListener* sock);\n\n      // Add an already-connected socket.  Socket events will cause the supplied\n      // VNCServer to be called.  The socket must ALREADY BE REGISTERED with\n      // the VNCServer.\n      void addSocket(network::Socket* sock_, VNCServer* srvr, bool outgoing=true);\n\n      bool getDisable(VNCServer* srvr);\n      void setDisable(VNCServer* srvr, bool disable);\n\n    protected:\n      int checkTimeouts() override;\n      void processEvent(HANDLE event) override;\n      virtual void remSocket(network::Socket* sock);\n\n      struct ConnInfo {\n        network::Socket* sock;\n        VNCServer* server;\n      };\n      struct ListenInfo {\n        network::SocketListener* sock;\n        VNCServer* server;\n        AddressChangeNotifier* notifier;\n        bool disable;\n      };\n      std::map<HANDLE, ListenInfo> listeners;\n      std::map<HANDLE, ConnInfo> connections;\n   };\n\n  }\n\n}\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/TrayIcon.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- CView.h\n\n// An instance of the CView class is created for each VNC viewer connection.\n\n#ifndef __RFB_WIN32_TRAY_ICON_H__\n#define __RFB_WIN32_TRAY_ICON_H__\n\n#include <windows.h>\n#include <shellapi.h>\n\n#include <rfb_win32/MsgWindow.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class TrayIcon : public MsgWindow {\n    public:\n      TrayIcon() : MsgWindow(\"VNCTray\") {\n#ifdef NOTIFYICONDATA_V1_SIZE\n        nid.cbSize = NOTIFYICONDATA_V1_SIZE;\n#else\n        nid.cbSize = sizeof(NOTIFYICONDATA);\n#endif\n\n        nid.hWnd = getHandle();\n        nid.uID = 0;\n        nid.hIcon = nullptr;\n        nid.uFlags = NIF_ICON | NIF_MESSAGE;\n        nid.uCallbackMessage = WM_USER;\n      }\n      virtual ~TrayIcon() {\n        remove();\n      }\n      bool setIcon(UINT icon) {\n        if (icon == 0) {\n          return remove();\n        } else {\n          nid.hIcon = (HICON)LoadImage(GetModuleHandle(nullptr), MAKEINTRESOURCE(icon),\n            IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);\n          return refresh();\n        }\n      }\n      bool setToolTip(const char* text) {\n        if (text == nullptr) {\n          nid.uFlags &= ~NIF_TIP;\n        } else {\n          const int tipLen = sizeof(nid.szTip)/sizeof(char);\n          strncpy(nid.szTip, text, tipLen);\n          nid.szTip[tipLen-1] = 0;\n          nid.uFlags |= NIF_TIP;\n        }\n        return refresh();\n      }\n      bool remove() {\n        return Shell_NotifyIcon(NIM_DELETE, &nid) != 0;\n      }\n      bool refresh() {\n        return Shell_NotifyIcon(NIM_MODIFY, &nid) || Shell_NotifyIcon(NIM_ADD, &nid);\n      }\n    protected:\n      NOTIFYICONDATA nid;\n    };\n\n  };\n\n};\n\n#endif\n\n\n"
  },
  {
    "path": "win/rfb_win32/TsSessions.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/TsSessions.h>\n\n#include <wtsapi32.h>\n\nstatic core::LogWriter vlog(\"TsSessions\");\n\nnamespace rfb {\nnamespace win32 {\n\n  ProcessSessionId::ProcessSessionId(DWORD processId) {\n    id = 0;\n    if (processId == (DWORD)-1)\n      processId = GetCurrentProcessId();\n    if (!ProcessIdToSessionId(GetCurrentProcessId(), &id))\n      throw core::win32_error(\"ProcessIdToSessionId\", GetLastError());\n  }\n\n  ProcessSessionId mySessionId;\n\n  ConsoleSessionId::ConsoleSessionId() {\n    id = WTSGetActiveConsoleSessionId();\n  }\n\n  bool inConsoleSession() {\n    ConsoleSessionId console;\n    return console.id == mySessionId.id;\n  }\n\n  void setConsoleSession(DWORD sessionId) {\n    if (sessionId == (DWORD)-1)\n      sessionId = mySessionId.id;\n\n    // Try to reconnect our session to the console\n    ConsoleSessionId console;\n    vlog.info(\"Console session is %lu\", console.id);\n    if (!WTSConnectSession(sessionId, console.id, (PTSTR)\"\", 0))\n      throw core::win32_error(\"Unable to connect session to Console\", GetLastError());\n\n    // Lock the newly connected session, for security\n    LockWorkStation();\n  }\n\n};\n};\n"
  },
  {
    "path": "win/rfb_win32/TsSessions.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// Windows version-independent Terminal Services Session discovery\n// and manipulation API.  This code will eventually be replaced\n// by the full TS-compatibility scheme.\n\n#ifndef __RFB_WIN32_TSSESSIONS_H__\n#define __RFB_WIN32_TSSESSIONS_H__\n\n#include <windows.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    struct SessionId {\n      DWORD id;\n    };\n\n    // Session Id for a given process\n    struct ProcessSessionId : SessionId {\n      ProcessSessionId(DWORD processId = -1);\n    };\n\n    // Session Id for current process\n    extern ProcessSessionId mySessionId;\n\n    // Current console Session Id\n    struct ConsoleSessionId : SessionId {\n      ConsoleSessionId();\n    };\n\n    // Check whether the process is in the Console session at present\n    bool inConsoleSession();\n\n    // Make the specified session the Console session.\n    //   If sessionId is -1 then the process' session is\n    //   made the Console session.\n    void setConsoleSession(DWORD sessionId = -1);\n\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/WMCursor.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMCursor.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/WMCursor.h>\n\n#include <rfb/Exception.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"WMCursor\");\n\nWMCursor::WMCursor() : cursor(nullptr) {\n  cursor = (HCURSOR)LoadImage(nullptr, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);\n}\n\nWMCursor::~WMCursor() {\n}\n  \nWMCursor::Info\nWMCursor::getCursorInfo() {\n  Info result;\n  CURSORINFO info;\n  info.cbSize = sizeof(CURSORINFO);\n  if (!GetCursorInfo(&info))\n    throw core::win32_error(\"GetCursorInfo failed\", GetLastError());\n  result.cursor = info.hCursor;\n  result.position = {info.ptScreenPos.x, info.ptScreenPos.y};\n  result.visible = info.flags & CURSOR_SHOWING;\n  return result;\n}\n"
  },
  {
    "path": "win/rfb_win32/WMCursor.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMCursor.h\n\n// WMCursor provides a single API through which the cursor state can be obtained\n// The underlying implementation will use either GetCursorInfo, or use the\n// wm_hooks library if GetCursorInfo is not available.\n\n#ifndef __RFB_WIN32_WM_CURSOR_H__\n#define __RFB_WIN32_WM_CURSOR_H__\n\n#include <windows.h>\n#include <rfb_win32/WMHooks.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    class WMCursor {\n    public:\n      WMCursor();\n      ~WMCursor();\n\n      struct Info {\n        HCURSOR cursor;\n        core::Point position;\n        bool visible;\n        Info() : cursor(nullptr), visible(false) {}\n        bool operator!=(const Info& info) {\n          return ((cursor != info.cursor) ||\n            (position != info.position) ||\n            (visible != info.visible));\n        }\n      };\n\n      Info getCursorInfo();\n    protected:\n      HCURSOR cursor;\n    };\n\n  };\n};\n\n#endif // __RFB_WIN32_WM_CURSOR_H__\n"
  },
  {
    "path": "win/rfb_win32/WMHooks.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMHooks.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <mutex>\n#include <thread>\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/WMHooks.h>\n#include <rfb_win32/Service.h>\n#include <rfb_win32/MsgWindow.h>\n#include <rfb_win32/IntervalTimer.h>\n\n#include <list>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"WMHooks\");\n\n\nstatic HMODULE hooksLibrary;\n\ntypedef UINT (*WM_Hooks_WMVAL_proto)();\nstatic WM_Hooks_WMVAL_proto WM_Hooks_WindowChanged;\nstatic WM_Hooks_WMVAL_proto WM_Hooks_WindowBorderChanged;\nstatic WM_Hooks_WMVAL_proto WM_Hooks_WindowClientAreaChanged;\nstatic WM_Hooks_WMVAL_proto WM_Hooks_RectangleChanged;\n#ifdef _DEBUG\nstatic WM_Hooks_WMVAL_proto WM_Hooks_Diagnostic;\n#endif\n\ntypedef BOOL (*WM_Hooks_Install_proto)(DWORD owner, DWORD thread);\nstatic WM_Hooks_Install_proto WM_Hooks_Install;\ntypedef BOOL (*WM_Hooks_Remove_proto)(DWORD owner);\nstatic WM_Hooks_Remove_proto WM_Hooks_Remove;\n#ifdef _DEBUG\ntypedef void (*WM_Hooks_SetDiagnosticRange_proto)(UINT min, UINT max);\nstatic WM_Hooks_SetDiagnosticRange_proto WM_Hooks_SetDiagnosticRange;\n#endif\n\ntypedef BOOL (*WM_Hooks_EnableRealInputs_proto)(BOOL pointer, BOOL keyboard);\nstatic WM_Hooks_EnableRealInputs_proto WM_Hooks_EnableRealInputs;\n\n\nstatic void LoadHooks()\n{\n  if (hooksLibrary != nullptr)\n    return;\n\n  hooksLibrary = LoadLibrary(\"wm_hooks.dll\");\n  if (hooksLibrary == nullptr)\n    return;\n\n  WM_Hooks_WindowChanged = (WM_Hooks_WMVAL_proto)(void*)GetProcAddress(hooksLibrary, \"WM_Hooks_WindowChanged\");\n  if (WM_Hooks_WindowChanged == nullptr)\n    goto error;\n  WM_Hooks_WindowBorderChanged = (WM_Hooks_WMVAL_proto)(void*)GetProcAddress(hooksLibrary, \"WM_Hooks_WindowBorderChanged\");\n  if (WM_Hooks_WindowBorderChanged == nullptr)\n    goto error;\n  WM_Hooks_WindowClientAreaChanged = (WM_Hooks_WMVAL_proto)(void*)GetProcAddress(hooksLibrary, \"WM_Hooks_WindowClientAreaChanged\");\n  if (WM_Hooks_WindowClientAreaChanged == nullptr)\n    goto error;\n  WM_Hooks_RectangleChanged = (WM_Hooks_WMVAL_proto)(void*)GetProcAddress(hooksLibrary, \"WM_Hooks_RectangleChanged\");\n  if (WM_Hooks_RectangleChanged == nullptr)\n    goto error;\n#ifdef _DEBUG\n  WM_Hooks_Diagnostic = (WM_Hooks_WMVAL_proto)(void*)GetProcAddress(hooksLibrary, \"WM_Hooks_Diagnostic\");\n  if (WM_Hooks_Diagnostic == nullptr)\n    goto error;\n#endif\n\n  WM_Hooks_Install = (WM_Hooks_Install_proto)(void*)GetProcAddress(hooksLibrary, \"WM_Hooks_Install\");\n  if (WM_Hooks_Install == nullptr)\n    goto error;\n  WM_Hooks_Remove = (WM_Hooks_Remove_proto)(void*)GetProcAddress(hooksLibrary, \"WM_Hooks_Remove\");\n  if (WM_Hooks_Remove == nullptr)\n    goto error;\n#ifdef _DEBUG\n  WM_Hooks_SetDiagnosticRange = (WM_Hooks_SetDiagnosticRange_proto)(void*)GetProcAddress(hooksLibrary, \"WM_Hooks_SetDiagnosticRange\");\n  if (WM_Hooks_SetDiagnosticRange == nullptr)\n    goto error;\n#endif\n\n  WM_Hooks_EnableRealInputs = (WM_Hooks_EnableRealInputs_proto)(void*)GetProcAddress(hooksLibrary, \"WM_Hooks_EnableRealInputs\");\n  if (WM_Hooks_EnableRealInputs == nullptr)\n    goto error;\n\n  return;\n\nerror:\n  FreeLibrary(hooksLibrary);\n  hooksLibrary = nullptr;\n}\n\n\nclass WMHooksThread {\npublic:\n  WMHooksThread() : active(true), thread(&WMHooksThread::worker, this),\n                    thread_id(-1) { }\n  void stop();\n  DWORD getThreadId() { return thread_id; }\nprotected:\n  void worker();\nprotected:\n  bool active;\n  std::thread thread;\n  DWORD thread_id;\n};\n\nstatic WMHooksThread* hook_mgr = nullptr;\nstatic std::list<WMHooks*> hooks;\nstatic std::mutex hook_mgr_lock;\n\n\nstatic bool StartHookThread() {\n  if (hook_mgr)\n    return true;\n  if (hooksLibrary == nullptr)\n    return false;\n  vlog.debug(\"Creating thread\");\n  hook_mgr = new WMHooksThread();\n  while (hook_mgr->getThreadId() == (DWORD)-1)\n    Sleep(0);\n  vlog.debug(\"Installing hooks\");\n  if (!WM_Hooks_Install(hook_mgr->getThreadId(), 0)) {\n    vlog.error(\"Failed to initialise hooks\");\n    hook_mgr->stop();\n    delete hook_mgr;\n    hook_mgr = nullptr;\n    return false;\n  }\n  return true;\n}\n\nstatic void StopHookThread() {\n  if (!hook_mgr)\n    return;\n  if (!hooks.empty())\n    return;\n  vlog.debug(\"Closing thread\");\n  hook_mgr->stop();\n  delete hook_mgr;\n  hook_mgr = nullptr;\n}\n\n\nstatic bool AddHook(WMHooks* hook) {\n  vlog.debug(\"Adding hook\");\n  const std::lock_guard<std::mutex> lock(hook_mgr_lock);\n  if (!StartHookThread())\n    return false;\n  hooks.push_back(hook);\n  return true;\n}\n\nstatic bool RemHook(WMHooks* hook) {\n  {\n    vlog.debug(\"Removing hook\");\n    const std::lock_guard<std::mutex> lock(hook_mgr_lock);\n    hooks.remove(hook);\n  }\n  StopHookThread();\n  return true;\n}\n\nstatic void NotifyHooksRegion(const Region& r) {\n  const std::lock_guard<std::mutex> lock(hook_mgr_lock);\n  std::list<WMHooks*>::iterator i;\n  for (i=hooks.begin(); i!=hooks.end(); i++)\n    (*i)->NotifyHooksRegion(r);\n}\n\n\nvoid\nWMHooksThread::worker() {\n  // Obtain message ids for all supported hook messages\n  UINT windowMsg = WM_Hooks_WindowChanged();\n  UINT clientAreaMsg = WM_Hooks_WindowClientAreaChanged();\n  UINT borderMsg = WM_Hooks_WindowBorderChanged();\n  UINT rectangleMsg = WM_Hooks_RectangleChanged();\n#ifdef _DEBUG\n  UINT diagnosticMsg = WM_Hooks_Diagnostic();\n#endif\n  MSG msg;\n  RECT wrect;\n  HWND hwnd;\n  int count = 0;\n\n  // Update delay handling\n  //   We delay updates by 40-80ms, so that the triggering application has time to\n  //   actually complete them before we notify the hook callbacks & they go off\n  //   capturing screen state.\n  const int updateDelayMs = 40;\n  MsgWindow updateDelayWnd(\"WMHooks::updateDelay\");\n  IntervalTimer updateDelayTimer(updateDelayWnd.getHandle(), 1);\n  Region updates[2];\n  int activeRgn = 0;\n\n  vlog.debug(\"Starting hook thread\");\n\n  thread_id = GetCurrentThreadId();\n\n  while (active && GetMessage(&msg, nullptr, 0, 0)) {\n    count++;\n\n    if (msg.message == WM_TIMER) {\n      // Actually notify callbacks of graphical updates\n      NotifyHooksRegion(updates[1-activeRgn]);\n      if (updates[activeRgn].is_empty())\n        updateDelayTimer.stop();\n      activeRgn = 1-activeRgn;\n      updates[activeRgn].clear();\n\n    } else if (msg.message == windowMsg) {\n      // An entire window has (potentially) changed\n      hwnd = (HWND) msg.lParam;\n      if (IsWindow(hwnd) && IsWindowVisible(hwnd) && !IsIconic(hwnd) &&\n        GetWindowRect(hwnd, &wrect) && !IsRectEmpty(&wrect)) {\n          updates[activeRgn].assign_union({{wrect.left, wrect.top,\n                                            wrect.right, wrect.bottom}});\n          updateDelayTimer.start(updateDelayMs);\n      }\n\n    } else if (msg.message == clientAreaMsg) {\n      // The client area of a window has (potentially) changed\n      hwnd = (HWND) msg.lParam;\n      if (IsWindow(hwnd) && IsWindowVisible(hwnd) && !IsIconic(hwnd) &&\n          GetClientRect(hwnd, &wrect) && !IsRectEmpty(&wrect))\n      {\n        POINT pt = {0,0};\n        if (ClientToScreen(hwnd, &pt)) {\n          updates[activeRgn].assign_union({{wrect.left+pt.x, wrect.top+pt.y,\n                                            wrect.right+pt.x, wrect.bottom+pt.y}});\n          updateDelayTimer.start(updateDelayMs);\n        }\n      }\n\n    } else if (msg.message == borderMsg) {\n      hwnd = (HWND) msg.lParam;\n      if (IsWindow(hwnd) && IsWindowVisible(hwnd) && !IsIconic(hwnd) &&\n          GetWindowRect(hwnd, &wrect) && !IsRectEmpty(&wrect))\n      {\n        Region changed({wrect.left, wrect.top, wrect.right, wrect.bottom});\n        RECT crect;\n        POINT pt = {0,0};\n        if (GetClientRect(hwnd, &crect) && ClientToScreen(hwnd, &pt) &&\n            !IsRectEmpty(&crect))\n        {\n          changed.assign_subtract({{crect.left+pt.x, crect.top+pt.y,\n                                    crect.right+pt.x, crect.bottom+pt.y}});\n        }\n        if (!changed.is_empty()) {\n          updates[activeRgn].assign_union(changed);\n          updateDelayTimer.start(updateDelayMs);\n        }\n      }\n    } else if (msg.message == rectangleMsg) {\n      Rect r(LOWORD(msg.wParam), HIWORD(msg.wParam),\n             LOWORD(msg.lParam), HIWORD(msg.lParam));\n      if (!r.is_empty()) {\n        updates[activeRgn].assign_union(r);\n        updateDelayTimer.start(updateDelayMs);\n      }\n\n#ifdef _DEBUG\n    } else if (msg.message == diagnosticMsg) {\n      vlog.info(\"DIAG msg=%x(%d) wnd=%lx\",\n                (unsigned)msg.wParam, (int)msg.wParam,\n                (unsigned long)msg.lParam);\n#endif\n    }\n  }\n\n  vlog.debug(\"Stopping hook thread - processed %d events\", count);\n  WM_Hooks_Remove(getThreadId());\n}\n\nvoid\nWMHooksThread::stop() {\n  vlog.debug(\"Stopping WMHooks thread\");\n  active = false;\n  PostThreadMessage(thread_id, WM_QUIT, 0, 0);\n  vlog.debug(\"Waiting for WMHooks thread\");\n  thread.join();\n}\n\n// -=- WMHooks class\n\nrfb::win32::WMHooks::WMHooks() : updateEvent(nullptr) {\n  LoadHooks();\n}\n\nrfb::win32::WMHooks::~WMHooks() {\n  RemHook(this);\n}\n\nbool rfb::win32::WMHooks::setEvent(HANDLE ue) {\n  if (updateEvent)\n    RemHook(this);\n  updateEvent = ue;\n  return AddHook(this);\n}\n\nbool rfb::win32::WMHooks::getUpdates(UpdateTracker* ut) {\n  if (!updatesReady) return false;\n  const std::lock_guard<std::mutex> lock(hook_mgr_lock);\n  updates.copyTo(ut);\n  updates.clear();\n  updatesReady = false;\n  return true;\n}\n\n#ifdef _DEBUG\nvoid\nrfb::win32::WMHooks::setDiagnosticRange(UINT min, UINT max) {\n  WM_Hooks_SetDiagnosticRange(min, max);\n}\n#endif\n\nvoid rfb::win32::WMHooks::NotifyHooksRegion(const Region& r) {\n  // hook_mgr_lock is already held at this point\n  updates.add_changed(r);\n  updatesReady = true;\n  SetEvent(updateEvent);\n}\n\n\n// -=- WMBlockInput class\n\nrfb::win32::WMBlockInput::WMBlockInput() : active(false) {\n  LoadHooks();\n}\n\nrfb::win32::WMBlockInput::~WMBlockInput() {\n  blockInputs(false);\n}\n\nstatic bool blocking = false;\nstatic bool blockRealInputs(bool block_) {\n  // NB: Requires blockMutex to be held!\n  if (hooksLibrary == nullptr)\n    return false;\n  if (block_) {\n    if (blocking)\n      return true;\n    // Enable blocking\n    if (!WM_Hooks_EnableRealInputs(false, false))\n      return false;\n    blocking = true;\n  }\n  if (blocking) {\n    WM_Hooks_EnableRealInputs(true, true);\n    blocking = false;\n  }\n  return block_ == blocking;\n}\n\nstatic std::mutex blockMutex;\nstatic int blockCount = 0;\n\nbool rfb::win32::WMBlockInput::blockInputs(bool on) {\n  if (active == on) return true;\n  const std::lock_guard<std::mutex> lock(blockMutex);\n  int newCount = on ? blockCount+1 : blockCount-1;\n  if (!blockRealInputs(newCount > 0))\n    return false;\n  blockCount = newCount;\n  active = on;\n  return true;\n}\n"
  },
  {
    "path": "win/rfb_win32/WMHooks.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMHooks.h\n\n#ifndef __RFB_WIN32_WM_HOOKS_H__\n#define __RFB_WIN32_WM_HOOKS_H__\n\n#include <windows.h>\n\n#include <rfb/UpdateTracker.h>\n\n#include <rfb_win32/Win32Util.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    // -=- WMHooks\n    //     Uses the wm_hooks DLL to intercept window messages, to get _hints_ as\n    //     to what may have changed on-screen.  Updates are notified via a Win32\n    //     event, and retrieved using the getUpdates method, which is thread-safe.\n    class WMHooks {\n    public:\n      WMHooks();\n      ~WMHooks();\n\n      // Specify the event object to notify.  Starts the hook subsystem if it is\n      // not already active, and returns false if the hooks fail to start.\n      bool setEvent(HANDLE updateEvent);\n\n      // Copies any new updates to the UpdateTracker.  Returns true if new updates\n      // were added, false otherwise.\n      bool getUpdates(UpdateTracker* ut);\n\n#ifdef _DEBUG\n      // Get notifications of any messages in the given range, to any hooked window\n      void setDiagnosticRange(UINT min, UINT max);\n#endif\n\n      // * INTERNAL NOTIFICATION FUNCTION * \n      void NotifyHooksRegion(const core::Region& r);\n    protected:\n      HANDLE updateEvent;\n      bool updatesReady;\n      SimpleUpdateTracker updates;\n    };\n\n    // -=- Support for filtering out local input events while remote connections are\n    //     active.  Implemented using SetWindowsHookEx for portability.\n    class WMBlockInput {\n    public:\n      WMBlockInput();\n      ~WMBlockInput();\n      bool blockInputs(bool block);\n    protected:\n      bool active;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_WM_HOOKS_H__\n"
  },
  {
    "path": "win/rfb_win32/WMNotifier.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMNotifier.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/WMNotifier.h>\n#include <rfb_win32/WMShatter.h>\n#include <rfb_win32/MsgWindow.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"WMMonitor\");\n\n\nWMMonitor::WMMonitor() : MsgWindow(\"WMMonitor\"), notifier(nullptr) {\n}\n\nWMMonitor::~WMMonitor() {\n}\n\n\nLRESULT\nWMMonitor::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {\n  switch (msg) {\n  case WM_DISPLAYCHANGE:\n    if (notifier) {\n      notifier->notifyDisplayEvent(Notifier::DisplaySizeChanged);\n      notifier->notifyDisplayEvent(Notifier::DisplayPixelFormatChanged);\n    }\n    break;\n  };\n  return MsgWindow::processMessage(msg, wParam, lParam);\n}\n"
  },
  {
    "path": "win/rfb_win32/WMNotifier.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMNotifier.h\n//\n// The WMNotifier is used to get callbacks indicating changes in the state\n// of the system, for instance in the size/format/palette of the display.\n// The WMNotifier contains a Win32 window, which receives notifications of\n// system events and stores them.  Whenever processEvent is called, any\n// incoming events are processed and the appropriate notifier called.\n\n#ifndef __RFB_WIN32_NOTIFIER_H__\n#define __RFB_WIN32_NOTIFIER_H__\n\n#include <rfb/SDesktop.h>\n#include <rfb_win32/MsgWindow.h>\n#include <rfb_win32/DeviceFrameBuffer.h>\n#include <rfb_win32/SInput.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    // -=- Window Message Monitor implementation\n\n    class WMMonitor : MsgWindow {\n    public:\n\n      class Notifier {\n      public:\n        typedef enum {DisplaySizeChanged,\n          DisplayPixelFormatChanged} DisplayEventType;\n        virtual void notifyDisplayEvent(DisplayEventType evt) = 0;\n      };\n\n      WMMonitor();\n      virtual ~WMMonitor();\n\n      void setNotifier(Notifier* wmn) {notifier=wmn;}\n\n    protected:\n      // - Internal MsgWindow callback\n      LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) override;\n\n      Notifier* notifier;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_WMNOTIFIER_H__\n"
  },
  {
    "path": "win/rfb_win32/WMPoller.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMPoller.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Configuration.h>\n#include <core/Exception.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/WMPoller.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"WMPoller\");\n\nBoolParameter rfb::win32::WMPoller::poll_console_windows(\"PollConsoleWindows\",\n  \"Server should poll console windows for updates\", true);\n\n// -=- WMPoller class\n\nbool\nrfb::win32::WMPoller::processEvent() {\n  PollInfo info;\n  if (poll_console_windows && ut) {\n    ::EnumWindows(WMPoller::enumWindowProc, (LPARAM) &info);\n    ut->add_changed(info.poll_include);\n  }\n  return false;\n}\n\nbool\nrfb::win32::WMPoller::setUpdateTracker(UpdateTracker* ut_) {\n  ut = ut_;\n  return true;\n}\n\nbool\nrfb::win32::WMPoller::checkPollWindow(HWND w) {\n  char buffer[128];\n  if (!GetClassName(w, buffer, 128))\n    throw core::win32_error(\"Unable to get window class:%u\", GetLastError());\n  if ((strcmp(buffer, \"tty\") != 0) &&\n    (strcmp(buffer, \"ConsoleWindowClass\") != 0)) {\n    return false;\n  }\n  return true;\n}\n\nvoid\nrfb::win32::WMPoller::pollWindow(HWND w, PollInfo* i) {\n  RECT r;\n  if (IsWindowVisible(w) && GetWindowRect(w, &r)) {\n    if (IsRectEmpty(&r)) return;\n    Region wrgn({r.left, r.top, r.right, r.bottom});\n    if (checkPollWindow(w)) {\n      wrgn.assign_subtract(i->poll_exclude);\n      i->poll_include.assign_union(wrgn);\n    } else {\n      i->poll_exclude.assign_union(wrgn);\n    }\n  }\n}\n\nBOOL CALLBACK\nrfb::win32::WMPoller::enumWindowProc(HWND w, LPARAM lp) {\n  pollWindow(w, (PollInfo*)lp);\n  return TRUE;\n}\n"
  },
  {
    "path": "win/rfb_win32/WMPoller.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMPoller.h\n//\n// Polls the foreground window.  If the pollOnlyConsoles flag is set,\n// then checks the window class of the foreground window first and\n// only polls it if it's a console.\n// If the pollAllWindows flag is set then iterates through visible\n// windows, and polls the visible bits.  If pollOnlyConsoles is also\n// set then only visible parts of console windows will be polled.\n\n#ifndef __RFB_WIN32_WM_POLLER_H__\n#define __RFB_WIN32_WM_POLLER_H__\n\n#include <windows.h>\n\n#include <core/Configuration.h>\n\n#include <rfb/UpdateTracker.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class WMPoller {\n    public:\n      WMPoller() : ut(nullptr) {}\n\n      bool processEvent();\n      bool setUpdateTracker(UpdateTracker* ut);\n\n      static core::BoolParameter poll_console_windows;\n    protected:\n      struct PollInfo {\n        core::Region poll_include;\n        core::Region poll_exclude;\n      };\n      static bool checkPollWindow(HWND w);\n      static void pollWindow(HWND w, PollInfo* info);\n      static BOOL CALLBACK enumWindowProc(HWND w, LPARAM lp);\n      UpdateTracker* ut;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_WM_POLLER_H__\n"
  },
  {
    "path": "win/rfb_win32/WMShatter.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMShatter.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/WMShatter.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"WMShatter\");\n\nbool\nrfb::win32::IsSafeWM(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) {\n  bool result = true;\n  switch (msg) {\n    // - UNSAFE MESSAGES\n  case WM_TIMER:\n    result = lParam == 0;\n    break;\n  };\n  if (!result) {\n    vlog.info(\"IsSafeWM: 0x%p received 0x%x(%I64u, %I64u) - not safe\",\n              window, msg, (long long)wParam, (long long)lParam);\n  }\n  return result;\n}\n\nLRESULT\nrfb::win32::SafeDefWindowProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) {\n  if (IsSafeWM(window, msg, wParam, lParam))\n    return DefWindowProc(window, msg, wParam, lParam);\n  return 0;\n}\n\nLRESULT\nrfb::win32::SafeDispatchMessage(const MSG* msg) {\n  if (IsSafeWM(msg->hwnd, msg->message, msg->wParam, msg->lParam))\n    return DispatchMessage(msg);\n  return 0;\n}\n"
  },
  {
    "path": "win/rfb_win32/WMShatter.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMShatter.h\n//\n// WMShatter provides the IsSafeWM routine, which returns true iff the\n// supplied window message is safe to pass to DispatchMessage, or to\n// process in the window procedure.\n//\n// This is only required, of course, to avoid so-called \"shatter\" attacks\n// to be made against the VNC server, which take advantage of the noddy\n// design of the Win32 window messaging system.\n//\n// The API here is designed to hopefully be future proof, so that if they\n// ever come up with a proper way to determine whether a message is safe\n// or not then it can just be reimplemented here...\n\n#ifndef __RFB_WIN32_SHATTER_H__\n#define __RFB_WIN32_SHATTER_H__\n\n#include <windows.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    bool IsSafeWM(HWND window, UINT msg, WPARAM wParam, LPARAM lParam);\n\n    LRESULT SafeDefWindowProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);\n\n    LRESULT SafeDispatchMessage(const MSG* msg);\n\n  };\n};\n\n#endif // __RFB_WIN32_SHATTER_H__\n"
  },
  {
    "path": "win/rfb_win32/WMWindowCopyRect.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMCopyRect.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/WMWindowCopyRect.h>\n\n#include <windows.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"WMCopyRect\");\n\n// -=- WMHooks class\n\nrfb::win32::WMCopyRect::WMCopyRect() : ut(nullptr), fg_window(nullptr) {\n}\n\nbool\nrfb::win32::WMCopyRect::processEvent() {\n  // See if the foreground window has moved\n  HWND window = GetForegroundWindow();\n  if (window) {\n    RECT wrect;\n    if (IsWindow(window) && IsWindowVisible(window) && GetWindowRect(window, &wrect)) {\n      Rect winrect(wrect.left, wrect.top, wrect.right, wrect.bottom);\n      if (fg_window == window) {\n        if (fg_window_rect.tl != winrect.tl && ut) {\n          // Window has moved - mark both the previous and new position as changed\n          // (we can't use add_copied() here because we aren't that properly synced\n          // with the actual state of the framebuffer)\n          ut->add_changed(winrect);\n          ut->add_changed(fg_window_rect);\n        }\n      }\n      fg_window = window;\n      fg_window_rect = winrect;\n    } else {\n      fg_window = nullptr;\n    }\n  } else {\n    fg_window = nullptr;\n  }\n  return false;\n}\n\nbool\nrfb::win32::WMCopyRect::setUpdateTracker(UpdateTracker* ut_) {\n  ut = ut_;\n  return true;\n}\n"
  },
  {
    "path": "win/rfb_win32/WMWindowCopyRect.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WMWindowCopyRect.h\n//\n// Helper class which produces copyRect actions by monitoring the location\n// of the current foreground window.\n// Whenever processEvent is called, the foreground window's position is\n// recalculated and a copy event flushed to the supplied UpdateTracker\n// if appropriate.\n\n#ifndef __RFB_WIN32_WM_WINDOW_COPYRECT_H__\n#define __RFB_WIN32_WM_WINDOW_COPYRECT_H__\n\n#include <rfb/UpdateTracker.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class WMCopyRect {\n    public:\n      WMCopyRect();\n\n      bool processEvent();\n      bool setUpdateTracker(UpdateTracker* ut);\n\n    protected:\n      UpdateTracker* ut;\n      void* fg_window;\n      core::Rect fg_window_rect;\n    };\n\n  };\n\n};\n\n#endif // __RFB_WIN32_WM_WINDOW_COPYRECT_H__\n"
  },
  {
    "path": "win/rfb_win32/Win32Util.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// Win32Util.cxx\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/Exception.h>\n#include <core/string.h>\n\n#include <rfb_win32/ModuleFileName.h>\n#include <rfb_win32/Win32Util.h>\n#include <rfb_win32/MonitorInfo.h>\n#include <rfb_win32/Handle.h>\n\n#include <rdr/HexOutStream.h>\n\n#include <stdio.h>\n\nusing namespace core;\n\nnamespace rfb {\nnamespace win32 {\n\n\nFileVersionInfo::FileVersionInfo(const char* filename) {\n  // Get executable name\n  ModuleFileName exeName;\n  if (!filename)\n    filename = exeName.buf;\n\n  // Attempt to open the file, to cause Access Denied, etc, errors\n  // to be correctly reported, since the GetFileVersionInfoXXX calls lie...\n  {\n    Handle file(CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));\n\t  if (file.h == INVALID_HANDLE_VALUE)\n      throw core::win32_error(\"Failed to open file\", GetLastError());\n  }\n\n  // Get version info size\n  DWORD handle;\n  int size = GetFileVersionInfoSize((char*)filename, &handle);\n  if (!size)\n    throw core::win32_error(\"GetVersionInfoSize failed\", GetLastError());\n\n  // Get version info\n  buf = new char[size];\n  if (!GetFileVersionInfo((char*)filename, handle, size, buf))\n    throw core::win32_error(\"GetVersionInfo failed\", GetLastError());\n}\n\nFileVersionInfo::~FileVersionInfo() {\n  delete [] buf;\n}\n\nconst char* FileVersionInfo::getVerString(const char* name, DWORD langId) {\n  uint8_t langIdBuf[sizeof(langId)];\n  for (int i=sizeof(langIdBuf)-1; i>=0; i--) {\n    langIdBuf[i] = (langId & 0xff);\n    langId = langId >> 8;\n  }\n\n  std::string langIdStr(binToHex(langIdBuf, sizeof(langId)));\n  std::string infoName;\n  infoName = format(\"\\\\StringFileInfo\\\\%s\\\\%s\", langIdStr.c_str(), name);\n\n  // Locate the required version string within the version info\n  char* buffer = nullptr;\n  UINT length = 0;\n  if (!VerQueryValue(buf, infoName.c_str(), (void**)&buffer, &length)) {\n    printf(\"unable to find %s version string\", infoName.c_str());\n    throw std::runtime_error(\"VerQueryValue failed\");\n  }\n  return buffer;\n}\n\n\nvoid centerWindow(HWND handle, HWND parent) {\n  RECT r;\n  MonitorInfo mi(parent ? parent : handle);\n  if (!parent || !IsWindowVisible(parent) || !GetWindowRect(parent, &r))\n    r=mi.rcWork;\n  centerWindow(handle, r);\n  mi.clipTo(handle);\n}\n\nvoid centerWindow(HWND handle, const RECT& r) {\n  RECT wr;\n  if (!GetWindowRect(handle, &wr)) return;\n  int w = wr.right-wr.left;\n  int h = wr.bottom-wr.top;\n  int x = (r.left + r.right - w)/2;\n  int y = (r.top + r.bottom - h)/2;\n  UINT flags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOSIZE;\n  SetWindowPos(handle, nullptr, x, y, 0, 0, flags);\n}\n\nvoid resizeWindow(HWND handle, int width, int height) {\n  RECT r;\n  GetWindowRect(handle, &r);\n  SetWindowPos(handle, nullptr, 0, 0, width, height, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);\n  centerWindow(handle, r);\n}\n\n\n};\n};\n"
  },
  {
    "path": "win/rfb_win32/Win32Util.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- Win32Util.h\n\n// Miscellaneous but useful Win32 API utility functions & classes.\n// In particular, a set of classes which wrap GDI objects,\n// and some to handle palettes.\n\n#ifndef __RFB_WIN32_GDIUTIL_H__\n#define __RFB_WIN32_GDIUTIL_H__\n\nnamespace rfb {\n\n  namespace win32 {\n\n    struct FileVersionInfo {\n      FileVersionInfo(const char* filename=nullptr);\n      ~FileVersionInfo();\n      const char* getVerString(const char* name, DWORD langId = 0x080904b0);\n    private:\n      char *buf;\n    };\n\n    // Center the window to a rectangle, or to a parent window.\n    // Optionally, resize the window to lay within the rect or parent window\n    // If the parent window is NULL then the working area if the window's\n    // current monitor is used instead.\n    void centerWindow(HWND handle, const RECT& r);\n    void centerWindow(HWND handle, HWND parent);\n\n    // resizeWindow resizes a window about its center\n    void resizeWindow(HWND handle, int width, int height);\n\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/rfb_win32/keymap.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// keymap.h - this file is shared between SInput.cxx and CKeyboard.cxx\n//\n// Mapping of X keysyms to and from Windows VK codes.  Ordering here must be\n// such that when we look up a Windows VK code we get the preferred X keysym.\n// Going the other way there is no problem because an X keysym always maps to\n// exactly one Windows VK code.  This map only contain keys which are not the\n// normal keys for printable ASCII characters.  For example it does not contain\n// VK_SPACE (note that things like VK_ADD are for the plus key on the keypad,\n// not on the main keyboard).\n\nstruct keymap_t {\n  uint32_t keysym;\n  uint8_t vk;\n  bool extended;\n};\n\nstatic keymap_t keymap[] = {\n\n  { XK_BackSpace,        VK_BACK, 0 },\n  { XK_Tab,              VK_TAB, 0 },\n  { XK_Clear,            VK_CLEAR, 0 },\n  { XK_Return,           VK_RETURN, 0 },\n  { XK_Pause,            VK_PAUSE, 0 },\n  { XK_Escape,           VK_ESCAPE, 0 },\n  { XK_Delete,           VK_DELETE, 1 },\n\n  // Cursor control & motion\n\n  { XK_Home,             VK_HOME, 1 },\n  { XK_Left,             VK_LEFT, 1 },\n  { XK_Up,               VK_UP, 1 },\n  { XK_Right,            VK_RIGHT, 1 },\n  { XK_Down,             VK_DOWN, 1 },\n  { XK_Page_Up,          VK_PRIOR, 1 },\n  { XK_Page_Down,        VK_NEXT, 1 },\n  { XK_End,              VK_END, 1 },\n\n  // Misc functions\n\n  { XK_Select,           VK_SELECT, 0 },\n  { XK_Print,            VK_SNAPSHOT, 0 },\n  { XK_Execute,          VK_EXECUTE, 0 },\n  { XK_Insert,           VK_INSERT, 1 },\n  { XK_Help,             VK_HELP, 0 },\n  { XK_Break,            VK_CANCEL, 1 },\n\n  // Auxiliary Functions - must come before XK_KP_F1, etc\n\n  { XK_F1,               VK_F1, 0 },\n  { XK_F2,               VK_F2, 0 },\n  { XK_F3,               VK_F3, 0 },\n  { XK_F4,               VK_F4, 0 },\n  { XK_F5,               VK_F5, 0 },\n  { XK_F6,               VK_F6, 0 },\n  { XK_F7,               VK_F7, 0 },\n  { XK_F8,               VK_F8, 0 },\n  { XK_F9,               VK_F9, 0 },\n  { XK_F10,              VK_F10, 0 },\n  { XK_F11,              VK_F11, 0 },\n  { XK_F12,              VK_F12, 0 },\n  { XK_F13,              VK_F13, 0 },\n  { XK_F14,              VK_F14, 0 },\n  { XK_F15,              VK_F15, 0 },\n  { XK_F16,              VK_F16, 0 },\n  { XK_F17,              VK_F17, 0 },\n  { XK_F18,              VK_F18, 0 },\n  { XK_F19,              VK_F19, 0 },\n  { XK_F20,              VK_F20, 0 },\n  { XK_F21,              VK_F21, 0 },\n  { XK_F22,              VK_F22, 0 },\n  { XK_F23,              VK_F23, 0 },\n  { XK_F24,              VK_F24, 0 },\n\n  // Keypad Functions, keypad numbers\n\n  { XK_KP_Tab,           VK_TAB, 0 },\n  { XK_KP_Enter,         VK_RETURN, 1 },\n  { XK_KP_F1,            VK_F1, 0 },\n  { XK_KP_F2,            VK_F2, 0 },\n  { XK_KP_F3,            VK_F3, 0 },\n  { XK_KP_F4,            VK_F4, 0 },\n  { XK_KP_Home,          VK_HOME, 0 },\n  { XK_KP_Left,          VK_LEFT, 0 },\n  { XK_KP_Up,            VK_UP, 0 },\n  { XK_KP_Right,         VK_RIGHT, 0 },\n  { XK_KP_Down,          VK_DOWN, 0 },\n  { XK_KP_End,           VK_END, 0 },\n  { XK_KP_Page_Up,       VK_PRIOR, 0 },\n  { XK_KP_Page_Down,     VK_NEXT, 0 },\n  { XK_KP_Begin,         VK_CLEAR, 0 },\n  { XK_KP_Insert,        VK_INSERT, 0 },\n  { XK_KP_Delete,        VK_DELETE, 0 },\n  { XK_KP_Multiply,      VK_MULTIPLY, 0 },\n  { XK_KP_Add,           VK_ADD, 0 },\n  { XK_KP_Separator,     VK_SEPARATOR, 0 },\n  { XK_KP_Subtract,      VK_SUBTRACT, 0 },\n  { XK_KP_Decimal,       VK_DECIMAL, 0 },\n  { XK_KP_Divide,        VK_DIVIDE, 1 },\n\n  { XK_KP_0,             VK_NUMPAD0, 0 },\n  { XK_KP_1,             VK_NUMPAD1, 0 },\n  { XK_KP_2,             VK_NUMPAD2, 0 },\n  { XK_KP_3,             VK_NUMPAD3, 0 },\n  { XK_KP_4,             VK_NUMPAD4, 0 },\n  { XK_KP_5,             VK_NUMPAD5, 0 },\n  { XK_KP_6,             VK_NUMPAD6, 0 },\n  { XK_KP_7,             VK_NUMPAD7, 0 },\n  { XK_KP_8,             VK_NUMPAD8, 0 },\n  { XK_KP_9,             VK_NUMPAD9, 0 },\n\n  // Modifiers\n    \n  { XK_Shift_L,          VK_SHIFT, 0 },\n  { XK_Shift_R,          VK_SHIFT, 0 },\n  { XK_Control_L,        VK_CONTROL, 0 },\n  { XK_Control_R,        VK_CONTROL, 1 },\n  { XK_Alt_L,            VK_MENU, 0 },\n  { XK_Alt_R,            VK_MENU, 1 },\n  { XK_Meta_L,           VK_MENU, 0 },\n  { XK_Meta_R,           VK_MENU, 1 },\n\n  // Left & Right Windows keys & Windows Menu Key\n\n  { XK_Super_L,          VK_LWIN, 0 },\n  { XK_Super_R,          VK_RWIN, 0 },\n  { XK_Menu,             VK_APPS, 0 },\n\n  // Japanese stuff - almost certainly wrong...\n\n  { XK_Kanji,            VK_KANJI, 0 },\n  { XK_Kana_Shift,       VK_KANA, 0 },\n\n};\n"
  },
  {
    "path": "win/rfb_win32/resource.h",
    "content": "/* Copyright (C) 2011 TigerVNC Team\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n/*\n * This file contains resource IDs shared between various Windows binaries.\n * If you are adding new resource ID ensure it doesn't conflict with per-binary\n * resource IDs.\n */\n\n#ifndef __RFB_WIN32_RESOURCE_H__\n#define __RFB_WIN32_RESOURCE_H__\n\n#define IDD_SECURITY\t\t117\n\n#define IDC_ENC_NONE\t\t1201\n#define IDC_ENC_TLS\t\t1202\n#define IDC_ENC_X509\t\t1203\n#define IDC_AUTH_NONE\t\t1206\n#define IDC_AUTH_VNC\t\t1207\n#define IDC_AUTH_PLAIN\t\t1208\n\n#endif\n"
  },
  {
    "path": "win/vncconfig/Authentication.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef WINVNCCONF_AUTHENTICATION\n#define WINVNCCONF_AUTHENTICATION\n\n#include <windows.h>\n#include <commctrl.h>\n\n#include <vncconfig/PasswordDialog.h>\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/SecurityPage.h>\n#include <rfb_win32/MsgBox.h>\n#include <rfb/ServerCore.h>\n#include <rfb/Security.h>\n#include <rfb/SecurityServer.h>\n#include <rfb/SSecurityVncAuth.h>\n#ifdef HAVE_GNUTLS\n#include <rfb/SSecurityTLS.h>\n#endif\n\nstatic core::BoolParameter queryOnlyIfLoggedOn(\"QueryOnlyIfLoggedOn\",\n  \"Only prompt for a local user to accept incoming connections if there is a user logged on\", false);\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class SecPage : public SecurityPage {\n    public:\n      SecPage(const RegKey& rk)\n        : SecurityPage(nullptr), regKey(rk) {\n        security = new SecurityServer();\n      }\n\n      void initDialog() override {\n        SecurityPage::initDialog();\n\n        setItemChecked(IDC_QUERY_CONNECT, rfb::Server::queryConnect);\n        setItemChecked(IDC_QUERY_LOGGED_ON, queryOnlyIfLoggedOn);\n        onCommand(IDC_AUTH_NONE, 0);\n      }\n\n      bool onCommand(int id, int cmd) override {\n        SecurityPage::onCommand(id, cmd);\n\n        setChanged(true);\n\n        if (id == IDC_AUTH_VNC_PASSWD) {\n          PasswordDialog passwdDlg(regKey, registryInsecure);\n          passwdDlg.showDialog(handle);\n        } else if (id == IDC_LOAD_CERT) {\n          const char* title = \"X509Cert\";\n          const char* filter =\n             \"X.509 Certificates (*.crt;*.cer;*.pem)\\0*.crt;*.cer;*.pem\\0All\\0*.*\\0\";\n          showFileChooser(regKey, title, filter, handle);\n        } else if (id == IDC_LOAD_CERTKEY) {\n          const char* title = \"X509Key\";\n          const char* filter = \"X.509 Keys (*.key;*.pem)\\0*.key;*.pem\\0All\\0*.*\\0\";\n          showFileChooser(regKey, title, filter, handle);\n        } else if (id == IDC_QUERY_LOGGED_ON) {\n          enableItem(IDC_QUERY_LOGGED_ON, enableQueryOnlyIfLoggedOn());\n        }\n\n        return true;\n      }\n      bool onOk() override {\n        SecurityPage::onOk();\n\n        if (isItemChecked(IDC_AUTH_VNC))\n          verifyVncPassword(regKey);\n        else if (haveVncPassword() && \n            MsgBox(nullptr, \"The VNC authentication method is disabled, but a password is still stored for it.\\n\"\n                      \"Do you want to remove the VNC authentication password from the registry?\",\n                      MB_ICONWARNING | MB_YESNO) == IDYES) {\n          regKey.setBinary(\"Password\", nullptr, 0);\n        }\n\n#ifdef HAVE_GNUTLS\n        if (isItemChecked(IDC_ENC_X509)) {\n          SSecurityTLS::X509_CertFile.setParam(regKey.getString(\"X509Cert\").c_str());\n          SSecurityTLS::X509_CertFile.setParam(regKey.getString(\"X509Key\").c_str());\n        }\n#endif\n\n        regKey.setString(\"SecurityTypes\", security->ToString());\n        regKey.setBool(\"QueryConnect\", isItemChecked(IDC_QUERY_CONNECT));\n        regKey.setBool(\"QueryOnlyIfLoggedOn\", isItemChecked(IDC_QUERY_LOGGED_ON));\n\n        return true;\n      }\n      void setWarnPasswdInsecure(bool warn) {\n        registryInsecure = warn;\n      }\n      bool enableQueryOnlyIfLoggedOn() {\n        return isItemChecked(IDC_QUERY_CONNECT);\n      }\n\n\n      static bool haveVncPassword() {\n        std::string password, passwordReadOnly;\n        SSecurityVncAuth::vncAuthPasswd.getVncAuthPasswd(&password, &passwordReadOnly);\n        return !password.empty();\n      }\n\n      static void verifyVncPassword(const RegKey& regKey) {\n        if (!haveVncPassword()) {\n          MsgBox(nullptr, \"The VNC authentication method is enabled, but no password is specified.\\n\"\n                    \"The password dialog will now be shown.\", MB_ICONINFORMATION | MB_OK);\n          PasswordDialog passwd(regKey, registryInsecure);\n          passwd.showDialog();\n        }\n      }\n\n      void loadX509Certs(void) override {}\n      void enableX509Dialogs(void) override {\n        enableItem(IDC_LOAD_CERT, true);\n        enableItem(IDC_LOAD_CERTKEY, true);\n      }\n      void disableX509Dialogs(void) override {\n        enableItem(IDC_LOAD_CERT, false);\n        enableItem(IDC_LOAD_CERTKEY, false);\n      }\n      void loadVncPasswd() override {\n        enableItem(IDC_AUTH_VNC_PASSWD, isItemChecked(IDC_AUTH_VNC));\n      }\n\n    protected:\n      RegKey regKey;\n      static bool registryInsecure;\n    private:\n      inline void modifyAuthMethod(int enc_idc, int auth_idc, bool enable)\n      {\n        setItemChecked(enc_idc, enable);\n        setItemChecked(auth_idc, enable);\n      }\n      inline bool showFileChooser(const RegKey& /*rk*/,\n                                  const char* title,\n                                  const char* filter,\n                                  HWND hwnd)\n      {\n        OPENFILENAME ofn;\n        char filename[MAX_PATH];\n\n        ZeroMemory(&ofn, sizeof(ofn));\n        ZeroMemory(&filename, sizeof(filename));\n        filename[0] = '\\0';\n        ofn.lStructSize = sizeof(ofn);\n        ofn.hwndOwner = hwnd;\n        ofn.lpstrFile = filename;\n        ofn.nMaxFile = sizeof(filename);\n        ofn.lpstrFilter = (char*)filter;\n        ofn.nFilterIndex = 1;\n        ofn.lpstrFileTitle = nullptr;\n        ofn.nMaxFileTitle = 0;\n        ofn.lpstrTitle = (char*)title;\n        ofn.lpstrInitialDir = nullptr;\n        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;\n\n        if (GetOpenFileName(&ofn)==TRUE) {\n          regKey.setString(title, filename);\n          return true;\n        }\n        return false;\n      }\n    };\n\n  };\n\n  bool SecPage::registryInsecure = false;\n\n};\n\n#endif\n"
  },
  {
    "path": "win/vncconfig/CMakeLists.txt",
    "content": "add_executable(vncconfig WIN32\n  Legacy.cxx\n  PasswordDialog.cxx\n  vncconfig.cxx\n  vncconfig.rc)\n\ntarget_include_directories(vncconfig PUBLIC ${CMAKE_BINARY_DIR}/win)\ntarget_link_libraries(vncconfig rfb_win32 rfb network rdr ws2_32.lib)\n\ninstall(TARGETS vncconfig\n  RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}\n)\n"
  },
  {
    "path": "win/vncconfig/Connections.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef WINVNCCONF_CONNECTIONS\n#define WINVNCCONF_CONNECTIONS\n\n#include <vector>\n\n#include <core/Configuration.h>\n#include <core/string.h>\n\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/Dialog.h>\n#include <rfb_win32/ModuleFileName.h>\n\n#include <rfb/Blacklist.h>\n\n#include <network/TcpSocket.h>\n\nstatic core::IntParameter port_number(\"PortNumber\",\n  \"TCP/IP port on which the server will accept connections\",\n  5900, 0, 65535);\nstatic core::StringParameter hosts(\"Hosts\",\n  \"Filter describing which hosts are allowed access to this server\", \"+\");\nstatic core::BoolParameter localHost(\"LocalHost\",\n  \"Only accept connections from via the local loop-back network interface\", false);\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class ConnHostDialog : public Dialog {\n    public:\n      ConnHostDialog() : Dialog(GetModuleHandle(nullptr)) {}\n      bool showDialog(const char* pat) {\n        pattern = pat;\n        return Dialog::showDialog(MAKEINTRESOURCE(IDD_CONN_HOST));\n      }\n      void initDialog() override {\n        if (pattern.empty())\n          pattern = \"+\";\n\n        if (pattern[0] == '+')\n          setItemChecked(IDC_ALLOW, true);\n        else if (pattern[0] == '?')\n          setItemChecked(IDC_QUERY, true);\n        else\n          setItemChecked(IDC_DENY, true);\n\n        setItemString(IDC_HOST_PATTERN, &pattern.c_str()[1]);\n        pattern.clear();\n      }\n      bool onOk() override {\n        std::string newPat;\n        if (isItemChecked(IDC_ALLOW))\n          newPat = '+';\n        else if (isItemChecked(IDC_QUERY))\n          newPat = '?';\n        else\n          newPat = '-';\n        newPat += getItemString(IDC_HOST_PATTERN);\n\n        try {\n          network::TcpFilter::Pattern pat(network::TcpFilter::parsePattern(newPat.c_str()));\n          pattern = network::TcpFilter::patternToStr(pat);\n        } catch(std::exception& e) {\n          MsgBox(nullptr, e.what(), MB_ICONEXCLAMATION | MB_OK);\n          return false;\n        }\n        return true;\n      }\n      const char* getPattern() {return pattern.c_str();}\n    protected:\n      std::string pattern;\n    };\n\n    class ConnectionsPage : public PropSheetPage {\n    public:\n      ConnectionsPage(const RegKey& rk)\n        : PropSheetPage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDD_CONNECTIONS)), regKey(rk) {}\n      void initDialog() override {\n        vlog.debug(\"Set IDC_PORT %d\", (int)port_number);\n        setItemInt(IDC_PORT, port_number ? port_number : 5900);\n        setItemChecked(IDC_RFB_ENABLE, port_number != 0);\n        setItemInt(IDC_IDLE_TIMEOUT, rfb::Server::idleTimeout);\n        setItemChecked(IDC_LOCALHOST, localHost);\n\n        HWND listBox = GetDlgItem(handle, IDC_HOSTS);\n        while (SendMessage(listBox, LB_GETCOUNT, 0, 0))\n          SendMessage(listBox, LB_DELETESTRING, 0, 0);\n\n        std::vector<std::string> hostv;\n        hostv = core::split(hosts, ',');\n        for (size_t i = 0; i < hostv.size(); i++) {\n          if (!hostv[i].empty())\n            SendMessage(listBox, LB_ADDSTRING, 0, (LPARAM)hostv[i].c_str());\n        }\n\n        onCommand(IDC_RFB_ENABLE, EN_CHANGE);\n      }\n      bool onCommand(int id, int cmd) override {\n        switch (id) {\n        case IDC_HOSTS:\n          {\n            DWORD selected = SendMessage(GetDlgItem(handle, IDC_HOSTS), LB_GETCURSEL, 0, 0);\n            DWORD count = SendMessage(GetDlgItem(handle, IDC_HOSTS), LB_GETCOUNT, 0, 0);\n            bool enable = selected != (DWORD)LB_ERR;\n            enableItem(IDC_HOST_REMOVE, enable);\n            enableItem(IDC_HOST_UP, enable && (selected > 0));\n            enableItem(IDC_HOST_DOWN, enable && (selected+1 < count));\n            enableItem(IDC_HOST_EDIT, enable);\n            setChanged(isChanged());\n          }\n          return true;\n\n        case IDC_PORT:\n        case IDC_IDLE_TIMEOUT:\n          if (cmd == EN_CHANGE)\n            setChanged(isChanged());\n          return false;\n\n        case IDC_RFB_ENABLE:\n        case IDC_LOCALHOST:\n          {\n            // RFB port\n            enableItem(IDC_PORT, isItemChecked(IDC_RFB_ENABLE));\n\n            // Hosts\n            enableItem(IDC_LOCALHOST, isItemChecked(IDC_RFB_ENABLE));\n\n            bool enableHosts = !isItemChecked(IDC_LOCALHOST) && isItemChecked(IDC_RFB_ENABLE);\n            enableItem(IDC_HOSTS, enableHosts);\n            enableItem(IDC_HOST_ADD, enableHosts);\n            if (!enableHosts) {\n              enableItem(IDC_HOST_REMOVE, enableHosts);\n              enableItem(IDC_HOST_UP, enableHosts);\n              enableItem(IDC_HOST_DOWN, enableHosts);\n              enableItem(IDC_HOST_EDIT, enableHosts);\n            } else {\n              onCommand(IDC_HOSTS, EN_CHANGE);\n            }\n            setChanged(isChanged());\n            return false;\n          }\n\n        case IDC_HOST_ADD:\n          if (hostDialog.showDialog(\"\"))\n          {\n            const char* pattern = hostDialog.getPattern();\n            if (pattern)\n              SendMessage(GetDlgItem(handle, IDC_HOSTS), LB_ADDSTRING, 0, (LPARAM)pattern);\n          }\n          return true;\n\n        case IDC_HOST_EDIT:\n          {\n            HWND listBox = GetDlgItem(handle, IDC_HOSTS);\n            int item = SendMessage(listBox, LB_GETCURSEL, 0, 0);\n            std::vector<char> pattern(SendMessage(listBox, LB_GETTEXTLEN, item, 0)+1);\n            SendMessage(listBox, LB_GETTEXT, item, (LPARAM)pattern.data());\n\n            if (hostDialog.showDialog(pattern.data())) {\n              const char* newPat = hostDialog.getPattern();\n              if (newPat) {\n                item = SendMessage(listBox, LB_FINDSTRINGEXACT, item, (LPARAM)pattern.data());\n                if (item != LB_ERR) {\n                  SendMessage(listBox, LB_DELETESTRING, item, 0); \n                  SendMessage(listBox, LB_INSERTSTRING, item, (LPARAM)newPat);\n                  SendMessage(listBox, LB_SETCURSEL, item, 0);\n                  onCommand(IDC_HOSTS, EN_CHANGE);\n                }\n              }\n            }\n          }\n          return true;\n\n        case IDC_HOST_UP:\n          {\n            HWND listBox = GetDlgItem(handle, IDC_HOSTS);\n            int item = SendMessage(listBox, LB_GETCURSEL, 0, 0);\n            std::vector<char> pattern(SendMessage(listBox, LB_GETTEXTLEN, item, 0)+1);\n            SendMessage(listBox, LB_GETTEXT, item, (LPARAM)pattern.data());\n            SendMessage(listBox, LB_DELETESTRING, item, 0);\n            SendMessage(listBox, LB_INSERTSTRING, item-1, (LPARAM)pattern.data());\n            SendMessage(listBox, LB_SETCURSEL, item-1, 0);\n            onCommand(IDC_HOSTS, EN_CHANGE);\n          }\n          return true;\n\n        case IDC_HOST_DOWN:\n          {\n            HWND listBox = GetDlgItem(handle, IDC_HOSTS);\n            int item = SendMessage(listBox, LB_GETCURSEL, 0, 0);\n            std::vector<char> pattern(SendMessage(listBox, LB_GETTEXTLEN, item, 0)+1);\n            SendMessage(listBox, LB_GETTEXT, item, (LPARAM)pattern.data());\n            SendMessage(listBox, LB_DELETESTRING, item, 0);\n            SendMessage(listBox, LB_INSERTSTRING, item+1, (LPARAM)pattern.data());\n            SendMessage(listBox, LB_SETCURSEL, item+1, 0);\n            onCommand(IDC_HOSTS, EN_CHANGE);\n          }\n          return true;\n\n        case IDC_HOST_REMOVE:\n          {\n            HWND listBox = GetDlgItem(handle, IDC_HOSTS);\n            int item = SendMessage(listBox, LB_GETCURSEL, 0, 0);\n            SendMessage(listBox, LB_DELETESTRING, item, 0);\n            onCommand(IDC_HOSTS, EN_CHANGE);\n          }\n\n        }\n        return false;\n      }\n      bool onOk() override {\n        regKey.setInt(\"PortNumber\", isItemChecked(IDC_RFB_ENABLE) ? getItemInt(IDC_PORT) : 0);\n        regKey.setInt(\"IdleTimeout\", getItemInt(IDC_IDLE_TIMEOUT));\n        regKey.setInt(\"LocalHost\", isItemChecked(IDC_LOCALHOST));\n        regKey.setString(\"Hosts\", getHosts().c_str());\n        return true;\n      }\n      bool isChanged() {\n        try {\n          std::string new_hosts = getHosts();\n          return (new_hosts != (const char*)hosts) ||\n              (localHost != isItemChecked(IDC_LOCALHOST)) ||\n              (port_number != getItemInt(IDC_PORT)) ||\n              (rfb::Server::idleTimeout != getItemInt(IDC_IDLE_TIMEOUT));\n        } catch (std::exception&) {\n          return false;\n        }\n      }\n      std::string getHosts() {\n        int bufLen = 1, i;\n        HWND listBox = GetDlgItem(handle, IDC_HOSTS);\n        for (i=0; i<SendMessage(listBox, LB_GETCOUNT, 0, 0); i++)\n          bufLen+=SendMessage(listBox, LB_GETTEXTLEN, i, 0)+1;\n        std::vector<char> hosts_str(bufLen);\n        hosts_str[0] = 0;\n        char* outPos = hosts_str.data();\n        for (i=0; i<SendMessage(listBox, LB_GETCOUNT, 0, 0); i++) {\n          outPos += SendMessage(listBox, LB_GETTEXT, i, (LPARAM)outPos);\n          outPos[0] = ',';\n          outPos[1] = 0;\n          outPos++;\n        }\n        return hosts_str.data();\n      }\n\n    protected:\n      RegKey regKey;\n      ConnHostDialog hostDialog;\n    };\n\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/vncconfig/Desktop.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef WINVNCCONF_DESKTOP\n#define WINVNCCONF_DESKTOP\n\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/Dialog.h>\n#include <rfb_win32/SDisplay.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class DesktopPage : public PropSheetPage {\n    public:\n      DesktopPage(const RegKey& rk)\n        : PropSheetPage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDD_DESKTOP)), regKey(rk) {}\n      void initDialog() override {\n        bool disconnectLock = rfb::win32::SDisplay::disconnectAction == \"Lock\";\n        bool disconnectLogoff = rfb::win32::SDisplay::disconnectAction == \"Logoff\";\n        setItemChecked(IDC_DISCONNECT_LOGOFF, disconnectLogoff);\n        setItemChecked(IDC_DISCONNECT_LOCK, disconnectLock);\n        setItemChecked(IDC_DISCONNECT_NONE, !disconnectLock && !disconnectLogoff);\n        setItemChecked(IDC_REMOVE_WALLPAPER, rfb::win32::SDisplay::removeWallpaper);\n        setItemChecked(IDC_DISABLE_EFFECTS, rfb::win32::SDisplay::disableEffects);\n      }\n      bool onCommand(int id, int /*cmd*/) override {\n        switch (id) {\n        case IDC_DISCONNECT_LOGOFF:\n        case IDC_DISCONNECT_LOCK:\n        case IDC_DISCONNECT_NONE:\n        case IDC_REMOVE_WALLPAPER:\n        case IDC_DISABLE_EFFECTS:\n          bool disconnectLock = rfb::win32::SDisplay::disconnectAction == \"Lock\";\n          bool disconnectLogoff = rfb::win32::SDisplay::disconnectAction == \"Logoff\";\n          setChanged((disconnectLogoff != isItemChecked(IDC_DISCONNECT_LOGOFF)) ||\n                     (disconnectLock != isItemChecked(IDC_DISCONNECT_LOCK)) ||\n                     (isItemChecked(IDC_REMOVE_WALLPAPER) != rfb::win32::SDisplay::removeWallpaper) ||\n                     (isItemChecked(IDC_DISABLE_EFFECTS) != rfb::win32::SDisplay::disableEffects));\n          break;\n        }\n        return false;\n      }\n      bool onOk() override {\n        const char* action = \"None\";\n        if (isItemChecked(IDC_DISCONNECT_LOGOFF))\n          action = \"Logoff\";\n        else if (isItemChecked(IDC_DISCONNECT_LOCK))\n          action = \"Lock\";\n        regKey.setString(\"DisconnectAction\", action);\n        regKey.setBool(\"RemoveWallpaper\", isItemChecked(IDC_REMOVE_WALLPAPER));\n        regKey.setBool(\"DisableEffects\", isItemChecked(IDC_DISABLE_EFFECTS));\n        return true;\n      }\n    protected:\n      RegKey regKey;\n    };\n\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/vncconfig/Hooking.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef WINVNCCONF_HOOKING\n#define WINVNCCONF_HOOKING\n\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/Dialog.h>\n#include <rfb_win32/SDisplay.h>\n#include <rfb_win32/WMPoller.h>\n#include <rfb/ServerCore.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class HookingPage : public PropSheetPage {\n    public:\n      HookingPage(const RegKey& rk)\n        : PropSheetPage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDD_HOOKING)), regKey(rk) {}\n      void initDialog() override {\n        setItemChecked(IDC_USEPOLLING, rfb::win32::SDisplay::updateMethod == 0);\n        setItemChecked(IDC_USEHOOKS, (rfb::win32::SDisplay::updateMethod == 1));\n        setItemChecked(IDC_POLLCONSOLES, rfb::win32::WMPoller::poll_console_windows);\n        setItemChecked(IDC_CAPTUREBLT, rfb::win32::DeviceFrameBuffer::useCaptureBlt);\n        onCommand(IDC_USEHOOKS, 0);\n      }\n      bool onCommand(int id, int /*cmd*/) override {\n        switch (id) {\n        case IDC_USEPOLLING:\n        case IDC_USEHOOKS:\n        case IDC_POLLCONSOLES:\n        case IDC_CAPTUREBLT:\n          setChanged(((rfb::win32::SDisplay::updateMethod == 0) != isItemChecked(IDC_USEPOLLING)) ||\n            ((rfb::win32::SDisplay::updateMethod == 1) != isItemChecked(IDC_USEHOOKS)) ||\n            (rfb::win32::WMPoller::poll_console_windows != isItemChecked(IDC_POLLCONSOLES)) ||\n            (rfb::win32::DeviceFrameBuffer::useCaptureBlt != isItemChecked(IDC_CAPTUREBLT)));\n          enableItem(IDC_POLLCONSOLES, isItemChecked(IDC_USEHOOKS));\n          break;\n        }\n        return false;\n      }\n      bool onOk() override {\n        if (isItemChecked(IDC_USEPOLLING))\n          regKey.setInt(\"UpdateMethod\", 0);\n        if (isItemChecked(IDC_USEHOOKS))\n          regKey.setInt(\"UpdateMethod\", 1);\n        regKey.setBool(\"PollConsoleWindows\", isItemChecked(IDC_POLLCONSOLES));\n        regKey.setBool(\"UseCaptureBlt\", isItemChecked(IDC_CAPTUREBLT));\n\n        // *** LEGACY compatibility ***\n        regKey.setBool(\"UseHooks\", isItemChecked(IDC_USEHOOKS));\n        return true;\n      }\n    protected:\n      RegKey regKey;\n    };\n\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/vncconfig/Inputs.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef WINVNCCONF_INPUTS\n#define WINVNCCONF_INPUTS\n\n#ifndef SPI_GETBLOCKSENDINPUTRESETS\n#define SPI_GETBLOCKSENDINPUTRESETS 0x1026\n#define SPI_SETBLOCKSENDINPUTRESETS 0x1027\n#endif\n\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/Dialog.h>\n#include <rfb/ServerCore.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    class InputsPage : public PropSheetPage {\n    public:\n      InputsPage(const RegKey& rk)\n        : PropSheetPage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDD_INPUTS)),\n          regKey(rk), enableAffectSSaver(true) {}\n      void initDialog() override {\n        setItemChecked(IDC_ACCEPT_KEYS, rfb::Server::acceptKeyEvents);\n        setItemChecked(IDC_RAW_KEYBOARD, SKeyboard::rawKeyboard);\n        setItemChecked(IDC_ACCEPT_PTR, rfb::Server::acceptPointerEvents);\n        setItemChecked(IDC_ACCEPT_CUTTEXT, rfb::Server::acceptCutText);\n        setItemChecked(IDC_SEND_CUTTEXT, rfb::Server::sendCutText);\n        setItemChecked(IDC_DISABLE_LOCAL_INPUTS, SDisplay::disableLocalInputs);\n        BOOL blocked = FALSE;\n        if (SystemParametersInfo(SPI_GETBLOCKSENDINPUTRESETS, 0, &blocked, 0))\n          setItemChecked(IDC_AFFECT_SCREENSAVER, !blocked);\n        else\n          enableAffectSSaver = false;\n        enableItem(IDC_AFFECT_SCREENSAVER, enableAffectSSaver);\n      }\n      bool onCommand(int /*id*/, int /*cmd*/) override {\n        BOOL inputResetsBlocked;\n        SystemParametersInfo(SPI_GETBLOCKSENDINPUTRESETS, 0, &inputResetsBlocked, 0);\n        setChanged((rfb::Server::acceptKeyEvents != isItemChecked(IDC_ACCEPT_KEYS)) ||\n          (SKeyboard::rawKeyboard != isItemChecked(IDC_RAW_KEYBOARD)) ||\n          (rfb::Server::acceptPointerEvents != isItemChecked(IDC_ACCEPT_PTR)) ||\n          (rfb::Server::acceptCutText != isItemChecked(IDC_ACCEPT_CUTTEXT)) ||\n          (rfb::Server::sendCutText != isItemChecked(IDC_SEND_CUTTEXT)) ||\n          (SDisplay::disableLocalInputs != isItemChecked(IDC_DISABLE_LOCAL_INPUTS)) ||\n          (enableAffectSSaver && (!inputResetsBlocked != isItemChecked(IDC_AFFECT_SCREENSAVER))));\n        return false;\n      }\n      bool onOk() override {\n        regKey.setBool(\"AcceptKeyEvents\", isItemChecked(IDC_ACCEPT_KEYS));\n        regKey.setBool(\"RawKeyboard\", isItemChecked(IDC_RAW_KEYBOARD));\n        regKey.setBool(\"AcceptPointerEvents\", isItemChecked(IDC_ACCEPT_PTR));\n        regKey.setBool(\"AcceptCutText\", isItemChecked(IDC_ACCEPT_CUTTEXT));\n        regKey.setBool(\"SendCutText\", isItemChecked(IDC_SEND_CUTTEXT));\n        regKey.setBool(\"DisableLocalInputs\", isItemChecked(IDC_DISABLE_LOCAL_INPUTS));\n        if (enableAffectSSaver) {\n          BOOL blocked = !isItemChecked(IDC_AFFECT_SCREENSAVER);\n          SystemParametersInfo(SPI_SETBLOCKSENDINPUTRESETS, blocked, nullptr, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);\n        }\n        return true;\n      }\n    protected:\n      RegKey regKey;\n      bool enableAffectSSaver;\n    };\n\n  };\n};\n\n#endif\n"
  },
  {
    "path": "win/vncconfig/Legacy.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#include <vncconfig/Legacy.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb_win32/CurrentUser.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\n\nstatic LogWriter vlog(\"Legacy\");\n\n\nvoid LegacyPage::LoadPrefs()\n      {\n        // VNC 3.3.3R3 Preferences Algorithm, as described by vncProperties.cpp\n        // - Load user-specific settings, based on logged-on user name,\n        //   from HKLM/Software/ORL/WinVNC3/<user>.  If they don't exist,\n        //   try again with username \"Default\".\n        // - Load system-wide settings from HKLM/Software/ORL/WinVNC3.\n        // - If AllowProperties is non-zero then load the user's own\n        //   settings from HKCU/Software/ORL/WinVNC3.\n\n        // Get the name of the current user\n        std::string username;\n        try {\n          username = UserName();\n        } catch (core::win32_error& e) {\n          if (e.err != ERROR_NOT_LOGGED_ON)\n            throw;\n        }\n\n        // Open and read the WinVNC3 registry key\n        allowProperties = true;\n        RegKey winvnc3;\n        try {\n          winvnc3.openKey(HKEY_LOCAL_MACHINE, \"Software\\\\ORL\\\\WinVNC3\");\n          int debugMode = winvnc3.getInt(\"DebugMode\", 0);\n          const char* debugTarget = nullptr;\n          if (debugMode & 2) debugTarget = \"file\";\n          if (debugMode & 4) debugTarget = \"stderr\";\n          if (debugTarget) {\n            char logSetting[32];\n            sprintf(logSetting, \"*:%s:%d\", debugTarget, winvnc3.getInt(\"DebugLevel\", 0));\n            regKey.setString(\"Log\", logSetting);\n          }\n \n          std::string authHosts = winvnc3.getString(\"AuthHosts\", \"\");\n          if (!authHosts.empty()) {\n            std::string newHosts;\n\n            // Reformat AuthHosts to Hosts.  Wish I'd left the format the same. :( :( :(\n            try {\n              // Split the AuthHosts string into patterns to match\n              std::vector<std::string> patterns;\n              patterns = split(authHosts.c_str(), ':');\n              for (size_t i = 0; i < patterns.size(); i++) {\n                if (!patterns[i].empty()) {\n                  int bits = 0;\n                  char pattern[1+4*4+4];\n                  pattern[0] = patterns[i][0];\n                  pattern[1] = 0;\n\n                  // Split the pattern into IP address parts and process\n                  std::vector<std::string> parts;\n                  parts = split(&patterns[i][1], '.');\n                  for (size_t j = 0; j < parts.size(); j++) {\n                    if (bits)\n                      strcat(pattern, \".\");\n                    if (parts[j].size() > 3)\n                      throw std::invalid_argument(\"Invalid IP address part\");\n                    if (!parts[j].empty()) {\n                      strcat(pattern, parts[j].c_str());\n                      bits += 8;\n                    }\n                  }\n\n                  // Pad out the address specification if required\n                  int addrBits = bits;\n                  while (addrBits < 32) {\n                    if (addrBits) strcat(pattern, \".\");\n                    strcat(pattern, \"0\");\n                    addrBits += 8;\n                  }\n\n                  // Append the number of bits to match\n                  char buf[4];\n                  sprintf(buf, \"/%d\", bits);\n                  strcat(pattern, buf);\n\n                  // Append this pattern to the Hosts value\n                  if (!newHosts.empty())\n                    newHosts += \",\";\n                  newHosts += pattern;\n                }\n              }\n\n              // Finally, save the Hosts value\n              regKey.setString(\"Hosts\", newHosts.c_str());\n            } catch (std::exception&) {\n              MsgBox(nullptr, \"Unable to convert AuthHosts setting to Hosts format.\",\n                     MB_ICONWARNING | MB_OK);\n            }\n          } else {\n            regKey.setString(\"Hosts\", \"+\");\n          }\n\n          regKey.setBool(\"LocalHost\", winvnc3.getBool(\"LoopbackOnly\", false));\n          // *** check AllowLoopback?\n\n          if (winvnc3.getBool(\"AuthRequired\", true))\n            regKey.setString(\"SecurityTypes\", \"VncAuth\");\n          else\n            regKey.setString(\"SecurityTypes\", \"None\");\n\n          int connectPriority = winvnc3.getInt(\"ConnectPriority\", 0);\n          regKey.setBool(\"DisconnectClients\", connectPriority == 0);\n          regKey.setBool(\"AlwaysShared\", connectPriority == 1);\n          regKey.setBool(\"NeverShared\", connectPriority == 2);\n\n        } catch(std::exception&) {\n        }\n\n        // Open the local, default-user settings\n        allowProperties = true;\n        try {\n          RegKey userKey;\n          userKey.openKey(winvnc3, \"Default\");\n          vlog.info(\"Loading default prefs\");\n          LoadUserPrefs(userKey);\n        } catch(std::exception& e) {\n          vlog.error(\"Error reading Default settings:%s\", e.what());\n        }\n\n        // Open the local, user-specific settings\n        if (userSettings && !username.empty()) {\n          try {\n            RegKey userKey;\n            userKey.openKey(winvnc3, username.c_str());\n            vlog.info(\"Loading local user prefs\");\n            LoadUserPrefs(userKey);\n          } catch(std::exception& e) {\n            vlog.error(\"Error reading local User settings:%s\", e.what());\n          }\n\n          // Open the user's own settings\n          if (allowProperties) {\n            try {\n              RegKey userKey;\n              userKey.openKey(HKEY_CURRENT_USER, \"Software\\\\ORL\\\\WinVNC3\");\n              vlog.info(\"Loading global user prefs\");\n              LoadUserPrefs(userKey);\n            } catch(std::exception& e) {\n              vlog.error(\"Error reading global User settings:%s\", e.what());\n            }\n          }\n        }\n\n        // Disable the Options menu item if appropriate\n        regKey.setBool(\"DisableOptions\", !allowProperties);\n      }\n\n      void LegacyPage::LoadUserPrefs(const RegKey& key)\n      {\n        regKey.setInt(\"PortNumber\", key.getBool(\"SocketConnect\") ? key.getInt(\"PortNumber\", 5900) : 0);\n        if (key.getBool(\"AutoPortSelect\", false)) {\n          MsgBox(nullptr, \"The AutoPortSelect setting is not supported by this release.\"\n                    \"The port number will default to 5900.\",\n                    MB_ICONWARNING | MB_OK);\n          regKey.setInt(\"PortNumber\", 5900);\n        }\n        regKey.setInt(\"IdleTimeout\", key.getInt(\"IdleTimeout\", 0));\n\n        regKey.setBool(\"RemoveWallpaper\", key.getBool(\"RemoveWallpaper\"));\n        regKey.setBool(\"DisableEffects\", key.getBool(\"DisableEffects\"));\n\n        if (key.getInt(\"QuerySetting\", 2) != 2) {\n          regKey.setBool(\"QueryConnect\", key.getInt(\"QuerySetting\") > 2);\n          MsgBox(nullptr, \"The QuerySetting option has been replaced by QueryConnect.\"\n                 \"Please see the documentation for details of the QueryConnect option.\",\n                 MB_ICONWARNING | MB_OK);\n        }\n        regKey.setInt(\"QueryTimeout\", key.getInt(\"QueryTimeout\", 10));\n\n        std::vector<uint8_t> passwd;\n        passwd = key.getBinary(\"Password\");\n        regKey.setBinary(\"Password\", passwd.data(), passwd.size());\n\n        bool enableInputs = key.getBool(\"InputsEnabled\", true);\n        regKey.setBool(\"AcceptKeyEvents\", enableInputs);\n        regKey.setBool(\"AcceptPointerEvents\", enableInputs);\n        regKey.setBool(\"AcceptCutText\", enableInputs);\n        regKey.setBool(\"SendCutText\", enableInputs);\n\n        switch (key.getInt(\"LockSetting\", 0)) {\n        case 0: regKey.setString(\"DisconnectAction\", \"None\"); break;\n        case 1: regKey.setString(\"DisconnectAction\", \"Lock\"); break;\n        case 2: regKey.setString(\"DisconnectAction\", \"Logoff\"); break;\n        };\n\n        regKey.setBool(\"DisableLocalInputs\", key.getBool(\"LocalInputsDisabled\", false));\n\n        // *** ignore polling preferences\n        // PollUnderCursor, PollForeground, OnlyPollConsole, OnlyPollOnEvent\n        regKey.setBool(\"UseHooks\", !key.getBool(\"PollFullScreen\", false));\n\n        if (key.isValue(\"AllowShutdown\"))\n          MsgBox(nullptr, \"The AllowShutdown option is not supported by this release.\", MB_ICONWARNING | MB_OK);\n        if (key.isValue(\"AllowEditClients\"))\n          MsgBox(nullptr, \"The AllowEditClients option is not supported by this release.\", MB_ICONWARNING | MB_OK);\n\n        allowProperties = key.getBool(\"AllowProperties\", allowProperties);\n      }\n"
  },
  {
    "path": "win/vncconfig/Legacy.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef WINVNCCONF_LEGACY\n#define WINVNCCONF_LEGACY\n\n#include <windows.h>\n#include <lmcons.h>\n#include <vncconfig/resource.h>\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/Dialog.h>\n#include <rfb_win32/MsgBox.h>\n#include <rfb/ServerCore.h>\n#include <rfb/Security.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class LegacyPage : public PropSheetPage {\n    public:\n      LegacyPage(const RegKey& rk, bool userSettings_)\n        : PropSheetPage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDD_LEGACY)), regKey(rk), userSettings(userSettings_) {}\n      void initDialog() override {\n        setItemChecked(IDC_PROTOCOL_3_3, rfb::Server::protocol3_3);\n      }\n      bool onCommand(int id, int /*cmd*/) override {\n        switch (id) {\n        case IDC_LEGACY_IMPORT:\n          {\n            DWORD result = MsgBox(nullptr,\n              \"Importing your legacy VNC 3.3 settings will overwrite your existing settings.\\n\"\n              \"Are you sure you wish to continue?\",\n              MB_ICONWARNING | MB_YESNO);\n            if (result == IDYES) {\n              LoadPrefs();\n              MsgBox(nullptr, \"Imported VNC 3.3 settings successfully.\",\n                     MB_ICONINFORMATION | MB_OK);\n\n              // Sleep to allow RegConfig thread to reload settings\n              Sleep(1000);\n              propSheet->reInitPages();\n            }\n          }\n          return true;\n        case IDC_PROTOCOL_3_3:\n          setChanged(isItemChecked(IDC_PROTOCOL_3_3) != rfb::Server::protocol3_3);\n          return false;\n        };\n        return false;\n      }\n      bool onOk() override {\n        regKey.setBool(\"Protocol3.3\", isItemChecked(IDC_PROTOCOL_3_3));\n        return true;\n      }\n\n      void LoadPrefs();\n      void LoadUserPrefs(const RegKey& key);\n\n    protected:\n      bool allowProperties;\n      RegKey regKey;\n      bool userSettings;\n    };\n\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/vncconfig/PasswordDialog.cxx",
    "content": "/* Copyright (C) 2004-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#include <vncconfig/resource.h>\n#include <vncconfig/PasswordDialog.h>\n#include <rfb_win32/MsgBox.h>\n#include <rfb/obfuscate.h>\n\nusing namespace rfb;\nusing namespace win32;\n\nPasswordDialog::PasswordDialog(const RegKey& rk, bool registryInsecure_)\n  : Dialog(GetModuleHandle(nullptr)), regKey(rk), registryInsecure(registryInsecure_) {\n}\n\nbool PasswordDialog::showDialog(HWND owner) {\n  return Dialog::showDialog(MAKEINTRESOURCE(IDD_AUTH_VNC_PASSWD), owner);\n}\n\nbool PasswordDialog::onOk() {\n  std::string password1(getItemString(IDC_PASSWORD1));\n  std::string password2(getItemString(IDC_PASSWORD2));\n  if (password1 != password2) {\n    MsgBox(nullptr, \"The supplied passwords do not match\",\n           MB_ICONEXCLAMATION | MB_OK);\n    return false;\n  }\n  if (registryInsecure &&\n      (MsgBox(nullptr, \"Please note that your password cannot be stored securely on this system.  \"\n                 \"Are you sure you wish to continue?\",\n              MB_YESNO | MB_ICONWARNING) == IDNO))\n    return false;\n  std::vector<uint8_t> obfPwd = obfuscate(password1.c_str());\n  regKey.setBinary(\"Password\", obfPwd.data(), obfPwd.size());\n  return true;\n}\n"
  },
  {
    "path": "win/vncconfig/PasswordDialog.h",
    "content": "/* Copyright (C) 2004-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef WINVNCCONF_PASSWORD_DIALOG\n#define WINVNCCONF_PASSWORD_DIALOG\n\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/Dialog.h>\n\nnamespace rfb {\n  namespace win32 {\n\n    class PasswordDialog : public Dialog {\n    public:\n      PasswordDialog(const RegKey& rk, bool registryInsecure_);\n      bool showDialog(HWND owner=nullptr);\n      bool onOk() override;\n    protected:\n      const RegKey& regKey;\n      bool registryInsecure;\n    };\n\n  };\n};\n\n#endif"
  },
  {
    "path": "win/vncconfig/Sharing.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n#ifndef WINVNCCONF_SHARING\n#define WINVNCCONF_SHARING\n\n#include <rfb_win32/Registry.h>\n#include <rfb_win32/Dialog.h>\n#include <rfb/ServerCore.h>\n\nnamespace rfb {\n\n  namespace win32 {\n\n    class SharingPage : public PropSheetPage {\n    public:\n      SharingPage(const RegKey& rk)\n        : PropSheetPage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDD_SHARING)), regKey(rk) {}\n      void initDialog() override {\n        setItemChecked(IDC_DISCONNECT_CLIENTS, rfb::Server::disconnectClients);\n        setItemChecked(IDC_SHARE_NEVER, rfb::Server::neverShared);\n        setItemChecked(IDC_SHARE_ALWAYS, rfb::Server::alwaysShared);\n        setItemChecked(IDC_SHARE_CLIENT, !(rfb::Server::neverShared || rfb::Server::alwaysShared));\n      }\n      bool onCommand(int /*id*/, int /*cmd*/) override {\n        setChanged((isItemChecked(IDC_DISCONNECT_CLIENTS) != rfb::Server::disconnectClients) ||\n          (isItemChecked(IDC_SHARE_NEVER) != rfb::Server::neverShared) ||\n          (isItemChecked(IDC_SHARE_ALWAYS) != rfb::Server::alwaysShared));\n        return true;\n      }\n      bool onOk() override {\n        regKey.setBool(\"DisconnectClients\", isItemChecked(IDC_DISCONNECT_CLIENTS));\n        regKey.setBool(\"AlwaysShared\", isItemChecked(IDC_SHARE_ALWAYS));\n        regKey.setBool(\"NeverShared\", isItemChecked(IDC_SHARE_NEVER));\n       return true;\n      }\n    protected:\n      RegKey regKey;\n    };\n\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/vncconfig/resource.h",
    "content": "// Used by vncconfig.rc\n\n#include <rfb_win32/resource.h>\n\n#define IDR_MANIFEST                    1\n#define IDI_ICON                        101\n#define IDD_DIALOG1                     102\n#define IDD_DIALOG2                     103\n#define IDD_CONNECTIONS                 105\n#define IDD_HOOKING                     106\n#define IDD_VNC_PASSWD                  107\n#define IDD_AUTH_VNC_PASSWD             107\n#define IDD_LEGACY                      108\n#define IDD_CONN_HOST                   109\n#define IDD_SHARING                     110\n#define IDD_INPUTS                      111\n#define IDR_TRAY                        112\n#define IDD_ABOUT                       113\n#define IDI_CONNECTED                   115\n#define IDD_DESKTOP                     116\n#define IDC_EDIT1                       1000\n#define IDC_PORT                        1000\n#define IDC_PASSWORD1                   1000\n#define IDC_HOST_PATTERN                1000\n#define IDC_AUTH_VNC_PASSWD             1009\n#define IDC_USEHOOKS                    1011\n#define IDC_POLLCONSOLES                1012\n#define IDC_COMPAREFB                   1013\n#define IDC_IDLE_TIMEOUT                1015\n#define IDC_HOSTS                       1016\n#define IDC_HOST_ADD                    1017\n#define IDC_HOST_REMOVE                 1018\n#define IDC_HOST_UP                     1019\n#define IDC_BUTTON4                     1020\n#define IDC_HOST_DOWN                   1020\n#define IDC_AUTH_INPUTONLY_PASSWD       1020\n#define IDC_HOST_EDIT                   1021\n#define IDC_PASSWORD2                   1022\n#define IDC_LEGACY_IMPORT               1023\n#define IDC_ALLOW                       1024\n#define IDC_DENY                        1025\n#define IDC_SHARE_ALWAYS                1030\n#define IDC_SHARE_NEVER                 1031\n#define IDC_SHARE_CLIENT                1032\n#define IDC_DISCONNECT_CLIENTS          1033\n#define IDC_ACCEPT_KEYS                 1034\n#define IDC_ACCEPT_PTR                  1035\n#define IDC_ACCEPT_CUTTEXT              1036\n#define IDC_SEND_CUTTEXT                1037\n#define IDC_PROTOCOL_3_3                1038\n#define IDC_DESCRIPTION                 1039\n#define IDC_BUILDTIME                   1040\n#define IDC_VERSION                     1041\n#define IDC_COPYRIGHT                   1042\n#define IDC_BL_THRESHOLD                1046\n#define IDC_BL_TIMEOUT                  1047\n#define IDC_AFFECT_SCREENSAVER          1048\n#define IDC_LOCALHOST                   1049\n#define IDC_DISABLE_LOCAL_INPUTS        1050\n#define IDC_QUERY_CONNECT               1055\n#define IDC_DISCONNECT_NONE             1056\n#define IDC_DISCONNECT_LOCK             1057\n#define IDC_DISCONNECT_LOGOFF           1058\n#define IDC_REMOVE_WALLPAPER            1059\n#define IDC_DISABLE_EFFECTS             1061\n#define IDC_CAPTUREBLT                  1062\n#define IDC_QUERY                       1064\n#define IDC_USEPOLLING                  1066\n#define IDC_QUERY_LOGGED_ON             1069\n#define IDC_AUTH_ADMIN_PASSWD           1076\n#define IDC_AUTH_VIEWONLY_PASSWD        1077\n#define IDC_AUTH_ADMIN_ENABLE           1078\n#define IDC_AUTH_VIEWONLY_ENABLE        1079\n#define IDC_AUTH_INPUTONLY_ENABLE       1080\n#define IDC_RFB_ENABLE                  1082\n#define IDC_LOAD_CERT                   1087\n#define IDC_LOAD_CERTKEY                1088\n#define IDC_RAW_KEYBOARD                1089\n#define ID_OPTIONS                      40001\n#define ID_CLOSE                        40002\n#define ID_ABOUT                        40003\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        117\n#define _APS_NEXT_COMMAND_VALUE         40004\n#define _APS_NEXT_CONTROL_VALUE         1083\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "win/vncconfig/vncconfig.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#include <winsock2.h>\n#include <windows.h>\n#include <commctrl.h>\n#include <string.h>\n\n#include \"resource.h\"\n\n#include <core/Logger_stdio.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/Dialog.h>\n#include <rfb_win32/RegConfig.h>\n#include <rfb_win32/CurrentUser.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace rfb::win32;\n\nstatic LogWriter vlog(\"main\");\n\n\n#include <vncconfig/Authentication.h>\n#include <vncconfig/Connections.h>\n#include <vncconfig/Sharing.h>\n#include <vncconfig/Hooking.h>\n#include <vncconfig/Inputs.h>\n#include <vncconfig/Legacy.h>\n#include <vncconfig/Desktop.h>\n\n\nconst char* rfb::win32::AppName = \"TigerVNC Configuration\";\n\n\n#ifdef _DEBUG\nBoolParameter captureDialogs(\"CaptureDialogs\", \"\", false);\n#endif\n\nHKEY configKey = HKEY_CURRENT_USER;\n\n\nvoid\nprocessParams(int argc, char* argv[]) {\n  for (int i=1; i<argc; i++) {\n    if (strcasecmp(argv[i], \"-service\") == 0) {\n      configKey = HKEY_LOCAL_MACHINE;\n    } else if (strcasecmp(argv[i], \"-user\") == 0) {\n      configKey = HKEY_CURRENT_USER;\n    } else {\n      int ret;\n\n      ret = Configuration::handleParamArg(argc, argv, i);\n      if (ret > 0) {\n        i += ret - 1;\n        continue;\n      }\n    }\n  }\n}\n\n\nint WINAPI WinMain(HINSTANCE inst, HINSTANCE /*prev*/, char* /*cmdLine*/, int /*cmdShow*/) {\n\n  // Configure debugging output\n#ifdef _DEBUG\n  AllocConsole();\n  freopen(\"CONIN$\",\"rb\",stdin);\n  freopen(\"CONOUT$\",\"wb\",stdout);\n  freopen(\"CONOUT$\",\"wb\",stderr);\n  setbuf(stderr, nullptr);\n  initStdIOLoggers();\n  logParams.setParam(\"*:stderr:100\");\n  vlog.info(\"Starting vncconfig applet\");\n#endif\n\n  try {\n    try {\n      // Process command-line args\n      int argc = __argc;\n      char** argv = __argv;\n      processParams(argc, argv);\n\n      /* *** Required if we wish to use IP address control\n      INITCOMMONCONTROLSEX icce;\n      icce.dwSize = sizeof(icce);\n      icce.dwICC = ICC_INTERNET_CLASSES;\n      InitCommonControlsEx(&icce);\n      */\n\n      // Create the required configuration registry key\n      RegKey rootKey;\n      rootKey.createKey(configKey, \"Software\\\\TigerVNC\\\\WinVNC4\");\n  \n      // Override whatever security it already had (NT only)\n      bool warnOnChangePassword = false;\n      try {\n        AccessEntries access;\n        Sid::Administrators adminSID;\n        Sid::SYSTEM systemSID;\n        access.addEntry(adminSID, KEY_ALL_ACCESS, GRANT_ACCESS);\n        access.addEntry(systemSID, KEY_ALL_ACCESS, GRANT_ACCESS);\n        UserSID userSID;\n        if (configKey == HKEY_CURRENT_USER)\n          access.addEntry(userSID, KEY_ALL_ACCESS, GRANT_ACCESS);\n        AccessControlList acl(CreateACL(access));\n\n        // Set the DACL, and don't allow the key to inherit its parent's DACL\n        rootKey.setDACL(acl, false);\n      } catch (core::win32_error& e) {\n        // Something weird happens on NT 4.0 SP5 but I can't reproduce it on other\n        // NT 4.0 service pack revisions.\n        if (e.err == ERROR_INVALID_PARAMETER) {\n          MsgBox(nullptr, \"Windows reported an error trying to secure the VNC server settings for this user.  \"\n                    \"Your settings may not be secure!\", MB_ICONWARNING | MB_OK);\n        } else if (e.err != ERROR_CALL_NOT_IMPLEMENTED &&\n                   e.err != ERROR_NOT_LOGGED_ON) {\n          // If the call is not implemented, ignore the error and continue\n          throw;\n        }\n        warnOnChangePassword = true;\n      }\n\n      // Start a RegConfig thread, to load in existing settings\n      RegConfigThread config;\n      config.start(configKey, \"Software\\\\TigerVNC\\\\WinVNC4\");\n\n      // Build the dialog\n      std::list<PropSheetPage*> pages;\n      SecPage auth(rootKey); pages.push_back(&auth);\n      auth.setWarnPasswdInsecure(warnOnChangePassword);\n      ConnectionsPage conn(rootKey); pages.push_back(&conn);\n      InputsPage inputs(rootKey); pages.push_back(&inputs);\n      SharingPage sharing(rootKey); pages.push_back(&sharing);\n      DesktopPage desktop(rootKey); pages.push_back(&desktop);\n      HookingPage hooks(rootKey); pages.push_back(&hooks);\n      LegacyPage legacy(rootKey, configKey == HKEY_CURRENT_USER); pages.push_back(&legacy);\n\n      // Load the default icon to use\n      HICON icon = (HICON)LoadImage(inst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 0, 0, LR_SHARED);\n\n      // Create the PropertySheet handler\n      const char* propSheetTitle = \"VNC server properties (service-mode)\";\n      if (configKey == HKEY_CURRENT_USER)\n        propSheetTitle = \"VNC server properties (user-mode)\";\n      PropSheet sheet(inst, propSheetTitle, pages, icon);\n\n#ifdef _DEBUG\n      vlog.debug(\"Capture dialogs=%s\", captureDialogs ? \"true\" : \"false\");\n      sheet.showPropSheet(nullptr, true, false, captureDialogs);\n#else\n      sheet.showPropSheet(nullptr, true, false);\n#endif\n    } catch (core::win32_error& e) {\n      switch (e.err) {\n      case ERROR_ACCESS_DENIED:\n        MsgBox(nullptr, \"You do not have sufficient access rights to run the VNC Configuration applet\",\n               MB_ICONSTOP | MB_OK);\n        return 1;\n      };\n      throw;\n    }\n\n  } catch (std::exception& e) {\n    MsgBox(nullptr, e.what(), MB_ICONEXCLAMATION | MB_OK);\n    return 1;\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "win/vncconfig/vncconfig.exe.manifest",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n<assemblyIdentity\n   version=\"4.0.0.26\"\n   processorArchitecture=\"X86\"\n   name=\"TigerVNC.vncconfig.exe\"\n   type=\"win32\"\n/>\n<description>.NET control deployment tool</description>\n<dependency>\n   <dependentAssembly>\n     <assemblyIdentity\n       type=\"win32\"\n       name=\"Microsoft.Windows.Common-Controls\"\n       version=\"6.0.0.0\"\n       processorArchitecture=\"X86\"\n       publicKeyToken=\"6595b64144ccf1df\"\n       language=\"*\"\n     />\n   </dependentAssembly>\n</dependency>\n</assembly>\n"
  },
  {
    "path": "win/vncconfig/vncconfig.exe.manifest64",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n<assemblyIdentity\n   version=\"4.0.0.26\"\n   processorArchitecture=\"AMD64\"\n   name=\"TigerVNC.vncconfig.exe\"\n   type=\"win32\"\n/>\n<description>.NET control deployment tool</description>\n<dependency>\n   <dependentAssembly>\n     <assemblyIdentity\n       type=\"win32\"\n       name=\"Microsoft.Windows.Common-Controls\"\n       version=\"6.0.0.0\"\n       processorArchitecture=\"AMD64\"\n       publicKeyToken=\"6595b64144ccf1df\"\n       language=\"*\"\n     />\n   </dependentAssembly>\n</dependency>\n</assembly>\n"
  },
  {
    "path": "win/vncconfig/vncconfig.rc",
    "content": "//Microsoft Developer Studio generated resource script.\n//\n#include \"resource.h\"\n#include \"resdefs.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"windows.h\"\n\n#ifndef IDC_STATIC\n#define IDC_STATIC -1\n#endif\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// English (U.K.) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)\n#ifdef _WIN32\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK\n#pragma code_page(1252)\n#endif //_WIN32\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"#include \"\"windows.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Icon\n//\n\n// Icon with lowest ID value placed first to ensure application icon\n// remains consistent on all systems.\nIDI_ICON                ICON    DISCARDABLE     \"vncconfig.ico\"\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Dialog\n//\n\nIDD_SECURITY DIALOG DISCARDABLE  0, 0, 180, 220\nSTYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Security\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    GROUPBOX\t\t\"Session encryption\", IDC_STATIC, 7,10,120,60\n    CONTROL\t\t\"None\", IDC_ENC_NONE, \"Button\", BS_AUTOCHECKBOX | WS_TABSTOP,\n\t\t\t10,20,50,15\n    CONTROL\t\t\"Anonymous TLS\", IDC_ENC_TLS, \"Button\",\n\t\t\tBS_AUTOCHECKBOX | WS_TABSTOP, 10,35,80,15\n    CONTROL\t\t\"TLS with X.509 certificates\", IDC_ENC_X509, \"Button\",\n\t\t\tBS_AUTOCHECKBOX | WS_TABSTOP, 10,50,110,15\n    GROUPBOX\t\t\"X.509 certificates\", IDC_STATIC, 7,75,185,30\n    PUSHBUTTON\t\t\"Load X.509 Certificate\", IDC_LOAD_CERT, 10,85,80,15\n    PUSHBUTTON\t\t\"Load X.509 Certificate key\", IDC_LOAD_CERTKEY, 90,85,100,15\n    GROUPBOX\t\t\"Authentication\", IDC_STATIC, 7,110,170,60\n    CONTROL\t\t\"None\", IDC_AUTH_NONE, \"Button\", BS_AUTOCHECKBOX | WS_TABSTOP,\n\t\t\t10,120,50,15\n    CONTROL\t\t\"Standard VNC\", IDC_AUTH_VNC, \"Button\",\n\t\t\tBS_AUTOCHECKBOX | WS_TABSTOP, 10,135,80,15\n    PUSHBUTTON\t\t\"Configure\", IDC_AUTH_VNC_PASSWD, 100,135,61,15\n/*\n    CONTROL\t\t\"Plaintext\", IDC_AUTH_PLAIN, \"Button\",\n\t\t\tBS_AUTOCHECKBOX | WS_TABSTOP, 10,150,70,15\n*/\n    CONTROL\t\t\"Prompt local user to accept connections\",\n\t\t\tIDC_QUERY_CONNECT, \"Button\", BS_AUTOCHECKBOX | WS_TABSTOP,\n\t\t\t7,170,181,15\n    CONTROL\t\t\"Only prompt when there is a user logged on\",\n\t\t\tIDC_QUERY_LOGGED_ON, \"Button\", BS_AUTOCHECKBOX | \n\t\t\tWS_TABSTOP,20,185,166,15\nEND\n\nIDD_CONNECTIONS DIALOG DISCARDABLE  0, 0, 218, 198\nSTYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Connections\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    CONTROL         \"Accept connections on port:\",IDC_RFB_ENABLE,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,7,10,138,15\n    EDITTEXT        IDC_PORT,150,10,61,15,ES_AUTOHSCROLL | ES_NUMBER\n    LTEXT           \"Disconnect idle clients after (seconds):\",IDC_STATIC,7,\n                    25,138,15,SS_CENTERIMAGE\n    EDITTEXT        IDC_IDLE_TIMEOUT,150,25,61,15,ES_AUTOHSCROLL | ES_NUMBER\n    GROUPBOX        \"Access control\",IDC_STATIC,7,55,204,135\n    CONTROL         \"Only accept connections from the local machine\",\n                    IDC_LOCALHOST,\"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,15,\n                    70,190,15\n    LISTBOX         IDC_HOSTS,15,90,130,95,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | \n                    WS_TABSTOP\n    PUSHBUTTON      \"&Add\",IDC_HOST_ADD,150,90,55,15\n    PUSHBUTTON      \"&Remove\",IDC_HOST_REMOVE,150,110,55,15\n    PUSHBUTTON      \"Move Up\",IDC_HOST_UP,150,130,55,15\n    PUSHBUTTON      \"Move Down\",IDC_HOST_DOWN,150,150,55,15\n    PUSHBUTTON      \"&Edit\",IDC_HOST_EDIT,150,170,55,15\nEND\n\nIDD_HOOKING DIALOG DISCARDABLE  0, 0, 197, 101\nSTYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Capture method\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    CONTROL         \"Poll for changes to the desktop\",IDC_USEPOLLING,\"Button\",\n                    BS_AUTORADIOBUTTON | WS_GROUP,7,10,183,15\n    CONTROL         \"Use VNC hooks to track changes\",IDC_USEHOOKS,\"Button\",\n                    BS_AUTORADIOBUTTON,7,25,183,15\n    CONTROL         \"Poll console windows for updates\",IDC_POLLCONSOLES,\n                    \"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,25,40,165,15\n    CONTROL         \"Capture alpha-blended windows\",IDC_CAPTUREBLT,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,7,55,183,15\nEND\n\nIDD_AUTH_VNC_PASSWD DIALOG DISCARDABLE  0, 0, 212, 70\nSTYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | \n    WS_SYSMENU\nCAPTION \"VNC server password\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    LTEXT           \"New password:\",IDC_STATIC,7,10,63,15\n    EDITTEXT        IDC_PASSWORD1,75,10,130,15,ES_PASSWORD | ES_AUTOHSCROLL\n    LTEXT           \"Confirm password:\",IDC_STATIC,7,30,63,14\n    EDITTEXT        IDC_PASSWORD2,75,30,130,14,ES_PASSWORD | ES_AUTOHSCROLL\n    DEFPUSHBUTTON   \"OK\",IDOK,100,50,50,15\n    PUSHBUTTON      \"Cancel\",IDCANCEL,155,50,50,15\nEND\n\nIDD_LEGACY DIALOG DISCARDABLE  0, 0, 166, 92\nSTYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Legacy\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    PUSHBUTTON      \"&Import VNC 3.3 settings\",IDC_LEGACY_IMPORT,7,10,92,20\n    CONTROL         \"Only use protocol version 3.3\",IDC_PROTOCOL_3_3,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,7,35,152,15\nEND\n\nIDD_CONN_HOST DIALOG DISCARDABLE  0, 0, 225, 57\nSTYLE DS_SYSMODAL | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION\nCAPTION \"Specify host IP address pattern\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    EDITTEXT        IDC_HOST_PATTERN,65,5,100,15,ES_AUTOHSCROLL\n    CONTROL         \"&Allow\",IDC_ALLOW,\"Button\",BS_AUTORADIOBUTTON | \n                    WS_GROUP,7,5,53,15\n    CONTROL         \"&Deny\",IDC_DENY,\"Button\",BS_AUTORADIOBUTTON,7,20,53,15\n    CONTROL         \"Query\",IDC_QUERY,\"Button\",BS_AUTORADIOBUTTON,7,35,53,15\n    DEFPUSHBUTTON   \"OK\",IDOK,115,35,50,15\n    PUSHBUTTON      \"Cancel\",IDCANCEL,170,35,50,15\n    LTEXT           \"e.g. 192.168.0.0/16\",IDC_STATIC,65,20,100,15\nEND\n\nIDD_SHARING DIALOG DISCARDABLE  0, 0, 186, 95\nSTYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Sharing\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    CONTROL         \"Always treat new connections as shared\",\n                    IDC_SHARE_ALWAYS,\"Button\",BS_AUTORADIOBUTTON | WS_GROUP,\n                    7,10,172,15\n    CONTROL         \"Never treat new connections as shared\",IDC_SHARE_NEVER,\n                    \"Button\",BS_AUTORADIOBUTTON,7,25,172,15\n    CONTROL         \"Use client's preferred sharing setting\",\n                    IDC_SHARE_CLIENT,\"Button\",BS_AUTORADIOBUTTON,7,40,172,15\n    CONTROL         \"Non-shared connections replace existing ones\",\n                    IDC_DISCONNECT_CLIENTS,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,7,55,172,15\nEND\n\nIDD_INPUTS DIALOG DISCARDABLE  0, 0, 186, 119\nSTYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Inputs\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    CONTROL         \"Accept pointer events from clients\",IDC_ACCEPT_PTR,\n                    \"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,7,10,172,15\n    CONTROL         \"Accept keyboard events from clients\",IDC_ACCEPT_KEYS,\n                    \"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,7,25,172,15\n    CONTROL         \"Send raw keyboard events to applications\",IDC_RAW_KEYBOARD,\n                    \"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,7,40,172,15\n    CONTROL         \"Accept clipboard updates from clients\",\n                    IDC_ACCEPT_CUTTEXT,\"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,\n                    7,55,172,15\n    CONTROL         \"Send clipboard updates to clients\",IDC_SEND_CUTTEXT,\n                    \"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,7,70,172,15\n    CONTROL         \"Allow input events to affect the screen-saver\",\n                    IDC_AFFECT_SCREENSAVER,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,7,85,172,15\n    CONTROL         \"Disable local inputs while server is in use\",\n                    IDC_DISABLE_LOCAL_INPUTS,\"Button\",BS_AUTOCHECKBOX | \n                    WS_TABSTOP,7,110,172,15\nEND\n\nIDD_ABOUT DIALOG DISCARDABLE  0, 0, 300, 92\nSTYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | \n    WS_SYSMENU\nCAPTION \"About TigerVNC config for Windows\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    DEFPUSHBUTTON   \"OK\",IDOK,245,70,47,15\n    ICON            IDI_ICON,IDC_STATIC,7,7,20,20\n    LTEXT           \">appname<\",IDC_DESCRIPTION,40,7,125,18\n    LTEXT           \">version<\",IDC_VERSION,165,7,77,18\n    LTEXT           \">buildtime<\",IDC_BUILDTIME,40,25,202,15\n    LTEXT           \">copyright<\",IDC_COPYRIGHT,40,40,256,15\n    LTEXT           \"See https://www.tigervnc.org for more information on TigerVNC.\",\n                    IDC_STATIC,40,55,202,15\nEND\n\nIDD_DESKTOP DIALOG DISCARDABLE  0, 0, 185, 137\nSTYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CONTROL | WS_POPUP | WS_CAPTION | \n    WS_SYSMENU\nCAPTION \"Desktop\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    GROUPBOX        \"While connected\",IDC_STATIC,7,5,171,45\n    CONTROL         \"Remove wallpaper\",IDC_REMOVE_WALLPAPER,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,15,15,155,15\n    CONTROL         \"Disable user interface effects\",IDC_DISABLE_EFFECTS,\n                    \"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,15,30,155,14\n    GROUPBOX        \"When last client disconnects\",IDC_STATIC,7,55,171,60\n    CONTROL         \"Do nothing\",IDC_DISCONNECT_NONE,\"Button\",\n                    BS_AUTORADIOBUTTON,15,65,155,15\n    CONTROL         \"Lock workstation\",IDC_DISCONNECT_LOCK,\"Button\",\n                    BS_AUTORADIOBUTTON,15,80,155,15\n    CONTROL         \"Logoff user\",IDC_DISCONNECT_LOGOFF,\"Button\",\n                    BS_AUTORADIOBUTTON,15,95,155,15\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// DESIGNINFO\n//\n\n#ifdef APSTUDIO_INVOKED\nGUIDELINES DESIGNINFO DISCARDABLE \nBEGIN\n    IDD_AUTHENTICATION, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 186\n        VERTGUIDE, 20\n        VERTGUIDE, 49\n        VERTGUIDE, 120\n        VERTGUIDE, 125\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 128\n        HORZGUIDE, 10\n        HORZGUIDE, 25\n        HORZGUIDE, 30\n        HORZGUIDE, 45\n        HORZGUIDE, 50\n        HORZGUIDE, 65\n        HORZGUIDE, 70\n        HORZGUIDE, 85\n        HORZGUIDE, 90\n        HORZGUIDE, 105\n        HORZGUIDE, 110\n        HORZGUIDE, 125\n    END\n\n    IDD_CONNECTIONS, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 211\n        VERTGUIDE, 15\n        VERTGUIDE, 145\n        VERTGUIDE, 150\n        VERTGUIDE, 205\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 191\n        HORZGUIDE, 10\n        HORZGUIDE, 25\n        HORZGUIDE, 40\n        HORZGUIDE, 55\n        HORZGUIDE, 70\n        HORZGUIDE, 85\n        HORZGUIDE, 90\n        HORZGUIDE, 105\n        HORZGUIDE, 110\n        HORZGUIDE, 125\n        HORZGUIDE, 130\n        HORZGUIDE, 145\n        HORZGUIDE, 150\n        HORZGUIDE, 165\n        HORZGUIDE, 170\n        HORZGUIDE, 185\n        HORZGUIDE, 190\n    END\n\n    IDD_HOOKING, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 190\n        VERTGUIDE, 25\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 94\n        HORZGUIDE, 10\n        HORZGUIDE, 25\n        HORZGUIDE, 40\n        HORZGUIDE, 55\n        HORZGUIDE, 70\n        HORZGUIDE, 85\n    END\n\n    IDD_AUTH_VNC_PASSWD, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 205\n        VERTGUIDE, 70\n        VERTGUIDE, 75\n        VERTGUIDE, 90\n        VERTGUIDE, 100\n        VERTGUIDE, 150\n        VERTGUIDE, 155\n        VERTGUIDE, 205\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 65\n        HORZGUIDE, 10\n        HORZGUIDE, 25\n        HORZGUIDE, 30\n        HORZGUIDE, 44\n        HORZGUIDE, 50\n        HORZGUIDE, 65\n    END\n\n    IDD_LEGACY, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 159\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 85\n        HORZGUIDE, 10\n        HORZGUIDE, 30\n        HORZGUIDE, 35\n        HORZGUIDE, 50\n    END\n\n    IDD_CONN_HOST, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 220\n        VERTGUIDE, 60\n        VERTGUIDE, 65\n        VERTGUIDE, 115\n        VERTGUIDE, 165\n        VERTGUIDE, 170\n        TOPMARGIN, 5\n        BOTTOMMARGIN, 50\n        HORZGUIDE, 20\n        HORZGUIDE, 35\n    END\n\n    IDD_SHARING, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 179\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 88\n        HORZGUIDE, 10\n        HORZGUIDE, 25\n        HORZGUIDE, 40\n        HORZGUIDE, 55\n        HORZGUIDE, 70\n    END\n\n    IDD_INPUTS, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 179\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 112\n        HORZGUIDE, 10\n        HORZGUIDE, 25\n        HORZGUIDE, 40\n        HORZGUIDE, 55\n        HORZGUIDE, 70\n        HORZGUIDE, 85\n        HORZGUIDE, 95\n        HORZGUIDE, 110\n    END\n\n    IDD_ABOUT, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 242\n        VERTGUIDE, 40\n        VERTGUIDE, 165\n        VERTGUIDE, 195\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 85\n        HORZGUIDE, 7\n        HORZGUIDE, 25\n        HORZGUIDE, 40\n        HORZGUIDE, 55\n        HORZGUIDE, 70\n    END\n\n    IDD_DESKTOP, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 182\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 32\n    END\nEND\n#endif    // APSTUDIO_INVOKED\n\n\n#ifndef _MAC\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION __RCVERSION\n PRODUCTVERSION __RCVERSION\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS 0x40004L\n FILETYPE 0x1L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"080904b0\"\n        BEGIN\n            VALUE \"Comments\", \"\\0\"\n            VALUE \"CompanyName\", \"TigerVNC team\\0\"\n            #ifdef WIN64\n            VALUE \"FileDescription\", \"TigerVNC server configuration applet for Win64\\0\"\n            VALUE \"ProductName\", \"TigerVNC server configuration applet for Win64\\0\"\n            #else\n            VALUE \"FileDescription\", \"TigerVNC server configuration applet for Win32\\0\"\n            VALUE \"ProductName\", \"TigerVNC server configuration applet for Win32\\0\"\n            #endif\n            VALUE \"FileVersion\", __RCVERSIONSTR\n            VALUE \"InternalName\", \"vncconfig\\0\"\n            VALUE \"LegalCopyright\", \"Copyright (C) 1999-2026 TigerVNC team and many others (see README.rst)\\0\"\n            VALUE \"LegalTrademarks\", \"TigerVNC\\0\"\n            VALUE \"OriginalFilename\", \"vncconfig.exe\\0\"\n            VALUE \"PrivateBuild\", \"\\0\"\n            VALUE \"ProductVersion\", __VERSIONSTR\n            VALUE \"SpecialBuild\", \"\\0\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x809, 1200\n    END\nEND\n\n#endif    // !_MAC\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// 24\n//\n\n#ifdef WIN64\nIDR_MANIFEST            24      DISCARDABLE     \"vncconfig.exe.manifest64\"\n#else\nIDR_MANIFEST            24      DISCARDABLE     \"vncconfig.exe.manifest\"\n#endif\n#endif    // English (U.K.) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "win/winvnc/AddNewClientDialog.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- AddnewClientDialog.h\n\n#ifndef __WINVNC_ADD_NEW_CLIENT_DIALOG_H__\n#define __WINVNC_ADD_NEW_CLIENT_DIALOG_H__\n\n#include <winvnc/resource.h>\n#include <rfb_win32/Dialog.h>\n\nnamespace winvnc {\n\n  class AddNewClientDialog : public rfb::win32::Dialog {\n  public:\n    AddNewClientDialog() : Dialog(GetModuleHandle(nullptr)) {}\n    // - Show the dialog and return true if OK was clicked,\n    //   false in case of error or Cancel\n    virtual bool showDialog() {\n      return Dialog::showDialog(MAKEINTRESOURCE(IDD_ADD_NEW_CLIENT));\n    }\n    const char* getHostName() const {return hostName.c_str();}\n  protected:\n\n    // Dialog methods (protected)\n    void initDialog() override {\n      if (!hostName.empty())\n        setItemString(IDC_HOST, hostName.c_str());\n    }\n    bool onOk() override {\n      hostName = getItemString(IDC_HOST);\n      return true;\n    }\n\n    std::string hostName;\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/winvnc/CMakeLists.txt",
    "content": "add_executable(winvnc4 WIN32\n  buildTime.cxx\n  ControlPanel.cxx\n  ManagedListener.cxx\n  QueryConnectDialog.cxx\n  STrayIcon.cxx\n  VNCServerService.cxx\n  VNCServerWin32.cxx\n  winvnc.cxx\n  winvnc.rc)\n\ntarget_include_directories(winvnc4 PUBLIC ${CMAKE_BINARY_DIR}/win)\ntarget_include_directories(winvnc4 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\ntarget_link_libraries(winvnc4 rfb rfb_win32 network rdr ws2_32.lib)\n\ninstall(TARGETS winvnc4\n  RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}\n)\n"
  },
  {
    "path": "win/winvnc/ControlPanel.cxx",
    "content": "// ControlPanel.cxx: implementation of the ControlPanel class.\n//\n//////////////////////////////////////////////////////////////////////\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include \"ControlPanel.h\"\n\n//////////////////////////////////////////////////////////////////////\n// Construction/Destruction\n//////////////////////////////////////////////////////////////////////\n\nusing namespace winvnc;\n\nbool ControlPanel::showDialog()\n{\n  return Dialog::showDialog(MAKEINTRESOURCE(IDD_CONTROL_PANEL), nullptr);\n}\n\nvoid ControlPanel::initDialog()\n{\n  const char *ColumnsStrings[] = {\n    \"IP address\",\n    \"Status\"\n  };\n  InitLVColumns(IDC_LIST_CONNECTIONS, handle, 120, 2, (char **)ColumnsStrings,\n                LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,\n                LVS_EX_FULLROWSELECT, LVCFMT_LEFT);\n  SendCommand(4, -1);\n}\n\nbool ControlPanel::onCommand(int item, int /*cmd*/)\n{\n  switch (item) {\n  case IDC_PROPERTIES:\n    SendMessage(m_hSTIcon, WM_COMMAND, ID_OPTIONS, 0);\n    return false;\n  case IDC_ADD_CLIENT:\n    SendMessage(m_hSTIcon, WM_COMMAND, ID_CONNECT, 0);\n    return false;\n  case IDC_KILL_ALL:\n    {\n      SendCommand(2, -1);\n      return false;\n    }\n  case IDC_KILL_SEL_CLIENT:\n    {     \n      SendCommand(3, 3);\n      return false;\n    }\n  case IDC_VIEW_ONLY:\n    {     \n      SendCommand(3, 1);\n      return false;\n    }\n  case IDC_FULL_CONTROL:\n    {     \n      SendCommand(3, 0);\n      return false;\n    }\n  case IDC_STOP_UPDATE:\n    {     \n      stop_updating = true;\n      EndDialog(handle, 0);\n      return false;\n    }\n  case IDC_DISABLE_CLIENTS:\n    {   \n      ListConnStatus.setDisable(isItemChecked(IDC_DISABLE_CLIENTS));\n      SendCommand(3, -1);\n      return false;\n    }\n  }\n  return false;\n  \n}\n\nvoid ControlPanel::UpdateListView(ListConnInfo* LCInfo)\n{\n  getSelConnInfo();\n  DeleteAllLVItem(IDC_LIST_CONNECTIONS, handle);\n  setItemChecked(IDC_DISABLE_CLIENTS, LCInfo->getDisable());\n\n  if(LCInfo->Empty()) \n    return;\n\n  ListConn.Copy(LCInfo);\n\n  const char* ItemString[2];\n  int i = 0;\n\n  for (ListConn.iBegin(); !ListConn.iEnd(); ListConn.iNext()) {\n    ListConn.iGetCharInfo(ItemString);\n    InsertLVItem(IDC_LIST_CONNECTIONS, handle, i, (char **) ItemString, 2);\n    for (ListSelConn.iBegin(); !ListSelConn.iEnd(); ListSelConn.iNext()) {\n      if (ListSelConn.iGetConn() == ListConn.iGetConn())\n        SelectLVItem(IDC_LIST_CONNECTIONS, handle, i);\n    }\n    i++;\n  } \n}\n\nBOOL ControlPanel::dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM /*lParam*/)\n{\n  switch (msg) {\n  case WM_INITDIALOG:\n    handle = hwnd;\n    initDialog();\n    return TRUE;\n  case WM_DESTROY:\n    if (stop_updating) {\n      stop_updating = false;\n      SendCommand(3, 2);\n    }\n    return TRUE;\n  case WM_COMMAND:\n    switch (LOWORD(wParam)) {\n    case IDCANCEL:\n      handle = nullptr;\n      EndDialog(hwnd, 0);\n      return TRUE;\n    default:\n      return onCommand(LOWORD(wParam), HIWORD(wParam));\n    }\n  }\n  return FALSE;\n}\n\nvoid ControlPanel::getSelConnInfo()\n{\n  int i = 0;\n  ListSelConn.Clear();\n  if(ListConn.Empty()) return;\n  for (ListConn.iBegin(); !ListConn.iEnd(); ListConn.iNext()) {\n    if (IsSelectedLVItem(IDC_LIST_CONNECTIONS, handle, i))\n      ListSelConn.iAdd(&ListConn);\n    i++;\n  }\n}\n\nvoid ControlPanel::SendCommand(DWORD command, int data)\n{\n  COPYDATASTRUCT copyData;\n  copyData.dwData = command;\n  copyData.cbData = 0;\n  copyData.lpData = nullptr;\n  getSelConnInfo();\n  if (data != -1) {\n    ListConnStatus.Copy(&ListSelConn);\n    ListConnStatus.setAllStatus(data);\n    ListConnStatus.setDisable(isItemChecked(IDC_DISABLE_CLIENTS));\n  } else {\n    ListConnStatus.Clear();\n  }\n  SendMessage(m_hSTIcon, WM_COPYDATA, 0, (LPARAM)&copyData);\n}\n\nControlPanel::~ControlPanel()\n{\n  \n}\n"
  },
  {
    "path": "win/winvnc/ControlPanel.h",
    "content": "// ControlPanel.h: interface for the ControlPanel class.\n//\n//////////////////////////////////////////////////////////////////////\n\n#ifndef AFX_CONTROLPANEL_H__\n#define AFX_CONTROLPANEL_H__\n\n\n#pragma once\n\n\n#include <list>\n#include <winvnc/resource.h>\n#include <winvnc/ListConnInfo.h>\n#include <rfb_win32/Dialog.h>\n#include <rfb_win32/ListViewControl.h>\n#include <rfb_win32/Win32Util.h>\n\nnamespace winvnc {\n  \n  class ControlPanel : rfb::win32::Dialog, rfb::win32::ListViewControl {\n  public:\n    ControlPanel(HWND hSTIcon) : Dialog(GetModuleHandle(nullptr)), ListViewControl(){\n      m_hSTIcon = hSTIcon;\n      stop_updating = false;\n    };\n    virtual bool showDialog();\n    void initDialog() override;\n    bool onCommand(int item, int cmd) override;\n    void UpdateListView(ListConnInfo* LCInfo);\n    HWND GetHandle() {return handle;};\n    void SendCommand(DWORD command, int data);\n    ~ControlPanel();\n    ListConnInfo ListConnStatus;\n  protected: \n    BOOL dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) override;\n    void getSelConnInfo();\n    HWND m_hSTIcon;\n    ListConnInfo ListConn;\n    ListConnInfo ListSelConn;\n    bool stop_updating;\n  };\n};\n\n#endif  \n"
  },
  {
    "path": "win/winvnc/ListConnInfo.h",
    "content": "/* Copyright (C) 2002-2003 RealVNC Ltd.  All Rights Reserved.\n *    \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n\n#ifndef __RFB_LISTCONNINFO_INCLUDED__\n#define __RFB_LISTCONNINFO_INCLUDED__\n\n#include <list>\n#include <string>\n\nnamespace winvnc {\n\n  struct ListConnInfo  {\n    ListConnInfo() : disableClients(false) {}\n\n    void Clear() {\n      conn.clear();\n      IP_address.clear();\n      status.clear();\n    }\n\n    bool Empty() { return conn.empty();}\n\n    void iBegin() {\n      ci = conn.begin();\n      Ii = IP_address.begin();\n      si = status.begin();\n    }\n\n    bool iEnd() { return ci == conn.end();}\n\n    void iNext() {\n      ci++;\n      Ii++;\n      si++;\n    }\n\n    void addInfo(void* Conn, const char* IP, int Status) {\n      conn.push_back(Conn);\n      IP_address.push_back(IP);\n      status.push_back(Status);\n    }\n\n    void iGetCharInfo(const char* buf[2]) {\n      buf[0] = Ii->c_str();\n      switch (*si) {\n      case 0:\n        buf[1] = \"Full control\";\n        break;\n      case 1:\n        buf[1] = \"View only\";\n        break;\n      case 2:\n        buf[1] = \"Stop updating\";\n        break;\n      default:\n        buf[1] = \"Unknown\";\n      }\n    }\n\n    void* iGetConn() { return *ci;}\n\n    int iGetStatus() { return *si;}\n\n    void iSetStatus(int istatus) { *si = istatus;}\n\n    void Copy(ListConnInfo* InputList) {\n      Clear();\n      if (InputList->Empty()) return;\n      for (InputList->iBegin(); !InputList->iEnd(); InputList->iNext()) {\n        iAdd(InputList);\n      }\n      setDisable(InputList->getDisable());\n    }\n\n    void iAdd (ListConnInfo* InputList) {\n      const char* buf[2];\n      InputList->iGetCharInfo(buf);\n      addInfo(InputList->iGetConn(), buf[0], InputList->iGetStatus());\n    }\n\n    void setDisable(bool disable) {disableClients = disable;}\n\n    bool getDisable() {return disableClients;}\n\n    void setAllStatus(int stat) {\n      std::list<int>::iterator st;\n      for (st = status.begin(); st != status.end(); st++)\n        *st = stat;\n    }\n\n  private:\n    std::list<void*> conn;\n    std::list<std::string> IP_address;\n    std::list<int> status;\n    std::list<void*>::iterator ci;\n    std::list<std::string>::iterator Ii;\n    std::list<int>::iterator si;\n    bool disableClients;\n  };\n};\n#endif\n\n"
  },
  {
    "path": "win/winvnc/ManagedListener.cxx",
    "content": "/* Copyright (C) 2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <core/LogWriter.h>\n\n#include <winvnc/ManagedListener.h>\n\nusing namespace winvnc;\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\n\nstatic LogWriter vlog(\"ManagedListener\");\n\n\nManagedListener::ManagedListener(SocketManager* mgr)\n: filter(nullptr), manager(mgr), addrChangeNotifier(nullptr), server(nullptr), port(0), localOnly(false) {\n}\n\nManagedListener::~ManagedListener() {\n  if (!sockets.empty()) {\n    std::list<network::SocketListener*>::iterator iter;\n    for (iter = sockets.begin(); iter != sockets.end(); ++iter)\n      manager->remListener(*iter);\n    sockets.clear();\n  }\n  delete filter;\n}\n\n\nvoid ManagedListener::setServer(rfb::VNCServer* svr) {\n  if (svr == server)\n    return;\n  vlog.info(\"Set server to %p\", svr);\n  server = svr;\n  refresh();\n}\n\nvoid ManagedListener::setPort(int port_, bool localOnly_) {\n  if ((port_ == port) && (localOnly == localOnly_))\n    return;\n  vlog.info(\"Set port to %d\", port_);\n  port = port_;\n  localOnly = localOnly_;\n  refresh();\n}\n\nvoid ManagedListener::setFilter(const char* filterStr) {\n  vlog.info(\"Set filter to %s\", filterStr);\n  delete filter;\n  filter = new network::TcpFilter(filterStr);\n  if (!sockets.empty() && !localOnly) {\n    std::list<network::SocketListener*>::iterator iter;\n    for (iter = sockets.begin(); iter != sockets.end(); ++iter)\n      (*iter)->setFilter(filter);\n  }\n}\n\nvoid ManagedListener::setAddressChangeNotifier(SocketManager::AddressChangeNotifier* acn) {\n  if (acn == addrChangeNotifier)\n    return;\n  addrChangeNotifier = acn;\n  refresh();\n}\n\nbool ManagedListener::isListening() {\n  return !sockets.empty();\n}\n\nvoid ManagedListener::refresh() {\n  std::list<network::SocketListener*>::iterator iter;\n  if (!sockets.empty()) {\n    for (iter = sockets.begin(); iter != sockets.end(); ++iter)\n      manager->remListener(*iter);\n    sockets.clear();\n  }\n  if (!server)\n    return;\n  try {\n    if (port) {\n      if (localOnly)\n        network::createLocalTcpListeners(&sockets, port);\n      else\n        network::createTcpListeners(&sockets, nullptr, port);\n    }\n  } catch (std::exception& e) {\n    vlog.error(\"%s\", e.what());\n  }\n  if (!sockets.empty()) {\n    if (!localOnly) {\n      for (iter = sockets.begin(); iter != sockets.end(); ++iter)\n        (*iter)->setFilter(filter);\n    }\n    try {\n      for (iter = sockets.begin(); iter != sockets.end(); ++iter)\n        manager->addListener(*iter, server, addrChangeNotifier);\n    } catch (...) {\n      std::list<network::SocketListener*>::iterator iter2;\n      for (iter2 = sockets.begin(); iter2 != iter; ++iter2)\n        manager->remListener(*iter2);\n      for (; iter2 != sockets.end(); ++iter2)\n        delete *iter;\n      sockets.clear();\n      throw;\n    }\n  }\n}\n"
  },
  {
    "path": "win/winvnc/ManagedListener.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __VNCSERVER_MANAGED_LISTENER_H__\n#define __VNCSERVER_MANAGED_LISTENER_H__\n\n#include <winsock2.h>\n#include <network/TcpSocket.h>\n#include <rfb_win32/SocketManager.h>\n\nnamespace winvnc {\n\n  // -=- ManagedListener\n  //     Wrapper class which simplifies the management of a listening socket\n  //     on a specified port, attached to a SocketManager and VNCServer.\n  //     Reopens sockets & reconfigures filters & callbacks as appropriate.\n  //     Handles addition/removal of Listeners from SocketManager internally.\n\n  class ManagedListener {\n  public:\n    ManagedListener(rfb::win32::SocketManager* mgr);\n    ~ManagedListener();\n    \n    void setServer(rfb::VNCServer* svr);\n    void setPort(int port, bool localOnly=false);\n    void setFilter(const char* filter);\n    void setAddressChangeNotifier(rfb::win32::SocketManager::AddressChangeNotifier* acn);\n\n    bool isListening();\n\n  protected:\n    void refresh();\n    std::list<network::SocketListener*> sockets;\n    network::TcpFilter* filter;\n    rfb::win32::SocketManager* manager;\n    rfb::win32::SocketManager::AddressChangeNotifier* addrChangeNotifier;\n    rfb::VNCServer* server;\n    int port;\n    bool localOnly;\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/winvnc/QueryConnectDialog.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <winvnc/VNCServerWin32.h>\n#include <winvnc/QueryConnectDialog.h>\n#include <winvnc/resource.h>\n\n#include <core/LogWriter.h>\n\n#include <rfb_win32/Win32Util.h>\n#include <rfb_win32/Service.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\nusing namespace winvnc;\n\nstatic LogWriter vlog(\"QueryConnectDialog\");\n\nstatic IntParameter timeout(\"QueryConnectTimeout\",\n                            \"Number of seconds to show the Accept connection dialog before \"\n                            \"rejecting the connection\",\n                            10, 0, INT_MAX);\n\n\n// - Visible methods\n\nQueryConnectDialog::QueryConnectDialog(network::Socket* sock_,\n                                       const char* userName_,\n                                       VNCServerWin32* s)\n: Dialog(GetModuleHandle(nullptr)),\n  thread(nullptr), sock(sock_), peerIp(sock->getPeerAddress()),\n  userName(userName_?userName_:\"\"),\n  approve(false), server(s) {\n}\n\nQueryConnectDialog::~QueryConnectDialog()\n{\n  if (thread != nullptr) {\n    thread->join();\n    delete thread;\n  }\n}\n\nvoid QueryConnectDialog::startDialog() {\n  thread = new std::thread(&QueryConnectDialog::worker, this);\n}\n\n\n// - Thread overrides\n\nvoid QueryConnectDialog::worker() {\n  countdown = timeout;\n  try {\n    if (desktopChangeRequired() && !changeDesktop())\n      throw std::runtime_error(\"changeDesktop failed\");\n    approve = Dialog::showDialog(MAKEINTRESOURCE(IDD_QUERY_CONNECT));\n    server->queryConnectionComplete();\n  } catch (...) {\n    server->queryConnectionComplete();\n    throw;\n  }\n}\n\n\n// - Dialog overrides\n\nvoid QueryConnectDialog::initDialog() {\n  if (!SetTimer(handle, 1, 1000, nullptr))\n    throw core::win32_error(\"SetTimer\", GetLastError());\n  setItemString(IDC_QUERY_HOST, peerIp.c_str());\n  if (userName.empty())\n    userName = \"(anonymous)\";\n  setItemString(IDC_QUERY_USER, userName.c_str());\n  setCountdownLabel();\n}\n\nvoid QueryConnectDialog::setCountdownLabel() {\n  char buf[16];\n  sprintf(buf, \"%d\", countdown);\n  setItemString(IDC_QUERY_COUNTDOWN, buf);\n}\n\nBOOL QueryConnectDialog::dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {\n  if (msg == WM_TIMER) {\n    if (--countdown == 0 || desktopChangeRequired()) {\n      DestroyWindow(hwnd);\n    } else {\n      setCountdownLabel();\n    }\n    return TRUE;\n  } else {\n    return Dialog::dialogProc(hwnd, msg, wParam, lParam);\n  }\n}\n"
  },
  {
    "path": "win/winvnc/QueryConnectDialog.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- QueryConnectDialog.h\n\n#ifndef __WINVNC_QUERY_CONNECT_DIALOG_H__\n#define __WINVNC_QUERY_CONNECT_DIALOG_H__\n\n#include <thread>\n\n#include <rfb_win32/Dialog.h>\n\nnamespace network { class Socket; }\n\nnamespace winvnc {\n\n  class VNCServerWin32;\n\n  class QueryConnectDialog : rfb::win32::Dialog {\n  public:\n    QueryConnectDialog(network::Socket* sock, const char* userName, VNCServerWin32* s);\n    ~QueryConnectDialog();\n    virtual void startDialog();\n    network::Socket* getSock() {return sock;}\n    bool isAccepted() const {return approve;}\n  protected:\n    // Thread methods\n    void worker();\n\n    // Dialog methods (protected)\n    void initDialog() override;\n    BOOL dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) override;\n\n    // Custom internal methods\n    void setCountdownLabel();\n\n    std::thread* thread;\n    int countdown;\n    network::Socket* sock;\n    std::string peerIp;\n    std::string userName;\n    bool approve;\n    VNCServerWin32* server;\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/winvnc/STrayIcon.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WinVNC Version 4.0 Tray Icon implementation\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <winvnc/STrayIcon.h>\n#include <winvnc/VNCServerService.h>\n#include <winvnc/resource.h>\n\n#include <core/Configuration.h>\n#include <core/LogWriter.h>\n\n#include <rfb_win32/LaunchProcess.h>\n#include <rfb_win32/TrayIcon.h>\n#include <rfb_win32/AboutDialog.h>\n#include <rfb_win32/MsgBox.h>\n#include <rfb_win32/Service.h>\n#include <rfb_win32/CurrentUser.h>\n\n#include <winvnc/ControlPanel.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\nusing namespace winvnc;\n\nstatic LogWriter vlog(\"STrayIcon\");\n\nBoolParameter STrayIconThread::disableOptions(\"DisableOptions\", \"Disable the Options entry in the VNC server tray menu.\", false);\nBoolParameter STrayIconThread::disableClose(\"DisableClose\", \"Disable the Close entry in the VNC server tray menu.\", false);\n\n\n//\n// -=- AboutDialog global values\n//\n\nconst WORD rfb::win32::AboutDialog::DialogId = IDD_ABOUT;\nconst WORD rfb::win32::AboutDialog::Copyright = IDC_COPYRIGHT;\nconst WORD rfb::win32::AboutDialog::Version = IDC_VERSION;\nconst WORD rfb::win32::AboutDialog::BuildTime = IDC_BUILDTIME;\nconst WORD rfb::win32::AboutDialog::Description = IDC_DESCRIPTION;\n\n\n//\n// -=- Internal tray icon class\n//\n\nconst UINT WM_SET_TOOLTIP = WM_USER + 1;\n\nnamespace winvnc {\n\nclass STrayIcon : public TrayIcon {\npublic:\n  STrayIcon(STrayIconThread& t) :\n    vncConfig(\"vncconfig.exe\", isServiceProcess() ? \"-noconsole -service\" : \"-noconsole\"),\n    vncConnect(\"winvnc4.exe\", \"-noconsole -connect\"), thread(t) {\n\n    // ***\n    SetWindowText(getHandle(), \"winvnc::IPC_Interface\");\n    // ***\n\n    SetTimer(getHandle(), 1, 3000, nullptr);\n    PostMessage(getHandle(), WM_TIMER, 1, 0);\n    PostMessage(getHandle(), WM_SET_TOOLTIP, 0, 0);\n    CPanel = new ControlPanel(getHandle());\n  }\n\n  LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) override {\n    switch(msg) {\n\n    case WM_USER:\n      {\n        bool userKnown = CurrentUserToken().canImpersonate();\n        bool allowOptions = !STrayIconThread::disableOptions && userKnown;\n        bool allowClose = !STrayIconThread::disableClose && userKnown;\n\n        switch (lParam) {\n        case WM_LBUTTONDBLCLK:\n          SendMessage(getHandle(), WM_COMMAND, ID_CONTR0L_PANEL, 0);\n          break;\n        case WM_RBUTTONUP:\n          HMENU menu = LoadMenu(GetModuleHandle(nullptr), MAKEINTRESOURCE(thread.menu));\n          HMENU trayMenu = GetSubMenu(menu, 0);\n\n\n          // Default item is Options, if available, or About if not\n          SetMenuDefaultItem(trayMenu, ID_CONTR0L_PANEL, FALSE);\n          \n          // Enable/disable options as required\n          EnableMenuItem(trayMenu, ID_OPTIONS, (!allowOptions ? MF_GRAYED : MF_ENABLED) | MF_BYCOMMAND);\n          EnableMenuItem(trayMenu, ID_CONNECT, (!userKnown ? MF_GRAYED : MF_ENABLED) | MF_BYCOMMAND);\n          EnableMenuItem(trayMenu, ID_CLOSE, (!allowClose ? MF_GRAYED : MF_ENABLED) | MF_BYCOMMAND);\n\n          thread.server.getClientsInfo(&LCInfo);\n          CheckMenuItem(trayMenu, ID_DISABLE_NEW_CLIENTS, (LCInfo.getDisable() ? MF_CHECKED : MF_UNCHECKED) | MF_BYCOMMAND);\n\n          // SetForegroundWindow is required, otherwise Windows ignores the\n          // TrackPopupMenu because the window isn't the foreground one, on\n          // some older Windows versions...\n          SetForegroundWindow(getHandle());\n\n          // Display the menu\n          POINT pos;\n          GetCursorPos(&pos);\n          TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, getHandle(), nullptr);\n\n          break;\n\t\t} \n        return 0;\n      }\n    \n      // Handle tray icon menu commands\n    case WM_COMMAND:\n      switch (LOWORD(wParam)) {\n      case ID_CONTR0L_PANEL:\n        CPanel->showDialog();\n        break;\n      case ID_DISABLE_NEW_CLIENTS:\n        {\n          thread.server.getClientsInfo(&LCInfo);\n          LCInfo.setDisable(!LCInfo.getDisable());\n          thread.server.setClientsStatus(&LCInfo);\n          CPanel->UpdateListView(&LCInfo);\n        }\n        break;\n      case ID_OPTIONS:\n        vncConfig.start(INVALID_HANDLE_VALUE);\n        break;\n      case ID_CONNECT:\n        vncConnect.start(INVALID_HANDLE_VALUE);\n        break;\n      case ID_DISCONNECT:\n        thread.server.disconnectClients(\"tray menu disconnect\");\n        break;\n      case ID_CLOSE:\n        if (MsgBox(nullptr, \"Are you sure you want to close the server?\",\n                   MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) == IDYES) {\n          if (isServiceProcess()) {\n            try {\n              rfb::win32::stopService(VNCServerService::Name);\n            } catch (std::exception& e) {\n              MsgBox(nullptr, e.what(), MB_ICONERROR | MB_OK);\n            }\n          } else {\n            thread.server.stop();\n          }\n        }\n        break;\n      case ID_ABOUT:\n        AboutDialog::instance.showDialog();\n        break;\n      }\n      return 0;\n\n      // Handle commands send by other processes\n    case WM_COPYDATA:\n      {\n        COPYDATASTRUCT* command = (COPYDATASTRUCT*)lParam;\n        switch (command->dwData) {\n        case 1:\n          {\n            std::string viewer((char*)command->lpData, command->cbData);\n            return thread.server.addNewClient(viewer.c_str()) ? 1 : 0;\n          }\n        case 2:\n          return thread.server.disconnectClients(\"IPC disconnect\") ? 1 : 0;\n        case 3:\n          thread.server.setClientsStatus(&CPanel->ListConnStatus);\n          /* fall through */\n        case 4:\n          thread.server.getClientsInfo(&LCInfo);\n          CPanel->UpdateListView(&LCInfo);\n          break;\n        };\n      };\n      break;\n\n    case WM_CLOSE:\n      PostQuitMessage(0);\n      break;\n\n    case WM_TIMER:\n      if (rfb::win32::desktopChangeRequired()) {\n        SendMessage(getHandle(), WM_CLOSE, 0, 0);\n        return 0;\n      }\n\n      thread.server.getClientsInfo(&LCInfo);\n      CPanel->UpdateListView(&LCInfo);\n\n      setIcon(thread.server.isServerInUse() ?\n              (!LCInfo.getDisable() ? thread.activeIcon : thread.dis_activeIcon) : \n              (!LCInfo.getDisable() ? thread.inactiveIcon : thread.dis_inactiveIcon));\n\n      return 0;\n\n    case WM_SET_TOOLTIP:\n      {\n        const std::lock_guard<std::mutex> a(thread.lock);\n        if (!thread.toolTip.empty())\n          setToolTip(thread.toolTip.c_str());\n      }\n      return 0;\n\n    }\n\n    return TrayIcon::processMessage(msg, wParam, lParam);\n  }\n\nprotected:\n  LaunchProcess vncConfig;\n  LaunchProcess vncConnect;\n  STrayIconThread& thread;\n  ControlPanel * CPanel;\n  ListConnInfo LCInfo;\n};\n\n\nSTrayIconThread::STrayIconThread(VNCServerWin32& sm, UINT inactiveIcon_, UINT activeIcon_, \n                                 UINT dis_inactiveIcon_, UINT dis_activeIcon_, UINT menu_)\n: thread(&STrayIconThread::worker, this), thread_id(-1),\n  windowHandle(nullptr), server(sm),\n  inactiveIcon(inactiveIcon_), activeIcon(activeIcon_),\n  dis_inactiveIcon(dis_inactiveIcon_), dis_activeIcon(dis_activeIcon_),\n  menu(menu_), runTrayIcon(true) {\n  while (thread_id == (DWORD)-1)\n    Sleep(0);\n}\n\nSTrayIconThread::~STrayIconThread() {\n  runTrayIcon = false;\n  PostThreadMessage(thread_id, WM_QUIT, 0, 0);\n  thread.join();\n}\n\nvoid STrayIconThread::worker() {\n  thread_id = GetCurrentThreadId();\n  while (runTrayIcon) {\n    if (rfb::win32::desktopChangeRequired() && \n      !rfb::win32::changeDesktop())\n      Sleep(2000);\n\n    STrayIcon icon(*this);\n    windowHandle = icon.getHandle();\n\n    MSG msg;\n    while (runTrayIcon && ::GetMessage(&msg, nullptr, 0, 0) > 0) {\n      TranslateMessage(&msg);\n      DispatchMessage(&msg);\n    }\n\n    windowHandle = nullptr;\n  }\n}\n\nvoid STrayIconThread::setToolTip(const char* text) {\n  if (!windowHandle) return;\n  const std::lock_guard<std::mutex> a(lock);\n  toolTip = text;\n  PostMessage(windowHandle, WM_SET_TOOLTIP, 0, 0);\n}\n\n}\n\n"
  },
  {
    "path": "win/winvnc/STrayIcon.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef WINVNC_TRAYICON_H\n#define WINVNC_TRAYICON_H\n\n#include <mutex>\n#include <thread>\n\n#include <winvnc/VNCServerWin32.h>\n\n#include <core/Configuration.h>\n\nnamespace winvnc {\n\n  class STrayIconThread {\n  public:\n    STrayIconThread(VNCServerWin32& sm, UINT inactiveIcon,\n      UINT activeIcon, UINT dis_inactiveIcon, UINT dis_activeIcon, UINT menu);\n    virtual ~STrayIconThread();\n\n    void setToolTip(const char* text);\n\n    static core::BoolParameter disableOptions;\n    static core::BoolParameter disableClose;\n\n    friend class STrayIcon;\n  protected:\n    void worker();\n\n    std::mutex lock;\n    std::thread thread;\n    DWORD thread_id;\n    HWND windowHandle;\n    std::string toolTip;\n    VNCServerWin32& server;\n    UINT inactiveIcon;\n    UINT activeIcon;\n    UINT dis_inactiveIcon;\n    UINT dis_activeIcon;\n    UINT menu;\n    bool runTrayIcon;\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/winvnc/VNCServerService.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WinVNC Version 4.0 Service-Mode implementation\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <winvnc/VNCServerService.h>\n\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb_win32/TsSessions.h>\n#include <rfb_win32/ModuleFileName.h>\n\n#include <windows.h>\n#include <wtsapi32.h>\n#include <tlhelp32.h>\n\nusing namespace winvnc;\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\n\nconst char* winvnc::VNCServerService::Name = \"TigerVNC\";\n\n// SendSAS is not available until Windows 7, and missing from MinGW\nstatic HMODULE sasLibrary = nullptr;\ntypedef void WINAPI (*SendSAS_proto)(BOOL AsUser);\nstatic SendSAS_proto _SendSAS = nullptr;\n\nVNCServerService::VNCServerService()\n  : Service(Name)\n  , stopServiceEvent(CreateEvent(nullptr, FALSE, FALSE, nullptr))\n  , sessionEvent(CreateEvent(nullptr, FALSE, FALSE, \"Global\\\\SessionEventTigerVNC\"))\n  , sessionEventCad(CreateEvent(nullptr, FALSE, FALSE, \"Global\\\\SessionEventTigerVNCCad\")) {\n  if (sasLibrary == nullptr) {\n    sasLibrary = LoadLibrary(\"sas.dll\");\n    if (sasLibrary != nullptr)\n      _SendSAS = (SendSAS_proto)(void*)GetProcAddress(sasLibrary, \"SendSAS\");\n  }\n  // - Set the service-mode logging defaults\n  //   These will be overridden by the Log option in the\n  //   registry, if present.\n  logParams.setParam(\"*:EventLog:0,Connections:EventLog:100\");\n}\n\n\n//////////////////////////////////////////////////////////////////////////////\n\nDWORD GetLogonPid(DWORD dwSessionId)\n{\n    DWORD dwLogonPid = 0;\n    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\n    if (hSnap != INVALID_HANDLE_VALUE)\n    {\n        PROCESSENTRY32 procEntry;\n        procEntry.dwSize = sizeof procEntry;\n\n        if (Process32First(hSnap, &procEntry)) do\n        {\n            DWORD dwLogonSessionId = 0;\n            if (_stricmp(procEntry.szExeFile, \"winlogon.exe\") == 0 &&\n                ProcessIdToSessionId(procEntry.th32ProcessID, &dwLogonSessionId) &&\n                dwLogonSessionId == dwSessionId)\n            {\n                dwLogonPid = procEntry.th32ProcessID;\n                break;\n            }\n        } while (Process32Next(hSnap, &procEntry));\n        CloseHandle(hSnap);\n    }\n    return dwLogonPid;\n}\n\n//////////////////////////////////////////////////////////////////////////////\nBOOL GetSessionUserTokenWin(OUT LPHANDLE lphUserToken)\n{\n    BOOL bResult = FALSE;\n    ConsoleSessionId ID_session;\n    DWORD Id = GetLogonPid(ID_session.id);\n    if (HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Id))\n    {\n        bResult = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, lphUserToken);\n        CloseHandle(hProcess);\n    }\n    return bResult;\n}\n\n//////////////////////////////////////////////////////////////////////////////\n// START the app as system \nHANDLE LaunchProcessWin(DWORD /*dwSessionId*/)\n{\n    HANDLE hProcess = nullptr;\n    HANDLE hToken = nullptr;\n    if (GetSessionUserTokenWin(&hToken))\n    {\n        ModuleFileName filename;\n        std::string cmdLine;\n        cmdLine = format(\"\\\"%s\\\" -noconsole -service_run\", filename.buf);\n        STARTUPINFO si;\n        ZeroMemory(&si, sizeof si);\n        si.cb = sizeof si;\n        si.dwFlags = STARTF_USESHOWWINDOW;\n        PROCESS_INFORMATION\tpi;\n        if (CreateProcessAsUser(hToken, nullptr, (char*)cmdLine.c_str(),\n                                nullptr, nullptr, FALSE, DETACHED_PROCESS,\n                                nullptr, nullptr, &si, &pi))\n        {\n            CloseHandle(pi.hThread);\n            hProcess = pi.hProcess;\n        }\n        CloseHandle(hToken);\n    }\n    return hProcess;\n}\n\nDWORD VNCServerService::serviceMain(int /*argc*/, char* /*argv*/ [])\n{\n    ConsoleSessionId OlddwSessionId;\n\n    HANDLE hProcess = nullptr;\n    //We use this event to notify the program that the session has changed\n    //The program need to end so the service can restart the program in the correct session\n    //wait_for_existing_process();\n    HANDLE testevent[2] = { stopServiceEvent, sessionEventCad };\n    setStatus(SERVICE_RUNNING);\n    while (status.dwCurrentState == SERVICE_RUNNING)\n    {\n        DWORD dwEvent = WaitForMultipleObjects(2, testevent, FALSE, 1000);\n        switch (dwEvent) \n        { \n        //stopServiceEvent, exit while loop\n        case WAIT_OBJECT_0 + 0: \n            setStatus(SERVICE_STOP_PENDING);\n            break; \n\n        //cad request\n        case WAIT_OBJECT_0 + 1:\n            if (_SendSAS != nullptr)\n                _SendSAS(FALSE);\n            break; \n\n        case WAIT_TIMEOUT:\n            {\n                ConsoleSessionId dwSessionId;\n                if (OlddwSessionId.id != dwSessionId.id)\n                {\n                    OlddwSessionId.id = dwSessionId.id;\n                    SetEvent(sessionEvent);\n                }\n                DWORD dwExitCode = 0;\n                if (hProcess == nullptr ||\n                    (GetExitCodeProcess(hProcess, &dwExitCode) &&\n                    dwExitCode != STILL_ACTIVE &&\n                    CloseHandle(hProcess)))\n                {\n                    hProcess = LaunchProcessWin(dwSessionId.id);\n                }\n            }\n            break;\n        }\n    }\n\n    SetEvent(sessionEvent);\n\n    if (hProcess)\n    {\n        WaitForSingleObject(hProcess, 15000);\n        CloseHandle(hProcess);\n    }\n    return 0;\n}\n\nvoid VNCServerService::stop() {\n  SetEvent(stopServiceEvent);\n  SetEvent(sessionEvent);\n}\n"
  },
  {
    "path": "win/winvnc/VNCServerService.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __WINVNC_SERVICEMODE_H__\n#define __WINVNC_SERVICEMODE_H__\n\n#include <winvnc/VNCServerWin32.h>\n#include <rfb_win32/Service.h>\n\nnamespace winvnc {\n\n  class VNCServerService : public rfb::win32::Service {\n  public:\n    VNCServerService();\n\n    DWORD serviceMain(int argc, char* argv[]) override;\n    void stop() override;\n\n    static const char* Name;\n  protected:\n    rfb::win32::Handle stopServiceEvent;\n    rfb::win32::Handle sessionEvent;\n    rfb::win32::Handle sessionEventCad;\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/winvnc/VNCServerWin32.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- WinVNC Version 4.0 Main Routine\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <winvnc/VNCServerWin32.h>\n#include <winvnc/resource.h>\n#include <winvnc/ListConnInfo.h>\n#include <winvnc/STrayIcon.h>\n\n#include <core/LogWriter.h>\n\n#include <network/TcpSocket.h>\n\n#include <rfb_win32/ComputerName.h>\n#include <rfb_win32/CurrentUser.h>\n#include <rfb_win32/Service.h>\n\n#include <rfb/SConnection.h>\n\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\nusing namespace winvnc;\nusing namespace network;\n\nstatic LogWriter vlog(\"VNCServerWin32\");\n\n\nconst char* winvnc::VNCServerWin32::RegConfigPath = \"Software\\\\TigerVNC\\\\WinVNC4\";\n\n\nstatic IntParameter port_number(\"PortNumber\",\n  \"TCP/IP port on which the server will accept connections\",\n  5900, 0, 65535);\nstatic StringParameter hosts(\"Hosts\",\n  \"Filter describing which hosts are allowed access to this server\", \"+\");\nstatic BoolParameter localHost(\"LocalHost\",\n  \"Only accept connections from via the local loop-back network interface\", false);\nstatic BoolParameter queryOnlyIfLoggedOn(\"QueryOnlyIfLoggedOn\",\n  \"Only prompt for a local user to accept incoming connections if there is a user logged on\", false);\nstatic BoolParameter showTrayIcon(\"ShowTrayIcon\",\n  \"Show the configuration applet in the system tray icon\", true);\n\n\nVNCServerWin32::VNCServerWin32()\n  : command(NoCommand),\n    commandEvent(CreateEvent(nullptr, TRUE, FALSE, nullptr)),\n    sessionEvent(isServiceProcess() ?\n      CreateEvent(nullptr, FALSE, FALSE, \"Global\\\\SessionEventTigerVNC\") : nullptr),\n    vncServer(ComputerName().buf, &desktop),\n    thread_id(-1), runServer(false), isDesktopStarted(false),\n    config(&sockMgr), rfbSock(&sockMgr), trayIcon(nullptr),\n    queryConnectDialog(nullptr)\n{\n  // Initialise the desktop\n  desktop.setStatusLocation(&isDesktopStarted);\n  desktop.setQueryConnectionHandler(this);\n\n  // Register the desktop's event to be handled\n  sockMgr.addEvent(desktop.getUpdateEvent(), &desktop);\n  sockMgr.addEvent(desktop.getTerminateEvent(), this);\n\n  // Register the queued command event to be handled\n  sockMgr.addEvent(commandEvent, this);\n  if (sessionEvent)\n    sockMgr.addEvent(sessionEvent, this);\n}\n\nVNCServerWin32::~VNCServerWin32() {\n  delete trayIcon;\n\n  // Stop the SDisplay from updating our state\n  desktop.setStatusLocation(nullptr);\n\n  // Join the Accept/Reject dialog thread\n  if (queryConnectDialog)\n    delete queryConnectDialog;\n}\n\n\nvoid VNCServerWin32::processAddressChange() {\n  if (!trayIcon)\n    return;\n\n  // Tool-tip prefix depends on server mode\n  const char* prefix = \"VNC server (user):\";\n  if (isServiceProcess())\n    prefix = \"VNC server (service):\";\n\n  // Fetch the list of addresses\n  std::list<std::string> addrs;\n  if (rfbSock.isListening())\n    addrs = TcpListener::getMyAddresses();\n  else\n    addrs.push_front(\"Not accepting connections\");\n\n  // Build the new tip\n  std::list<std::string>::iterator i, next_i;\n  std::string toolTip(prefix);\n  for (i=addrs.begin(); i!= addrs.end(); i=next_i) {\n    next_i = i; next_i ++;\n    toolTip += *i;\n    if (next_i != addrs.end())\n      toolTip += \",\";\n  }\n  \n  // Pass the new tip to the tray icon\n  vlog.info(\"Refreshing tray icon\");\n  trayIcon->setToolTip(toolTip.c_str());\n}\n\nvoid VNCServerWin32::regConfigChanged() {\n  // -=- Make sure we're listening on the right ports.\n  rfbSock.setServer(&vncServer);\n  rfbSock.setPort(port_number, localHost);\n\n  // -=- Update the TCP address filter for both ports, if open.\n  rfbSock.setFilter(hosts);\n\n  // -=- Update the tray icon tooltip text with IP addresses\n  processAddressChange();\n}\n\n\nint VNCServerWin32::run() {\n  {\n    const std::lock_guard<std::mutex> a(runLock);\n    thread_id = GetCurrentThreadId();\n    runServer = true;\n  }\n\n  // - Create the tray icon (if possible)\n  if (showTrayIcon)\n\t  trayIcon = new STrayIconThread(*this, IDI_ICON, IDI_CONNECTED,\n                                 IDI_ICON_DISABLE, IDI_CONNECTED_DISABLE,\n                                 IDR_TRAY);\n\n  // - Register for notification of configuration changes\n  config.setCallback(this);\n  if (isServiceProcess())\n    config.setKey(HKEY_LOCAL_MACHINE, RegConfigPath);\n  else\n    config.setKey(HKEY_CURRENT_USER, RegConfigPath);\n\n  // - Set the address-changed handler for the RFB socket\n  rfbSock.setAddressChangeNotifier(this);\n\n  int result = 0;\n  try {\n    vlog.debug(\"Entering message loop\");\n\n    // - Run the server until we're told to quit\n    MSG msg;\n    while (runServer) {\n      result = sockMgr.getMessage(&msg, nullptr, 0, 0);\n      if (result < 0)\n        throw core::win32_error(\"getMessage\", GetLastError());\n      if (!isServiceProcess() && (result == 0))\n        break;\n      TranslateMessage(&msg);\n      DispatchMessage(&msg);\n    }\n\n    vlog.debug(\"Server exited cleanly\");\n  } catch (core::win32_error &s) {\n    vlog.error(\"%s\", s.what());\n    result = s.err;\n  } catch (std::exception &e) {\n    vlog.error(\"%s\", e.what());\n  }\n\n  {\n    const std::lock_guard<std::mutex> a(runLock);\n    runServer = false;\n    thread_id = (DWORD)-1;\n  }\n\n  return result;\n}\n\nvoid VNCServerWin32::stop() {\n  const std::lock_guard<std::mutex> a(runLock);\n  runServer = false;\n  if (thread_id != (DWORD)-1)\n    PostThreadMessage(thread_id, WM_QUIT, 0, 0);\n}\n\n\nbool VNCServerWin32::disconnectClients(const char* reason) {\n  return queueCommand(DisconnectClients, reason, 0);\n}\n\nbool VNCServerWin32::addNewClient(const char* client) {\n  TcpSocket* sock = nullptr;\n  try {\n    std::string hostname;\n    int port;\n    getHostAndPort(client, &hostname, &port, 5500);\n    vlog.error(\"port=%d\", port);\n    sock = new TcpSocket(hostname.c_str(), port);\n    if (queueCommand(AddClient, sock, 0))\n      return true;\n    delete sock;\n  } catch (...) {\n    delete sock;\n  }\n  return false;\n}\n\nbool VNCServerWin32::getClientsInfo(ListConnInfo* LCInfo) {\n  return queueCommand(GetClientsInfo, LCInfo, 0);\n}\n\nbool VNCServerWin32::setClientsStatus(ListConnInfo* LCInfo) {\n  return queueCommand(SetClientsStatus, LCInfo, 0);\n}\n\nvoid VNCServerWin32::queryConnection(network::Socket* sock,\n                                     const char* userName)\n{\n  if (queryOnlyIfLoggedOn && CurrentUserToken().noUserLoggedOn()) {\n    vncServer.approveConnection(sock, true, nullptr);\n    return;\n  }\n  if (queryConnectDialog) {\n    vncServer.approveConnection(sock, false, \"Another connection is currently being queried.\");\n    return;\n  }\n  queryConnectDialog = new QueryConnectDialog(sock, userName, this);\n  queryConnectDialog->startDialog();\n}\n\nvoid VNCServerWin32::queryConnectionComplete() {\n  queueCommand(QueryConnectionComplete, nullptr, 0, false);\n}\n\n\nbool VNCServerWin32::queueCommand(Command cmd, const void* data, int len, bool wait) {\n  std::unique_lock<std::mutex> lock(commandLock);\n  while (command != NoCommand)\n    commandSig.wait(lock);\n  command = cmd;\n  commandData = data;\n  commandDataLen = len;\n  SetEvent(commandEvent);\n  if (wait) {\n    while (command != NoCommand)\n      commandSig.wait(lock);\n    commandSig.notify_one();\n  }\n  return true;\n}\n\nvoid VNCServerWin32::processEvent(HANDLE event_) {\n  ResetEvent(event_);\n\n  if (event_ == commandEvent.h) {\n    // If there is no command queued then return immediately\n    {\n      const std::lock_guard<std::mutex> a(commandLock);\n      if (command == NoCommand)\n        return;\n    }\n\n    // Perform the required command\n    switch (command) {\n\n    case DisconnectClients:\n      // Disconnect all currently active VNC viewers\n      vncServer.closeClients((const char*)commandData);\n      break;\n\n    case AddClient:\n      // Make a reverse connection to a VNC viewer\n      sockMgr.addSocket((network::Socket*)commandData, &vncServer);\n      break;\n  case GetClientsInfo:\n    getConnInfo((ListConnInfo*)commandData);\n    break;\n  case SetClientsStatus:\n    setConnStatus((ListConnInfo*)commandData);\n    break;\n\n    case QueryConnectionComplete:\n      // The Accept/Reject dialog has completed\n      // Get the result, then clean it up\n      vncServer.approveConnection(queryConnectDialog->getSock(),\n                                  queryConnectDialog->isAccepted(),\n                                  \"Connection rejected by user\");\n      delete queryConnectDialog;\n      queryConnectDialog = nullptr;\n      break;\n\n    default:\n      vlog.error(\"Unknown command %d queued\", command);\n    };\n\n    // Clear the command and signal completion\n    {\n      std::unique_lock<std::mutex> lock(commandLock);\n      command = NoCommand;\n      commandSig.notify_one();\n    }\n  } else if ((event_ == sessionEvent.h) ||\n             (event_ == desktop.getTerminateEvent())) {\n    stop();\n  }\n}\n\nvoid VNCServerWin32::getConnInfo(ListConnInfo * listConn)\n{\n  std::list<network::Socket*> sockets;\n  std::list<network::Socket*>::iterator i;\n\n  listConn->Clear();\n  listConn->setDisable(sockMgr.getDisable(&vncServer));\n\n  vncServer.getSockets(&sockets);\n\n  for (i = sockets.begin(); i != sockets.end(); i++) {\n    rfb::SConnection* conn;\n    int status;\n\n    conn = vncServer.getConnection(*i);\n    if (!conn)\n      continue;\n\n    if (!conn->authenticated())\n      status = 3;\n    else if (conn->accessCheck(rfb::AccessPtrEvents |\n                               rfb::AccessKeyEvents |\n                               rfb::AccessView))\n      status = 0;\n    else if (conn->accessCheck(rfb::AccessView))\n      status = 1;\n    else\n      status = 2;\n\n    listConn->addInfo((void*)(*i), (*i)->getPeerAddress(), status);\n  }\n}\n\nvoid VNCServerWin32::setConnStatus(ListConnInfo* listConn)\n{\n  sockMgr.setDisable(&vncServer, listConn->getDisable());\n\n  if (listConn->Empty())\n    return;\n\n  for (listConn->iBegin(); !listConn->iEnd(); listConn->iNext()) {\n    network::Socket* sock;\n    rfb::SConnection* conn;\n    int status;\n\n    sock = (network::Socket*)listConn->iGetConn();\n\n    conn = vncServer.getConnection(sock);\n    if (!conn)\n      continue;\n\n    status = listConn->iGetStatus();\n    if (status == 3) {\n      conn->close(nullptr);\n    } else {\n      rfb::AccessRights ar;\n\n      ar = rfb::AccessDefault;\n\n      switch (status) {\n      case 0:\n        ar |= rfb::AccessPtrEvents |\n              rfb::AccessKeyEvents |\n              rfb::AccessView;\n        break;\n      case 1:\n        ar |= rfb::AccessView;\n        ar &= ~(rfb::AccessPtrEvents |\n                rfb::AccessKeyEvents);\n        break;\n      case 2:\n        ar &= ~(rfb::AccessPtrEvents |\n                rfb::AccessKeyEvents |\n                rfb::AccessView);\n        break;\n      }\n      conn->setAccessRights(ar);\n    }\n  }\n}\n"
  },
  {
    "path": "win/winvnc/VNCServerWin32.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n#ifndef __VNCSERVER_WIN32_H__\n#define __VNCSERVER_WIN32_H__\n\n#include <condition_variable>\n#include <mutex>\n\n#include <winsock2.h>\n#include <network/TcpSocket.h>\n#include <rfb/VNCServerST.h>\n#include <rfb_win32/RegConfig.h>\n#include <rfb_win32/SDisplay.h>\n#include <rfb_win32/SocketManager.h>\n#include <winvnc/QueryConnectDialog.h>\n#include <winvnc/ManagedListener.h>\n\nnamespace core {\n    class Thread;\n}\n\nnamespace winvnc {\n\n  struct ListConnInfo;\n  class STrayIconThread;\n\n  class VNCServerWin32 : rfb::win32::QueryConnectionHandler,\n                         rfb::win32::SocketManager::AddressChangeNotifier,\n                         rfb::win32::RegConfig::Callback,\n                         rfb::win32::EventHandler {\n  public:\n    VNCServerWin32();\n    virtual ~VNCServerWin32();\n\n    // Run the server in the current thread\n    int run();\n\n    // Cause the run() call to return\n    // THREAD-SAFE\n    void stop();\n\n    // Determine whether a viewer is active\n    // THREAD-SAFE\n    bool isServerInUse() const {return isDesktopStarted;}\n\n    // Connect out to the specified VNC viewer\n    // THREAD-SAFE\n    bool addNewClient(const char* client);\n\n    // Disconnect all connected clients\n    // THREAD-SAFE\n    bool disconnectClients(const char* reason=nullptr);\n\n    // Call used to notify VNCServerST of user accept/reject query completion\n    // CALLED FROM AcceptConnectDialog THREAD\n    void queryConnectionComplete();\n\n    // Where to read the configuration settings from\n    static const char* RegConfigPath;\n\n    bool getClientsInfo(ListConnInfo* LCInfo);\n\n    bool setClientsStatus(ListConnInfo* LCInfo);\n\n  protected:\n    // QueryConnectionHandler interface\n    // Callback used to prompt user to accept or reject a connection.\n    // CALLBACK IN VNCServerST \"HOST\" THREAD\n    void queryConnection(network::Socket* sock,\n                         const char* userName) override;\n\n    // SocketManager::AddressChangeNotifier interface\n    // Used to keep tray icon up to date\n    void processAddressChange() override;\n\n    // RegConfig::Callback interface\n    // Called via the EventManager whenever RegConfig sees the registry change\n    void regConfigChanged() override;\n\n    // EventHandler interface\n    // Used to perform queued commands\n    void processEvent(HANDLE event) override;\n\n    void getConnInfo(ListConnInfo * listConn);\n    void setConnStatus(ListConnInfo* listConn);\n\n  protected:\n    // Perform a particular internal function in the server thread\n    typedef enum {NoCommand, DisconnectClients, AddClient, QueryConnectionComplete, SetClientsStatus, GetClientsInfo} Command;\n    bool queueCommand(Command cmd, const void* data, int len, bool wait=true);\n    Command command;\n    const void* commandData;\n    int commandDataLen;\n    std::mutex commandLock;\n    std::condition_variable commandSig;\n    rfb::win32::Handle commandEvent;\n    rfb::win32::Handle sessionEvent;\n\n    // VNCServerWin32 Server-internal state\n    rfb::win32::SDisplay desktop;\n    rfb::VNCServerST vncServer;\n    std::mutex runLock;\n    DWORD thread_id;\n    bool runServer;\n    bool isDesktopStarted;\n    rfb::win32::SocketManager sockMgr;\n    rfb::win32::RegConfig config;\n\n    ManagedListener rfbSock;\n    STrayIconThread* trayIcon;\n\n    QueryConnectDialog* queryConnectDialog;\n  };\n\n};\n\n#endif\n"
  },
  {
    "path": "win/winvnc/buildTime.cxx",
    "content": "/* Copyright (C) 2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\nconst char* buildTime = \"Built on \" __DATE__ \" at \" __TIME__;\n"
  },
  {
    "path": "win/winvnc/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Developer Studio generated include file.\n// Used by winvnc.rc\n//\n#define IDR_MANIFEST                    1\n#define IDI_ICON                        101\n#define IDR_TRAY                        102\n#define IDD_DIALOG1                     103\n#define IDD_ABOUT                       104\n#define IDI_CONNECTED                   105\n#define IDD_QUERY_CONNECT               107\n#define IDD_ADD_NEW_CLIENT              108\n#define IDB_BITMAP                      109\n#define IDD_CONTROL_PANEL               110\n#define IDI_ICON_DISABLE                111\n#define IDI_CONNECTED_DISABLE           112\n#define IDC_DESCRIPTION                 1000\n#define IDC_BUILDTIME                   1001\n#define IDC_VERSION                     1002\n#define IDC_COPYRIGHT                   1003\n#define IDC_QUERY_COUNTDOWN             1008\n#define IDC_QUERY_USER                  1009\n#define IDC_QUERY_HOST                  1010\n#define IDC_HOST                        1011\n#define IDC_LIST_CONNECTIONS            1012\n#define IDC_STATIC_KLIENTS_LIST         1013\n#define IDC_STATIC_SELECTED_KLIENTS     1014\n#define IDC_VIEW_ONLY                   1015\n#define IDC_FULL_CONTROL                1016\n#define IDC_STOP_UPDATE                 1017\n#define IDC_KILL_SEL_CLIENT             1018\n#define IDC_PROPERTIES                  1019\n#define IDC_ADD_CLIENT                  1020\n#define IDC_KILL_ALL                    1021\n#define IDC_DISABLE_CLIENTS             1022\n#define ID_CONTR0L_PANEL                40001\n#define ID_CLOSE                        40002\n#define ID_ABOUT                        40003\n#define ID_DISCONNECT                   40004\n#define ID_CONNECT                      40005\n#define ID_OPTIONS                      40006\n#define ID_DISABLE_NEW_CLIENTS          40007\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        113\n#define _APS_NEXT_COMMAND_VALUE         40008\n#define _APS_NEXT_CONTROL_VALUE         1023\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "win/winvnc/winvnc.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- VNC server 4.0 for Windows (WinVNC4)\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <string.h>\n\n#include <winvnc/VNCServerWin32.h>\n#include <winvnc/VNCServerService.h>\n#include <winvnc/AddNewClientDialog.h>\n\n#include <core/Logger_file.h>\n#include <core/Logger_stdio.h>\n#include <core/LogWriter.h>\n#include <core/string.h>\n\n#include <rfb_win32/AboutDialog.h>\n#include <rfb_win32/MsgBox.h>\n\n#include <network/TcpSocket.h>\n\nusing namespace winvnc;\nusing namespace core;\nusing namespace rfb;\nusing namespace win32;\n\nstatic LogWriter vlog(\"main\");\n\nconst char* rfb::win32::AppName = \"TigerVNC Server\";\n\n\nextern bool runAsService;\nstatic bool runServer = true;\nstatic bool close_console = false;\n\n\n//\n// -=- processParams\n//     Read in the command-line parameters and interpret them.\n//\n\nstatic void programInfo() {\n  win32::FileVersionInfo inf;\n  printf(\"%s - %s, Version %s\\n\",\n    inf.getVerString(\"ProductName\"),\n    inf.getVerString(\"FileDescription\"),\n    inf.getVerString(\"FileVersion\"));\n  printf(\"%s\\n\", buildTime);\n  printf(\"%s\\n\\n\", inf.getVerString(\"LegalCopyright\"));\n}\n\nstatic void programUsage() {\n  printf(\"Command-line options:\\n\");\n  printf(\"  -connect [<host[::port]>]            - Connect an existing WinVNC server to a listening viewer.\\n\");\n  printf(\"  -disconnect                          - Disconnect all clients from an existing WinVNC server.\\n\");\n  printf(\"  -register <options...>               - Register WinVNC server as a system service.\\n\");\n  printf(\"  -unregister                          - Remove WinVNC server from the list of system services.\\n\");\n  printf(\"  -start                               - Start the WinVNC server system service.\\n\");\n  printf(\"  -stop                                - Stop the WinVNC server system service.\\n\");\n  printf(\"  -status                              - Query the WinVNC service status.\\n\");\n  printf(\"  -help                                - Provide usage information.\\n\");\n  printf(\"  -noconsole                           - Run without a console (i.e. no stderr/stdout)\\n\");\n  printf(\"  <setting>=<value>                    - Set the named configuration parameter.\\n\");\n  printf(\"    (Parameter values specified on the command-line override those specified by other configuration methods.)\\n\");\n  printf(\"\\nLog names:\\n\");\n  LogWriter::listLogWriters();\n  printf(\"\\nLog destinations:\\n\");\n  Logger::listLoggers();\n  printf(\"\\nAvailable configuration parameters:\\n\");\n  Configuration::listParams(79, 14);\n}\n\nstatic void MsgBoxOrLog(const char* msg, bool isError=false) {\n  if (close_console) {\n    MsgBox(nullptr, msg, (isError ? MB_ICONERROR : MB_ICONINFORMATION) | MB_OK);\n  } else {\n    if (isError) {\n      try {\n        vlog.error(\"%s\", msg);\n        return;\n      } catch (...) {\n      }\n    }\n    fprintf(stderr, \"%s\\n\", msg);\n  }\n}\n\nstatic void processParams(int argc, char** argv) {\n  for (int i=1; i<argc; i++) {\n    try {\n\n      if (strcasecmp(argv[i], \"-connect\") == 0) {\n        runServer = false;\n        const char *host = nullptr;\n        if (i+1 < argc) {\n          host = argv[i+1];\n          i++;\n        } else {\n          AddNewClientDialog ancd;\n          if (ancd.showDialog())\n            host = ancd.getHostName();\n        }\n        if (host != nullptr) {\n          HWND hwnd = FindWindow(nullptr, \"winvnc::IPC_Interface\");\n          if (!hwnd)\n            throw std::runtime_error(\"Unable to locate existing VNC Server.\");\n          COPYDATASTRUCT copyData;\n          copyData.dwData = 1; // *** AddNewClient\n          copyData.cbData = strlen(host);\n          copyData.lpData = (void*)host;\n          printf(\"Sending connect request to VNC Server...\\n\");\n          if (!SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&copyData))\n            MsgBoxOrLog(\"Connection failed.\", true);\n        }\n      } else if (strcasecmp(argv[i], \"-disconnect\") == 0) {\n        runServer = false;\n        HWND hwnd = FindWindow(nullptr, \"winvnc::IPC_Interface\");\n        if (!hwnd)\n          throw std::runtime_error(\"Unable to locate existing VNC Server.\");\n        COPYDATASTRUCT copyData;\n        copyData.dwData = 2; // *** DisconnectClients\n        copyData.lpData = nullptr;\n        copyData.cbData = 0;\n        printf(\"Sending disconnect request to VNC Server...\\n\");\n        if (!SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&copyData))\n          MsgBoxOrLog(\"Failed to disconnect clients.\", true);\n      } else if (strcasecmp(argv[i], \"-start\") == 0) {\n        printf(\"Attempting to start service...\\n\");\n        runServer = false;\n        if (rfb::win32::startService(VNCServerService::Name))\n          MsgBoxOrLog(\"Started service successfully\");\n      } else if (strcasecmp(argv[i], \"-stop\") == 0) {\n        printf(\"Attempting to stop service...\\n\");\n        runServer = false;\n        if (rfb::win32::stopService(VNCServerService::Name))\n          MsgBoxOrLog(\"Stopped service successfully\");\n      } else if (strcasecmp(argv[i], \"-status\") == 0) {\n        printf(\"Querying service status...\\n\");\n        runServer = false;\n        std::string result;\n        DWORD state = rfb::win32::getServiceState(VNCServerService::Name);\n        result = format(\"The %s service is in the %s state.\",\n                        VNCServerService::Name,\n                        rfb::win32::serviceStateName(state));\n        MsgBoxOrLog(result.c_str());\n      } else if (strcasecmp(argv[i], \"-service\") == 0) {\n        printf(\"Run in service mode\\n\");\n        runServer = false;\n        runAsService = true;\n\n      } else if (strcasecmp(argv[i], \"-service_run\") == 0) {\n        printf(\"Run in service mode\\n\");\n        runAsService = true;\n\n      } else if (strcasecmp(argv[i], \"-register\") == 0) {\n        printf(\"Attempting to register service...\\n\");\n        runServer = false;\n        int j = i;\n        i = argc;\n\n        // Try to clean up earlier services we've had\n        try {\n          rfb::win32::unregisterService(\"WinVNC4\");\n        } catch (core::win32_error&) {\n          // Do nothing as we might fail simply because there was no\n          // service to remove\n        }\n        try {\n          rfb::win32::unregisterService(\"TigerVNC Server\");\n        } catch (core::win32_error&) {\n        }\n\n        if (rfb::win32::registerService(VNCServerService::Name,\n                                        \"TigerVNC Server\",\n                                        \"Provides remote access to this machine via the VNC/RFB protocol.\",\n                                        argc-(j+1), &argv[j+1]))\n          MsgBoxOrLog(\"Registered service successfully\");\n      } else if (strcasecmp(argv[i], \"-unregister\") == 0) {\n        printf(\"Attempting to unregister service...\\n\");\n        runServer = false;\n        if (rfb::win32::unregisterService(VNCServerService::Name))\n          MsgBoxOrLog(\"Unregistered service successfully\");\n\n      } else if (strcasecmp(argv[i], \"-noconsole\") == 0) {\n        close_console = true;\n        vlog.info(\"Closing console\");\n        if (!FreeConsole())\n          vlog.info(\"Unable to close console:%lu\", GetLastError());\n\n      } else if ((strcasecmp(argv[i], \"-help\") == 0) ||\n        (strcasecmp(argv[i], \"--help\") == 0) ||\n        (strcasecmp(argv[i], \"-h\") == 0) ||\n        (strcasecmp(argv[i], \"/?\") == 0)) {\n        runServer = false;\n        programUsage();\n        break;\n\n      } else {\n        int ret;\n\n        ret = Configuration::handleParamArg(argc, argv, i);\n        if (ret > 0) {\n          i += ret - 1;\n          continue;\n        }\n\n        // Nope.  Show them usage and don't run the server\n        runServer = false;\n        programUsage();\n        break;\n      }\n\n    } catch (std::exception& e) {\n      MsgBoxOrLog(e.what(), true);\n    }\n  }\n}\n\n\n//\n// -=- main\n//\n\nint WINAPI WinMain(HINSTANCE /*inst*/, HINSTANCE /*prevInst*/, char* /*cmdLine*/, int /*cmdShow*/) {\n  int result = 0;\n\n  try {\n    // - Initialise the available loggers\n    //freopen(\"\\\\\\\\drupe\\\\tjr\\\\WinVNC4.log\",\"ab\",stderr);\n#ifdef _DEBUG\n    AllocConsole();\n\tfreopen(\"CONIN$\", \"rb\", stdin);\n\tfreopen(\"CONOUT$\", \"wb\", stdout);\n\tfreopen(\"CONOUT$\", \"wb\", stderr);\n    setbuf(stderr, nullptr);\n\tinitStdIOLoggers();\n\tinitFileLogger(\"C:\\\\temp\\\\WinVNC4.log\");\n\tlogParams.setParam(\"*:stderr:100\");\n#else\n    initFileLogger(\"C:\\\\temp\\\\WinVNC4.log\");\n\tlogParams.setParam(\"*:stderr:0\");\n#endif\n    rfb::win32::initEventLogLogger(VNCServerService::Name);\n\n    // - By default, just log errors to stderr\n    \n\n    // - Print program details and process the command line\n    programInfo();\n\n\tint argc = __argc;\n\tchar **argv = __argv;\n    processParams(argc, argv);\n\n    // - Run the server if required\n    if (runServer) {\n      // Start the network subsystem and run the server\n      VNCServerWin32 server;\n      result = server.run();\n    } else if (runAsService) {\n      VNCServerService service;\n      service.start();\n      result = service.getStatus().dwWin32ExitCode;\n    }\n\n    vlog.debug(\"WinVNC service destroyed\");\n  } catch (std::exception& e) {\n    MsgBoxOrLog(e.what(), true);\n  }\n\n  vlog.debug(\"WinVNC process quitting\");\n  return result;\n}\n"
  },
  {
    "path": "win/winvnc/winvnc.rc",
    "content": "//Microsoft Developer Studio generated resource script.\n//\n#include \"resource.h\"\n#include \"resdefs.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"windows.h\"\n\n#ifndef IDC_STATIC\n#define IDC_STATIC -1\n#endif\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// English (U.K.) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)\n#ifdef _WIN32\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK\n#pragma code_page(1252)\n#endif //_WIN32\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"#include \"\"windows.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n#ifndef _MAC\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION __RCVERSION\n PRODUCTVERSION __RCVERSION\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS 0x40004L\n FILETYPE 0x1L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"080904b0\"\n        BEGIN\n            VALUE \"Comments\", \"\\0\"\n            VALUE \"CompanyName\", \"TigerVNC team\\0\"\n            VALUE \"FileDescription\", \"TigerVNC server\\0\"\n            VALUE \"ProductName\", \"TigerVNC server\\0\"\n            VALUE \"FileVersion\", __RCVERSIONSTR\n            VALUE \"InternalName\", \"winvnc\\0\"\n            VALUE \"LegalCopyright\", \"Copyright (C) 1999-2026 TigerVNC team and many others (see README.rst)\\0\"\n            VALUE \"LegalTrademarks\", \"TigerVNC\\0\"\n            VALUE \"OriginalFilename\", \"winvnc4.exe\\0\"\n            VALUE \"PrivateBuild\", \"\\0\"\n            VALUE \"ProductVersion\", __VERSIONSTR\n            VALUE \"SpecialBuild\", \"\\0\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x809, 1200\n    END\nEND\n\n#endif    // !_MAC\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Icon\n//\n\n// Icon with lowest ID value placed first to ensure application icon\n// remains consistent on all systems.\nIDI_ICON                ICON    DISCARDABLE     \"winvnc.ico\"\nIDI_CONNECTED           ICON    DISCARDABLE     \"connected.ico\"\nIDI_ICON_DISABLE        ICON    DISCARDABLE     \"icon_dis.ico\"\nIDI_CONNECTED_DISABLE   ICON    DISCARDABLE     \"connecte.ico\"\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Menu\n//\n\nIDR_TRAY MENU DISCARDABLE \nBEGIN\n    POPUP \"Tray Menu\"\n    BEGIN\n        MENUITEM \"Control &panel\",              ID_CONTR0L_PANEL\n        MENUITEM SEPARATOR\n        MENUITEM \"&Options...\",                 ID_OPTIONS\n        MENUITEM \"Add &new client...\",          ID_CONNECT\n        MENUITEM \"&Disconnect clients\",         ID_DISCONNECT\n        MENUITEM \"D&isable new clients\",        ID_DISABLE_NEW_CLIENTS\n        MENUITEM SEPARATOR\n        MENUITEM \"&Close VNC server\",           ID_CLOSE\n        MENUITEM \"&About...\",                   ID_ABOUT\n    END\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Dialog\n//\n\nIDD_ABOUT DIALOG DISCARDABLE  0, 0, 300, 92\nSTYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | \n    WS_SYSMENU\nCAPTION \"About TigerVNC server for Windows\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    DEFPUSHBUTTON   \"OK\",IDOK,245,70,47,15\n    CONTROL         109,IDC_STATIC,\"Static\",SS_BITMAP,5,10,33,31\n    LTEXT           \">appname<\",IDC_DESCRIPTION,45,10,125,15\n    LTEXT           \">version<\",IDC_VERSION,170,10,72,15\n    LTEXT           \">buildtime<\",IDC_BUILDTIME,45,25,202,15\n    LTEXT           \">copyright<\",IDC_COPYRIGHT,45,40,256,15\n    LTEXT           \"See https://www.tigervnc.org for more information on VNC.\",\n                    IDC_STATIC,45,55,202,15\nEND\n\nIDD_QUERY_CONNECT DIALOG DISCARDABLE  0, 0, 164, 93\nSTYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | \n    WS_SYSMENU\nCAPTION \"VNC server : Accept connection?\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    DEFPUSHBUTTON   \"&Reject\",IDCANCEL,105,72,52,14\n    PUSHBUTTON      \"&Accept\",IDOK,7,72,53,14\n    RTEXT           \"User:\",IDC_STATIC,7,10,28,15,SS_CENTERIMAGE\n    RTEXT           \"Host:\",IDC_STATIC,7,30,28,15,SS_CENTERIMAGE\n    CTEXT           \"Seconds until automatic reject:\",IDC_STATIC,7,50,113,15,\n                    SS_CENTERIMAGE\n    LTEXT           \"-\",IDC_QUERY_COUNTDOWN,125,50,32,15,SS_CENTERIMAGE\n    LTEXT           \"-\",IDC_QUERY_USER,40,10,117,15,SS_CENTERIMAGE\n    LTEXT           \"-\",IDC_QUERY_HOST,40,30,117,15,SS_CENTERIMAGE\nEND\n\nIDD_ADD_NEW_CLIENT DIALOG DISCARDABLE  0, 0, 177, 52\nSTYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | \n    WS_CAPTION | WS_SYSMENU\nCAPTION \"VNC server : Add new client\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    EDITTEXT        IDC_HOST,80,10,90,15,ES_AUTOHSCROLL\n    DEFPUSHBUTTON   \"OK\",IDOK,80,31,40,14\n    PUSHBUTTON      \"Cancel\",IDCANCEL,125,31,45,14\n    CONTROL         109,IDC_STATIC,\"Static\",SS_BITMAP | SS_REALSIZEIMAGE,7,\n                    10,33,31\n    RTEXT           \"Viewer:\",IDC_STATIC,45,10,30,15,SS_CENTERIMAGE\nEND\n\nIDD_CONTROL_PANEL DIALOG DISCARDABLE  0, 0, 267, 238\nSTYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | DS_CONTEXTHELP | \n    WS_VISIBLE | WS_CAPTION | WS_SYSMENU\nCAPTION \"Control panel\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    CONTROL         \"List1\",IDC_LIST_CONNECTIONS,\"SysListView32\",LVS_REPORT | \n                    LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOSORTHEADER | \n                    WS_BORDER | WS_TABSTOP,7,25,253,76\n    LTEXT           \"Authorised clients list\",IDC_STATIC_KLIENTS_LIST,87,7,\n                    74,11,SS_CENTERIMAGE\n    GROUPBOX        \"Control of selected clients\",\n                    IDC_STATIC_SELECTED_KLIENTS,7,108,124,103\n    PUSHBUTTON      \"View-only\",IDC_VIEW_ONLY,13,121,111,14\n    PUSHBUTTON      \"Full control \",IDC_FULL_CONTROL,13,145,112,14\n    PUSHBUTTON      \"Stop updating\",IDC_STOP_UPDATE,13,167,111,14\n    PUSHBUTTON      \"Kill clients\",IDC_KILL_SEL_CLIENT,13,190,111,14\n    PUSHBUTTON      \"Properties\",IDC_PROPERTIES,144,121,111,14\n    PUSHBUTTON      \"Add new client\",IDC_ADD_CLIENT,144,145,111,14\n    PUSHBUTTON      \"Kill all clients\",IDC_KILL_ALL,144,167,111,14\n    CONTROL         \"Disable new clients\",IDC_DISABLE_CLIENTS,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,144,191,111,13\n    PUSHBUTTON      \"Close\",IDCANCEL,144,217,111,14\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// 24\n//\n\n#ifdef WIN64\nIDR_MANIFEST            24      DISCARDABLE     \"winvnc4.exe.manifest64\"\n#else\nIDR_MANIFEST            24      DISCARDABLE     \"winvnc4.exe.manifest\"\n#endif\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// DESIGNINFO\n//\n\n#ifdef APSTUDIO_INVOKED\nGUIDELINES DESIGNINFO DISCARDABLE \nBEGIN\n    IDD_ABOUT, DIALOG\n    BEGIN\n        LEFTMARGIN, 5\n        VERTGUIDE, 45\n        VERTGUIDE, 170\n        VERTGUIDE, 195\n        VERTGUIDE, 242\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 85\n        HORZGUIDE, 10\n        HORZGUIDE, 25\n        HORZGUIDE, 40\n        HORZGUIDE, 55\n        HORZGUIDE, 70\n    END\n\n    IDD_QUERY_CONNECT, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 157\n        VERTGUIDE, 35\n        VERTGUIDE, 40\n        VERTGUIDE, 60\n        VERTGUIDE, 120\n        VERTGUIDE, 125\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 86\n        HORZGUIDE, 10\n        HORZGUIDE, 25\n        HORZGUIDE, 30\n        HORZGUIDE, 45\n        HORZGUIDE, 50\n        HORZGUIDE, 65\n    END\n\n    IDD_ADD_NEW_CLIENT, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 170\n        VERTGUIDE, 45\n        VERTGUIDE, 75\n        VERTGUIDE, 80\n        VERTGUIDE, 120\n        VERTGUIDE, 125\n        VERTGUIDE, 170\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 45\n        HORZGUIDE, 10\n        HORZGUIDE, 25\n        HORZGUIDE, 30\n        HORZGUIDE, 45\n    END\n\n    IDD_CONTROL_PANEL, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 260\n        VERTGUIDE, 13\n        VERTGUIDE, 124\n        VERTGUIDE, 144\n        VERTGUIDE, 255\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 231\n        HORZGUIDE, 121\n        HORZGUIDE, 135\n        HORZGUIDE, 145\n        HORZGUIDE, 159\n        HORZGUIDE, 181\n        HORZGUIDE, 191\n        HORZGUIDE, 204\n        HORZGUIDE, 217\n    END\nEND\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Bitmap\n//\n\nIDB_BITMAP              BITMAP  DISCARDABLE     \"winvnc.bmp\"\n#endif    // English (U.K.) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "win/winvnc/winvnc4.exe.manifest",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n<assemblyIdentity\n   version=\"4.0.0.26\"\n   processorArchitecture=\"X86\"\n   name=\"TigerVNC.winvnc4.exe\"\n   type=\"win32\"\n/>\n<description>.NET control deployment tool</description>\n<dependency>\n   <dependentAssembly>\n     <assemblyIdentity\n       type=\"win32\"\n       name=\"Microsoft.Windows.Common-Controls\"\n       version=\"6.0.0.0\"\n       processorArchitecture=\"X86\"\n       publicKeyToken=\"6595b64144ccf1df\"\n       language=\"*\"\n     />\n   </dependentAssembly>\n</dependency>\n</assembly>\n"
  },
  {
    "path": "win/winvnc/winvnc4.exe.manifest64",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n<assemblyIdentity\n   version=\"4.0.0.26\"\n   processorArchitecture=\"AMD64\"\n   name=\"TigerVNC.winvnc4.exe\"\n   type=\"win32\"\n/>\n<description>.NET control deployment tool</description>\n<dependency>\n   <dependentAssembly>\n     <assemblyIdentity\n       type=\"win32\"\n       name=\"Microsoft.Windows.Common-Controls\"\n       version=\"6.0.0.0\"\n       processorArchitecture=\"AMD64\"\n       publicKeyToken=\"6595b64144ccf1df\"\n       language=\"*\"\n     />\n   </dependentAssembly>\n</dependency>\n</assembly>\n"
  },
  {
    "path": "win/wm_hooks/CMakeLists.txt",
    "content": "add_library(wm_hooks SHARED\n  ../wm_hooks/wm_hooks.cxx\n  ../wm_hooks/wm_hooks.rc)\n\n# We want the DLL to be named wm_hooks.dll rather than libwm_hooks.dll\nset_target_properties(wm_hooks PROPERTIES PREFIX \"\")\n\ntarget_include_directories(wm_hooks PUBLIC ${CMAKE_BINARY_DIR}/win)\ntarget_include_directories(wm_hooks PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\n\ninstall(TARGETS wm_hooks\n  RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}\n)\n"
  },
  {
    "path": "win/wm_hooks/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Developer Studio generated include file.\n// Used by wm_hooks.rc\n//\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        101\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1000\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "win/wm_hooks/wm_hooks.cxx",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- wm_hooks.cxx\n//\n// Window Message Hooks Dynamic Link library\n\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include <wm_hooks/wm_hooks.h>\n\n#define SHARED __attribute__((section (\"shared\"), shared))\n\nUINT WM_HK_PingThread = RegisterWindowMessage(\"RFB.WM_Hooks.PingThread\");\n\nUINT WM_HK_WindowChanged = RegisterWindowMessage(\"RFB.WM_Hooks.WindowChanged\");\nUINT WM_Hooks_WindowChanged() {\n  return WM_HK_WindowChanged;\n}\n\nUINT WM_HK_WindowClientAreaChanged = RegisterWindowMessage(\"RFB.WM_Hooks.WindowClientAreaChanged\");\nUINT WM_Hooks_WindowClientAreaChanged() {\n  return WM_HK_WindowClientAreaChanged;\n}\n\nUINT WM_HK_WindowBorderChanged = RegisterWindowMessage(\"RFB.WM_Hooks.WindowBorderChanged\");\nUINT WM_Hooks_WindowBorderChanged() {\n  return WM_HK_WindowBorderChanged;\n}\n\nUINT WM_HK_RectangleChanged = RegisterWindowMessage(\"RFB.WM_Hooks.RectangleChanged\");\nUINT WM_Hooks_RectangleChanged() {\n  return WM_HK_RectangleChanged;\n}\n\nUINT WM_HK_CursorChanged = RegisterWindowMessage(\"RFB.WM_Hooks.CursorChanged\");\nUINT WM_Hooks_CursorChanged() {\n  return WM_HK_CursorChanged;\n}\n\n#ifdef _DEBUG\nUINT WM_HK_Diagnostic = RegisterWindowMessage(\"RFB.WM_Hooks.Diagnostic\");\nUINT WM_Hooks_Diagnostic() {\n  return WM_HK_Diagnostic;\n}\n#endif\n\nATOM ATOM_Popup_Selection = GlobalAddAtom(\"RFB.WM_Hooks.PopupSelectionAtom\");\n\n//\n// -=- DLL entry point\n//\n\nHINSTANCE dll_instance = nullptr;\n\nBOOL WINAPI DllMain(HANDLE instance, ULONG reason, LPVOID /*reserved*/) {\n  switch (reason) {\n  case DLL_PROCESS_ATTACH:\n    dll_instance = (HINSTANCE)instance;\n    return TRUE;\n  case DLL_PROCESS_DETACH:\n    return TRUE;\n  case DLL_THREAD_DETACH:\n    WM_Hooks_Remove(GetCurrentThreadId());\n    return TRUE;\n  default:\n    return TRUE;\n  };\n}\n\n//\n// -=- Display update hooks\n//\n\nDWORD hook_owner SHARED = 0;\nDWORD hook_target SHARED = 0;\nHHOOK hook_CallWndProc SHARED = nullptr;\nHHOOK hook_CallWndProcRet SHARED = nullptr;\nHHOOK hook_GetMessage SHARED = nullptr;\nHHOOK hook_DialogMessage SHARED = nullptr;\nBOOL enable_cursor_shape SHARED = FALSE;\nHCURSOR cursor SHARED = nullptr;\n#ifdef _DEBUG\nUINT diagnostic_min SHARED =1;\nUINT diagnostic_max SHARED =0;\n#endif\n\n#ifdef _DEBUG\nDLLEXPORT void WM_Hooks_SetDiagnosticRange(UINT min, UINT max) {\n  diagnostic_min = min; diagnostic_max=max;\n}\n#endif\n\nbool NotifyHookOwner(UINT event, WPARAM wParam, LPARAM lParam) {\n  if (hook_owner) {\n    return PostThreadMessage(hook_owner, event, wParam, lParam)!=0;\n    /*\n    if (last_event)\n      return PostThreadMessage(hook_owner, last_event, last_wParam, last_lParam);\n    last_event = event;\n    last_wParam = wParam;\n    last_lParam = lParam;\n    return true;\n    */\n  }\n  return false;\n}\n\nbool NotifyWindow(HWND hwnd, UINT msg) {\n  return NotifyHookOwner(WM_HK_WindowChanged, msg, (LPARAM)hwnd);\n}\nbool NotifyWindowBorder(HWND hwnd, UINT msg) {\n  return NotifyHookOwner(WM_HK_WindowBorderChanged, msg, (LPARAM)hwnd);\n}\nbool NotifyWindowClientArea(HWND hwnd, UINT msg) {\n  return NotifyHookOwner(WM_HK_WindowClientAreaChanged, msg, (LPARAM)hwnd);\n}\nbool NotifyRectangle(RECT* rect) {\n  WPARAM w = MAKELONG((SHORT)rect->left, (SHORT)rect->top);\n  LPARAM l = MAKELONG((SHORT)rect->right, (SHORT)rect->bottom);\n  return NotifyHookOwner(WM_HK_RectangleChanged, w, l);\n}\nbool NotifyCursor(HCURSOR cursor_) {\n  return NotifyHookOwner(WM_HK_CursorChanged, 0, (LPARAM)cursor_);\n}\n\nvoid ProcessWindowMessage(UINT msg, HWND wnd, WPARAM wParam, LPARAM /*lParam*/) {\n#ifdef _DEBUG\n  if ((msg >= diagnostic_min) && (msg <= diagnostic_max))\n    PostThreadMessage(hook_owner, WM_HK_Diagnostic, msg, (LPARAM)wnd);\n#endif\n  if (!IsWindowVisible(wnd)) return;\n  switch (msg) {\n\n    // -=- Border update events\n\tcase WM_NCPAINT:\n\tcase WM_NCACTIVATE:\n    NotifyWindowBorder(wnd, msg);\n\t\tbreak;\n\n    // -=- Client area update events\n\tcase BM_SETCHECK:\n\tcase BM_SETSTATE:\n\tcase EM_SETSEL:\n\tcase WM_CHAR:\n\tcase WM_ENABLE:\n\tcase WM_KEYUP:\n\tcase WM_LBUTTONUP:\n\tcase WM_MBUTTONUP:\n\tcase WM_PALETTECHANGED:\n\tcase WM_RBUTTONUP:\n\tcase WM_SYSCOLORCHANGE:\n\tcase WM_SETTEXT:\n  case WM_SETFOCUS:\n\t//case WM_TIMER:\n    NotifyWindowClientArea(wnd, msg);\n    break;\n\tcase WM_HSCROLL:\n\tcase WM_VSCROLL:\n\t\tif (((int) LOWORD(wParam) == SB_THUMBTRACK) || ((int) LOWORD(wParam) == SB_ENDSCROLL))\n\t\t\tNotifyWindow(wnd, msg);\n\t\tbreak;\n\n\tcase WM_WINDOWPOSCHANGING:\n  case WM_DESTROY:\n    {\n      RECT wrect;\n      if (GetWindowRect(wnd, &wrect)) {\n        NotifyRectangle(&wrect);\n      }\n    }\n    break;\n\n  case WM_WINDOWPOSCHANGED:\n    NotifyWindow(wnd, msg);\n    break;\n\n\tcase WM_PAINT:\n    // *** could improve this\n    NotifyWindowClientArea(wnd, msg);\n    break;\n\n    // Handle pop-up menus appearing\n  case 482:\n    NotifyWindow(wnd, 482);\n    break;\n\n    // Handle pop-up menus having items selected\n\tcase 485:\n\t\t{\n\t\t\tHANDLE prop = GetProp(wnd, (LPCTSTR) (intptr_t) ATOM_Popup_Selection);\n      if (prop != (HANDLE) wParam) {\n        NotifyWindow(wnd, 485);\n\t\t\t\tSetProp(wnd,\n\t\t\t\t\t(LPCTSTR) (intptr_t) ATOM_Popup_Selection,\n\t\t\t\t\t(HANDLE) wParam);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n  case WM_NCMOUSEMOVE:\n  case WM_MOUSEMOVE:\n    if (enable_cursor_shape) {\n      HCURSOR new_cursor = GetCursor();\n      if (new_cursor != cursor) {\n        cursor = new_cursor;\n        NotifyCursor(cursor);\n      }\n    }\n    break;\n\n    /* ***\n\t\tif (prf_use_GetUpdateRect)\n\t\t{\n\t\t\tHRGN region;\n\t\t\tregion = CreateRectRgn(0, 0, 0, 0);\n\n\t\t\t// Get the affected region\n\t\t\tif (GetUpdateRgn(hWnd, region, FALSE) != ERROR)\n\t\t\t{\n\t\t\t\tint buffsize;\n\t\t\t\tUINT x;\n\t\t\t\tRGNDATA *buff;\n\t\t\t\tPOINT TopLeft;\n\n\t\t\t\t// Get the top-left point of the client area\n\t\t\t\tTopLeft.x = 0;\n\t\t\t\tTopLeft.y = 0;\n\t\t\t\tif (!ClientToScreen(hWnd, &TopLeft))\n\t\t\t\t\tbreak;\n\n\t\t\t\t// Get the size of buffer required\n\t\t\t\tbuffsize = GetRegionData(region, 0, 0);\n\t\t\t\tif (buffsize != 0)\n\t\t\t\t{\n\t\t\t\t\tbuff = (RGNDATA *) new BYTE [buffsize];\n\t\t\t\t\tif (buff == nullptr)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t// Now get the region data\n\t\t\t\t\tif(GetRegionData(region, buffsize, buff))\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (x=0; x<(buff->rdh.nCount); x++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Obtain the rectangles from the list\n\t\t\t\t\t\t\tRECT *urect = (RECT *) (((BYTE *) buff) + sizeof(RGNDATAHEADER) + (x * sizeof(RECT)));\n\t\t\t\t\t\t\tSendDeferredUpdateRect(\n\t\t\t\t\t\t\t\thWnd,\n\t\t\t\t\t\t\t\t(SHORT) (TopLeft.x + urect->left),\n\t\t\t\t\t\t\t\t(SHORT) (TopLeft.y + urect->top),\n\t\t\t\t\t\t\t\t(SHORT) (TopLeft.x + urect->right),\n\t\t\t\t\t\t\t\t(SHORT) (TopLeft.y + urect->bottom)\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tdelete [] buff;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Now free the region\n\t\t\tif (region != nullptr)\n\t\t\t\tDeleteObject(region);\n\t\t}\n    */\n  };\n}\n\nLRESULT CALLBACK HookCallWndProc(int nCode, WPARAM wParam, LPARAM lParam) {\n  if (nCode == HC_ACTION) {\n    CWPSTRUCT* info = (CWPSTRUCT*) lParam;\n    ProcessWindowMessage(info->message, info->hwnd, info->wParam, info->lParam);\n  }\n  return CallNextHookEx(hook_CallWndProc, nCode, wParam, lParam);\n}\n\nLRESULT CALLBACK HookCallWndProcRet(int nCode, WPARAM wParam, LPARAM lParam) {\n  if (nCode == HC_ACTION) {\n    CWPRETSTRUCT* info = (CWPRETSTRUCT*) lParam;\n    ProcessWindowMessage(info->message, info->hwnd, info->wParam, info->lParam);\n  }\n  return CallNextHookEx(hook_CallWndProcRet, nCode, wParam, lParam);\n}\n\nLRESULT CALLBACK HookGetMessage(int nCode, WPARAM wParam, LPARAM lParam) {\n  if (nCode == HC_ACTION) {\n    if (wParam & PM_REMOVE) {\n      MSG* msg = (MSG*) lParam;\n      ProcessWindowMessage(msg->message, msg->hwnd, msg->wParam, msg->lParam);\n    }\n  }\n  return CallNextHookEx(hook_GetMessage, nCode, wParam, lParam);\n}\n\nLRESULT CALLBACK HookDialogMessage(int nCode, WPARAM wParam, LPARAM lParam) {\n  if (nCode == HC_ACTION) {\n    MSG* msg = (MSG*) lParam;\n    ProcessWindowMessage(msg->message, msg->hwnd, msg->wParam, msg->lParam);\n  }\n  return CallNextHookEx(hook_DialogMessage, nCode, wParam, lParam);\n}\n\n// - WM_Hooks_Install\n\nBOOL WM_Hooks_Install(DWORD owner, DWORD thread) {\n  // - Are there already hooks set?\n  if (hook_owner) {\n    if (!PostThreadMessage(hook_owner, WM_HK_PingThread, 0, 0)) {\n      WM_Hooks_Remove(hook_owner);\n    } else {\n      return FALSE;\n    }\n  }\n\n  // - Initialise the hooks\n  hook_owner = owner;\n  hook_target = thread;\n\n  hook_CallWndProc = SetWindowsHookEx(WH_CALLWNDPROC, HookCallWndProc, dll_instance, thread);\n  hook_CallWndProcRet = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallWndProcRet, dll_instance, thread);\n  hook_GetMessage = SetWindowsHookEx(WH_GETMESSAGE, HookGetMessage, dll_instance, thread);\n  hook_DialogMessage = SetWindowsHookEx(WH_SYSMSGFILTER, HookDialogMessage, dll_instance, thread);\n\n  if (!hook_CallWndProc /*|| !hook_CallWndProcRet*/ || !hook_GetMessage || !hook_DialogMessage) {\n    WM_Hooks_Remove(owner);\n    return FALSE;\n  }\n\n  return TRUE;\n}\n\n// - WM_Hooks_Remove\n\nBOOL WM_Hooks_Remove(DWORD owner) {\n  if (owner != hook_owner) return FALSE;\n  if (hook_CallWndProc) {\n    UnhookWindowsHookEx(hook_CallWndProc);\n    hook_CallWndProc = nullptr;\n  }\n  if (hook_CallWndProcRet) {\n    UnhookWindowsHookEx(hook_CallWndProcRet);\n    hook_CallWndProcRet = nullptr;\n  }\n  if (hook_GetMessage) {\n    UnhookWindowsHookEx(hook_GetMessage);\n    hook_GetMessage = nullptr;\n  }\n  if (hook_DialogMessage) {\n    UnhookWindowsHookEx(hook_DialogMessage);\n    hook_DialogMessage = nullptr;\n  }\n  hook_owner = 0;\n  hook_target = 0;\n  return TRUE;\n}\n\n//\n// -=- User input hooks\n//\n\nHHOOK hook_keyboard SHARED = nullptr;\nHHOOK hook_pointer SHARED = nullptr;\nbool enable_real_ptr SHARED = true;\nbool enable_synth_ptr SHARED = true;\nbool enable_real_kbd SHARED = true;\nbool enable_synth_kbd SHARED = true;\n\n#ifdef WH_KEYBOARD_LL\nLRESULT CALLBACK HookKeyboardHook(int nCode, WPARAM wParam, LPARAM lParam) {\n  if (nCode >= 0) {\n    KBDLLHOOKSTRUCT* info = (KBDLLHOOKSTRUCT*) lParam;\n    bool real_event = (info->flags & LLKHF_INJECTED) == 0;\n    if ((real_event && !enable_real_kbd) ||\n      (!real_event && !enable_synth_kbd)) {\n      return 1;\n    }\n  }\n  return CallNextHookEx(hook_keyboard, nCode, wParam, lParam);\n}\n\nLRESULT CALLBACK HookPointerHook(int nCode, WPARAM wParam, LPARAM lParam) {\n  if (nCode >= 0) {\n    MSLLHOOKSTRUCT* info = (MSLLHOOKSTRUCT*) lParam;\n    bool real_event = (info->flags & LLMHF_INJECTED) == 0;\n    if ((real_event && !enable_real_ptr) ||\n      (!real_event && !enable_synth_ptr)) {\n      return 1;\n    }\n  }\n  return CallNextHookEx(hook_keyboard, nCode, wParam, lParam);\n}\n\nbool RefreshInputHooks() {\n  bool success = true;\n  bool set_ptr_hook = !enable_real_ptr || !enable_synth_ptr;\n  bool set_kbd_hook = !enable_real_kbd || !enable_synth_kbd;\n  if (hook_keyboard && !set_kbd_hook) {\n    UnhookWindowsHookEx(hook_keyboard);\n    hook_keyboard = nullptr;\n  }\n  if (hook_pointer && !set_ptr_hook) {\n    UnhookWindowsHookEx(hook_pointer);\n    hook_pointer = nullptr;\n  }\n  if (!hook_keyboard && set_kbd_hook) {\n    hook_keyboard = SetWindowsHookEx(WH_KEYBOARD_LL, HookKeyboardHook, dll_instance, 0);\n    if (!hook_keyboard) success = false;\n  }\n  if (!hook_pointer && set_ptr_hook) {\n    hook_pointer = SetWindowsHookEx(WH_MOUSE_LL, HookPointerHook, dll_instance, 0);\n    if (!hook_pointer) success = false;\n  }\n  return success;\n}\n#else\n#pragma message(\"  NOTE: low-level mouse and keyboard hooks not supported\")\n#endif\n\n// - WM_Hooks_EnableRealInputs\n\nBOOL WM_Hooks_EnableRealInputs(BOOL pointer, BOOL keyboard) {\n#ifdef WH_KEYBOARD_LL\n  enable_real_ptr = pointer!=0;\n  enable_real_kbd = keyboard!=0;\n  return RefreshInputHooks();\n#else\n  return FALSE;\n#endif\n}\n\n// - WM_Hooks_EnableSynthInputs\n\nBOOL WM_Hooks_EnableSynthInputs(BOOL pointer, BOOL keyboard) {\n#ifdef WH_KEYBOARD_LL\n  enable_synth_ptr = pointer!=0;\n  enable_synth_kbd = keyboard!=0;\n  return RefreshInputHooks();\n#else\n  return FALSE;\n#endif\n}\n\n// - WM_Hooks_EnableCursorShape\n\nBOOL WM_Hooks_EnableCursorShape(BOOL enable) {\n  enable_cursor_shape = enable;\n  return TRUE;\n}\n"
  },
  {
    "path": "win/wm_hooks/wm_hooks.h",
    "content": "/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.\n * \n * This is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n * \n * This software is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this software; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,\n * USA.\n */\n\n// -=- wm_hooks.h\n//\n// Window Message Hooks Dynamic Link library\n//\n// This interface is used by the WMHooks class in rfb_win32 to hook the\n// windows on the desktop and receive notifications of changes in their\n// state.\n\n#ifndef __WM_HOOKS_H__\n#define __WM_HOOKS_H__\n\n#include <windows.h>\n\n#define DLLEXPORT __declspec(dllexport)\n\nextern \"C\"\n{\n  //\n  // -=- Display hook message types\n  //\n\n  DLLEXPORT UINT WM_Hooks_WindowChanged();\n  DLLEXPORT UINT WM_Hooks_WindowBorderChanged();\n  DLLEXPORT UINT WM_Hooks_WindowClientAreaChanged();\n  DLLEXPORT UINT WM_Hooks_RectangleChanged();\n  DLLEXPORT UINT WM_Hooks_CursorChanged();\n\n  //\n  // -=- Display update hooks\n  //\n\n  // - WM_Hooks_Install\n  // Add the current thread to the list of threads that will receive\n  // notifications of changes to the display.\n  // If thread is NULL then the entire display will be hooked.\n  // If thread is !NULL and then the specified\n  // thread will be hooked.\n  // Each thread may only register one hook at a time.\n  // The call will fail (return FALSE) if the thread already has hooks\n  // set, or if the hooks cannot be set, or some other error occurs.\n\n  DLLEXPORT BOOL WM_Hooks_Install(DWORD owner, DWORD thread);\n\n  // - WM_Hooks_Remove\n  // Removes any hook set by the current thread.\n  // The return indicates whether anything went wrong removing the hooks,\n  // that might cause problems later.\n\n  DLLEXPORT BOOL WM_Hooks_Remove(DWORD owner);\n\n  //\n  // -=- User input hooks\n  //\n\n  // - WM_Hooks_EnableRealInputs\n  // If TRUE is passed, then \"real\" input is enabled, otherwise it is disabled.\n\n  DLLEXPORT BOOL WM_Hooks_EnableRealInputs(BOOL pointer, BOOL keyboard);\n\n  // - WM_Hooks_EnableSynthInputs\n  // If TRUE is passed, then synthetic inputs are enabled, otherwise disabled.\n\n  DLLEXPORT BOOL WM_Hooks_EnableSynthInputs(BOOL pointer, BOOL keyboard);\n\n  //\n  // -=- Cursor shape hooking\n  //\n\n  // - WM_Hooks_EnableCursorShape\n  // If TRUE is passed, then hooks will produce notifications when cursor shape\n  // changes.\n\n  DLLEXPORT BOOL WM_Hooks_EnableCursorShape(BOOL enable);\n\n#ifdef _DEBUG\n  // - WM_Hooks_SetDiagnosticRange\n  // Select a range of messages that will be reported while hooks are active\n  DLLEXPORT void WM_Hooks_SetDiagnosticRange(UINT min, UINT max);\n  DLLEXPORT UINT WM_Hooks_Diagnostic();\n#endif\n\n}\n\n#endif // __WM_HOOKS_H__\n"
  },
  {
    "path": "win/wm_hooks/wm_hooks.rc",
    "content": "//Microsoft Developer Studio generated resource script.\n//\n#include \"resource.h\"\n#include \"resdefs.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"windows.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// English (U.K.) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)\n#ifdef _WIN32\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK\n#pragma code_page(1252)\n#endif //_WIN32\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"#include \"\"windows.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE DISCARDABLE \nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n#ifndef _MAC\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION __RCVERSION\n PRODUCTVERSION __RCVERSION\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS 0x40004L\n FILETYPE 0x2L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"080904b0\"\n        BEGIN\n            VALUE \"Comments\", \"\\0\"\n            VALUE \"CompanyName\", \"TigerVNC team\\0\"\n            VALUE \"FileDescription\", \"TigerVNC server hooking DLL\\0\"\n            VALUE \"ProductName\", \"TigerVNC server hooking DLL\\0\"\n            VALUE \"FileVersion\", __RCVERSIONSTR\n            VALUE \"InternalName\", \"\\0\"\n            VALUE \"LegalCopyright\", \"Copyright (C) 1999-2026 TigerVNC team and many others (see README.rst)\\0\"\n            VALUE \"LegalTrademarks\", \"TigerVNC\\0\"\n            VALUE \"OriginalFilename\", \"wm_hooks.dll\\0\"\n            VALUE \"PrivateBuild\", \"\\0\"\n            VALUE \"ProductVersion\", __VERSIONSTR\n            VALUE \"SpecialBuild\", \"\\0\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x809, 1200\n    END\nEND\n\n#endif    // !_MAC\n\n#endif    // English (U.K.) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  }
]